/*===========================================================================
  Copyright (C) 1995-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
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENTifer   USRINP
.AUTHOR      R.M. van Hees IPG-ESO Garching
.KEYWORDS    low level plot routine
.LANGUAGE    C
.PURPOSE     Decode a character string into an array
              allowed types of values are i(nt), l(ong), f(loat) and d(ouble)
        input: char type     requested type of array elements in cbuff
               char *string  character string
               int  maxval   maximum number of elements in the output array
       output: char *cbuff   character pointer to a pointer of requested type
               int  *nrval   actuel number of values found
.RETURNS     status (=0 ok)
.COMMENTS    The input string has to contain values separated by "," or ":".
             The values in the output array are converted to the requested type
             Thus  type = 'f'          returns - char pointer to 1.0 4.0 8.0
                   string = "1,4,8"            - nrval = 3

                   type = 'f' or 'd'
                   string = ".6:3:.4" --> 0.6 1.0 1.4 1.8 2.2 2.6 3.0.
                                          nrval = 7
                   if type = 'i', 'l' --> 1 1 1 2 2 3 3   (!)
.ENVIRONment MIDAS
             #include <midas_def.h>     Prototypes for MIDAS interfaces
             #include <plot_def.h>      Symbols used by the PLT interfaces


.VERSION     1.1     23-Mar-1994   Updated the documentation  RvH

 090630		last modif
------------------------------------------------------------*/
/*
 * Define _POSIX_SOURCE to indicate
 * that this is a POSIX program
 */
#define  _POSIX_SOURCE 1

/*
 * definition of the used functions in this module
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>


/*
 * define some macros and constants
 */
#include <midas_def.h>
#include <plot_def.h>

#undef  FATAL
#define FATAL           1

/*
 * here start the code of the function
 */
#ifdef __STDC__
      int  USRINP(char type, char *string, int maxval, char *cbuff, int *nrval)
#else
     int USRINP( type, string, maxval, cbuff, nrval )
     char type, *string, *cbuff;
     int  maxval, *nrval;
