/*===========================================================================
  Copyright (C) 1988-2009 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENT         cdlist.c
.LANGUAGE      C
.AUTHOR        Preben Grosbol,  ESO/IPG
.KEYWORDS      decoding, list of numbers
.COMMENT       Routines for decoding and accessing list of numbers
               given as a MIDAS 'list'.
.VERSION       1.0    1988-Oct-11 : Creation,   PJG

 090706		last modif
------------------------------------------------------------------------*/

#define    MXLIST     64                /* max. no. of entries in list  */

static  int          lno = -1;          /* no.  to current list range   */
static  struct {                        /* structure with list of no's  */
                 int    first;          /* first no. in range           */
                 int     last;          /* last no. of in range         */
               } list[MXLIST];

int  deflist(plist)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE       decode string with MIDAS 'list' specification and initiate
               internal list structure.
.RETURN        status, 0: OK, -1:invalid list, 1: list too long
------------------------------------------------------------------------*/
char     *plist;                       /* pointer to list specification */
{
  char   c;
  int    l,ldig,n;

  lno = -1;
  for (n=0; n<MXLIST; n++) list[n].first = -1;  /* reset internal list  */

  if (*plist == '*') {                          /* check special cases  */
     if (*(++plist)) return -1;
     list[0].first = 1; list[0].last = 9999;
     lno = 0; return 0;
  }

  n = 0; l = 0; ldig = 0;
  while ((c = *plist++) && c!=' ') {            /* go through list      */
    if (c == ',' && ldig) {
       if (list[l].first<0) list[l].first = n;
       list[l].last = (n<list[l].first) ? list[l].first : n;
       l++;
       if (MXLIST<=l) { lno = 0; return 1; }
    }
    else if (c == '-' && ldig) list[l].first = n;
    else if (c == '.' && ldig) {
            if ((*plist++ != '.')) return -1;
            list[l].first = n;
    }
    else if (c<'0' || '9'<c) return -1;

    ldig = (('0' <= c) && (c <= '9')); 
    if (ldig)
       n = 10 * n + (c - '0');
    else 
       n = 0;
  }
  if (ldig) {
     if (list[l].first<0) list[l].first = n;
     list[l].last = (n<list[l].first) ? list[l].first : n;
   }
   else return -1;

  lno = 0;
  return 0;
}

int getlist(pno)
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE       get next no. in list previously defined. The no. is
               return through the parameter.
.RETURN        status, 1:valid no., 0:no number return
------------------------------------------------------------------------*/
int        *pno;               /* pointer to var. with next no. in list */
{
  if (lno<0) return 0;                   /* return if list empty        */
  if (list[lno].first<0) {
     lno = -1; return 0;
  }

  *pno = list[lno].first++;                  /* get next no. in list    */
  if (list[lno].last<list[lno].first) {      /* check if range finished */
     list[lno++].first = -1;
     if (MXLIST<=lno) lno = -1;
  }      
     
  return 1;
}