#endif
{
int    ii, ierr, nr, nrstep, slen, *ibuff, imval[3];
long   *lbuff, lmval[3];
float  *fbuff;
double *dbuff, dmval[3];
char   *dummy, *pntr, *pntcm, *pnt2d, *cval, *cmval[3];

char *err_type = "*** FATAL: type = i(nt), l(ong), f(loat) or d(ouble)",
     *err_nrc  = "*** WARNING: USRINP, you have requested more values than can be stored",
     *err_inp  = "*** FATAL: syntax error in the INPUT string";

/*
 * initialisation
 */
*nrval = 0;
ierr = ERR_NORMAL;
dbuff = (double *) 0;
fbuff = (float *) 0;
ibuff = (int *) 0;
lbuff = (long *) 0;

/*
 * remove trailing blanks from the input string, and save the input string
 */
pntr = string;
(void) strtok( string, " " ); 
slen = (int) strlen( string );
dummy = osmmget( slen + 1 );
(void) strcpy ( dummy, string );

/*
 * allocate memory for local character strings
 */
cval = osmmget(21);
for ( ii = 0; ii < 3; ii++ ) cmval[ii] = osmmget(21);

/*
 * allocate memory for requested type of values
 */
switch( (int) type )
   { case 'i': case 'I':
         ibuff = (int *) cbuff;
         break;
     case 'l': case 'L': 
         lbuff = (long *) cbuff;
         break;
     case 'r': case 'R': case 'f': case 'F': 
         fbuff = (float *) cbuff;
         break;
     case 'd': case 'D': 
         dbuff = (double *) cbuff;
         break;
     default :
         SCTPUT( err_type );
         ierr = FATAL;
    }

while( strlen( string ) > (size_t) 0 && *nrval < maxval && ierr == ERR_NORMAL )
   { nr = 0;
     pntcm = strchr( string, ',' );
     pnt2d = strchr( string, ':' );
/*
 * does the string contain zero or more characters and no "," or ":" ?
 *   or does it contain a "," before a ":" ?
 */
     if ( pnt2d == NULL || ( pntcm != NULL && pntcm < pnt2d ))
        { if ( pntcm == NULL )
             { (void) strcpy( cval, string );
               *string = '\0';
             }
          else
             { (void) strncpy( cval, string, (pntcm - string) );
               *(cval+(pntcm - string)) = '\0';
               string = pntcm + 1;
             }
          switch( (int) type )
             { case 'i': case 'I':
                   *(ibuff + *nrval) = atoi( cval );
                   break;
               case 'l': case 'L': 
                   *(lbuff + *nrval) = atol( cval );
                   break;
               case 'r': case 'R': case 'f': case 'F': 
                   *(fbuff + *nrval) = (float) atof( cval );
                   break;
               case 'd': case 'D': 
                   *(dbuff + *nrval) = atof( cval );
                   break;
             }
          (*nrval)++;
        }
/*
 * it contains a ":" before a "," !
 */
     else
        { (void) strncpy(cmval[nr], string, (pnt2d - string)); /*store CSTART*/
          *(cmval[nr++]+(pnt2d - string)) = '\0';
          string = pnt2d + 1;
          pnt2d = strchr( string, ':' );
/*
 * there are two cases after a:b:c there is no futher input: pntcm == NULL
 * or there is more something like a:b:c,d...
 */
          if ( pntcm == NULL )
             { if ( pnt2d != NULL )                                /*get CEND*/
                  { (void) strncpy( cmval[nr], string, (pnt2d - string) );
                    *(cmval[nr++]+(pnt2d - string)) = '\0';
                    string = pnt2d + 1;
                    pnt2d = strchr( string, ':' );
                    if ( pnt2d == NULL )
                       { (void) strcpy( cmval[nr], string );    /*store CINCR*/
                         *string = '\0';
                       }
                    else                            /*wrong syntax a:b:c:d...*/
                       { ierr = FATAL;
                         SCTPUT( err_inp );
                        }
                  }
               else                                        /*wrong syntax a:b*/
                  { ierr = FATAL;
                    SCTPUT( err_inp );
                  }
             }
/*
 * the string still contains a "," 
 */
          else 
             { if ( pnt2d != NULL && pnt2d < pntcm )               /*get CEND*/
                  { (void) strncpy( cmval[nr], string, (pnt2d - string) );
                    *(cmval[nr++]+(pnt2d - string)) = '\0';
                    string = pnt2d + 1;
                    pnt2d = strchr( string, ':' );
                  }
               else                                   /*wrong syntax a:b,c...*/
                  { ierr = FATAL;
                    SCTPUT( err_inp );
                  }
               if ( pnt2d != NULL && pnt2d < pntcm ) /*wrong syntax a:b:c:d,.*/
                  { ierr = FATAL;
                    SCTPUT( err_inp );
                  }
               else                                               /*get CINCR*/
                  { (void) strncpy( cmval[nr], string, (pntcm - string) );
                    *(cmval[nr]+(pntcm - string)) = '\0';
                    string = pntcm + 1;
                  }
             }
          if ( ierr == ERR_NORMAL )
             { switch( (int) type )
                  { case 'i': case 'I':
                        for ( ii = 0; ii < 3; ii++ )
                            imval[ii] = atoi( cmval[ii] );
                        if ( imval[2] == 0 ) imval[2]++;
                        if ( imval[0] > imval[1] && imval[2] > 0 ) 
                             imval[2] *= -1;
                        nrstep = NSTEP( (double) imval[0], (double) imval[1],
                                                           (double) imval[2] );

                        if ( nrstep + *nrval > maxval )
                           { SCTPUT( err_nrc );
                             nrstep = maxval;
                           }

                        for ( ii = 0; ii < nrstep; ii++ )
                            { *(ibuff + *nrval) = imval[0] + ii * imval[2];
                              (*nrval)++;
                            }
                        break;
                    case 'l': case 'L': 
                        for ( ii = 0; ii < 3; ii++ )
                            lmval[ii] = atol( cmval[ii] );
                        if ( lmval[2] == 0 ) lmval[2]++;
                        if ( lmval[0] > lmval[1] && lmval[2] > 0 ) 
                           lmval[2] *= -1;
                        nrstep = NSTEP( (double) lmval[0], (double) lmval[1],
                                                           (double) lmval[2]);
                        if ( nrstep + *nrval > maxval )
                           { SCTPUT( err_nrc );
                             nrstep = maxval;
                           }

                        for ( ii = 0; ii < nrstep; ii++ )
                            { *(lbuff + *nrval) = lmval[0] + ii * lmval[2];
                              (*nrval)++;
                            }
                        break;
                    default :
                        for ( ii = 0; ii < 3; ii++ )
                            dmval[ii] = atof( cmval[ii] );
                        if ( dmval[2] == 0 ) dmval[2] += 1.0;;
                        if ( dmval[0] > dmval[1] && dmval[2] > 0 ) 
                           dmval[2] *= -1;
                        nrstep = NSTEP( dmval[0], dmval[1], dmval[2]);

                        if ( nrstep + *nrval > maxval )
                           { SCTPUT( err_nrc );
                             nrstep = maxval;
                           }

                        if ( type == 'd' || type == 'D' )
                           { for ( ii = 0; ii < nrstep; ii++ )
                                 { *(dbuff+ *nrval) = dmval[0] + ii * dmval[2];
                                   (*nrval)++;
                                 }
                           }
                        else
                           { for ( ii = 0; ii < nrstep; ii++ )
                                 { *(fbuff+ *nrval) = (float) 
                                                    (dmval[0] + ii * dmval[2]);
                                   (*nrval)++;
                                 }
                           }
                        break;
                  }
             }
        }
   }
/*
 * restore the input string
 */
string = pntr;
(void) strcpy( string, dummy );

/*
 * free allocated memory
 */
(void) osmmfree( (char *) cval );
(void) osmmfree( (char *) dummy );
(void) osmmfree( (char *) cmval[0] );
(void) osmmfree( (char *) cmval[1] );
(void) osmmfree( (char *) cmval[2] );

return ierr;
}

