/*===========================================================================
  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
===========================================================================*/

/*+++++++++++++++++++ CGN interfaces part D  +++++++++++++++++++++++++++++++
.LANGUAGE   C
.IDENTIFICATION Module cgnd.c
.COMMENTS
  holds  CGN_INDEXK, _JNDEXC, _JNDEXS, _CNVT, _xCNVT, _EXIST, _IBUILD
.AUTHOR  K. Banse	ESO - Garching
.KEYWORDS
  name translation, parsing, filling
.ENVIRONMENT VMS and UNIX

.VERSION

 090326		last modif
-----------------------------------------------------------------------------*/

#include <stdio.h>

#include <fileexts.h>

#if vms
#else

#include <sys/types.h>
#include <dirent.h>

static int  nofiles = -1;

#endif
/*

*/

#ifdef __STDC__
int CGN_INDEXK(char * s , char t , int count)
#else
int CGN_INDEXK(s,t,count)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 returns position of single character in input string
.RETURN
 returns position of single character in input string, -1 if not there
--------------------------------------------------*/
char *s;	/* IN: input string  */
char t;      	/* IN: test character */
int count;	/* IN: counter  */
#endif 

{
register int i;

register char  cc;

 
for (i=0; i<count; i++)
   {
   cc = s[i];
   if (cc == t)
      return (i);
   else if (cc == '\0')
      return (-2-i);
   }
 
return (-1);
}
/*

*/

#ifdef __STDC__
int CGN_JNDEXC(char * s , char t)
#else
int CGN_JNDEXC(s,t)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 returns position of single character in input string, running backwards
.RETURN
 returns position of single character in input string, -1 if not there
--------------------------------------------------*/

char *s;    /* input string  */
char t;     /* test character */
#endif

{
int  i;
register int   nr;

register char  cc;


i = -1;
nr = -1;

while (nr > -2)				/* it is assumed, that t != '\0' !! */
   {
   cc = s[++nr];
   if (cc == t)
      i = nr;
   else if (cc == '\0')
      return (i);			/* return last index found */
   }

return (-99);
}
/*

*/

#ifdef __STDC__
int CGN_JNDEXS(char * s , char * t)
#else
int CGN_JNDEXS(s,t)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 returns position of substring in input string, running backwards
.RETURN
 returns position of substring in input string, -1 if not there
--------------------------------------------------*/
char *s;    /* input string  */
char *t;    /* substring */
#endif

{
register int i, j, k, kstrn;


kstrn = (int)strlen(s) - (int)strlen(t);

for (i=kstrn; i >= 0; i--)
   {
   for (j=i,k=0; (t[k] != '\0') && (s[j] == t[k]); j++,k++)
      ;
   if (t[k] == '\0')
      return (i);
   }
 
return (-1);			/* substring not found */
}
/*

*/

int CGN_CNVT(line,type,maxval,ibuf,rbuf,dbuf)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  parse an input line of max. 80 char. and store max. 40 values in integer,
  real or double precision buffer
.ALGORITHM
  use C-functions atoi + atof for the actual conversion
  the actual no. of values, 'actval' is returned as the function return value
  if input line is empty, 'actval' = 0
  if input line contains non-numeric characters, 'actval' < 0
.RETURN
  actval:	I*4		actual no. of values in input string
				if < 0, something wrong in input string
--------------------------------------------------*/
 
char   *line;   /* IN : input line (terminated by \0 )  */
int   type;	/* IN : = 1, for decimal integer
		        = 2, for real;
		        = 3, for hex. integer;
		        = 4, for double prec. */
int   maxval;  /* IN : maximal no. of output values */
int   *ibuf;   /* OUT: integer output buffer */
float  *rbuf;   /* OUT: real output buffer */
double *dbuf;   /* OUT: double precision output buffer */
 
{
int   ic, start, slen, mytype, ml;
register int   kr, ir;

float   rr;

char	*wp, work[84];

double  dbldum;




start = 0;
ml = (int)strlen(line);
mytype = type;
wp = work;
 

/*  extract substrings from input buffer and use `sscanf' for conversion  */

for (ir=0; ir<maxval; ir++)
   {
   slen = CGN_EXTRSS(line,ml,',',&start,wp,80);
   if (slen < 1) return (ir);
 
   if ((*wp == '0') && (*(wp+1) == 'x')) 	/* check for hex input */
      {
      mytype = 3;
      wp += 2;
      }

                                  /*  decimal integer type  */
   if (mytype == 1)
      {
      ic = CGN_INDEXC(wp,'.');
      if (ic < 0) 
         ic = sscanf(wp,"%d",&ibuf[ir]);
      else
         {
         ic = sscanf(wp,"%e",&rr);		/* needed for 2.0E+1 */
         ibuf[ir] = (int) rr;
         }
      }	

                                  /*  float type  */
   else if (mytype == 2)
      {
      ic = sscanf(wp,"%le",&dbldum);
      if (ic == 1) rbuf[ir] = (float) dbldum;
      }

                                  /*  hex. integer type  */
   else if (mytype == 3)
      {
      int  myint;

      ic = sscanf(wp,"%x",&myint);
      if (ic != 1) return (-1);

      if (type == 2)
         rbuf[ir] = (float) myint;
      else if (type == 4)
         dbuf[ir] = (double) myint;
      else 
         ibuf[ir] = myint;

      wp = work;
      mytype = type;		/* reset `wp' and `mytype' */
      }

                                  /*  double type  */
   else if (mytype == 4) 
      {				    /* also type = 3 is treated as double... */
      for (kr=0; kr<slen; kr++)
         {
         if ( (work[kr] == 'D') || (work[kr] == 'd') )
            {
            work[kr] = 'e';
            break;
            }
         }

      ic = sscanf(wp,"%le",&dbuf[ir]);
      }	
 

   else
      return (-2);


   if (ic != 1) return (-1);
   }
 
return maxval;
}
/*

*/

#ifdef __STDC__
int CGN_EXIST(int flag, char *dirname, char *pattrn, char *file_buff)
#else
int CGN_EXIST(flag,dirname,pattrn,file_buff)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 check if a filename matching the `pattrn' exists in given directory
 on subsequent calls return full filenames (128 chars long at most)
.RETURN
 returns no. of files which match the pattern in given directory
 or
 just 0/-1
--------------------------------------------------*/

int  flag;			/* IN: = 0 -> only return no. of matching names
				       = 1 -> return matching names one after
                                              the other in `file_buff' */
char *dirname;			/* IN: directory where to look */
char *pattrn;			/* IN: pattern to match, e.g. abc*.bdf  */
char *file_buff;		/* OUT: matching filename (max 128 chars) */
#endif


{
#if vms
return (-1);
#else


/* we want only the no. of files matching the pattern */

if (flag == 0)
   {
   if (nofiles > -1) oslclose();

   nofiles = oslopen(dirname,pattrn);

   if (nofiles < 0)
      nofiles = -1;			/* problems with directory */

   else if (nofiles == 0)
      {
      (void) oslclose();
      nofiles = -1;
      return (0);
      }					/* no matching file found */

   return (nofiles);
   }


/* now we want the file names matching the pattern */

else
   {
   struct dirent  *dirp, *oslread();

   if (nofiles > 0)
      {
      dirp = oslread();
      (void) strcpy(file_buff,dirp->d_name);	/* get file name */
      nofiles --;
      return (1);
      } 

   else if (nofiles == 0)
      {
      (void) oslclose();
      nofiles = -1;
      return (0);
      }

   else 
      return (-1);
   }

#endif
}
/*

*/

#ifdef __STDC__
int CGN_IBUILD(int simno, char *name, int datform, int sizze, 
               int *imno, int *cloned) 
#else
int CGN_IBUILD(simno,name,datform,sizze,imno,cloned)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 using as source an opened image, create a new image with size `size' 
 and data format `datform'
 either all descriptors of the source image are cloned to the new image,
 or just the standard descriptors are copied to the new image
 (the rest will have to be copied later...)
.RETURN
 0 if successful, else Midas error code
--------------------------------------------------*/

int  simno;	/* IN: id of source image */
char *name;	/* IN: name of new image */
int  datform;	/* IN: format for new image, e.g. D_R4_FORMAT */
int  sizze;	/* IN: no. of pixel of new image */
int *imno;	/* OUT: id of new image */
int *cloned;	/* OUT: cloned_flag, 1 = yes; 0 = no descr cloning done */
#endif

{
int  uni, nulo, iav, dsc_format, stat;
int  optflg[2];




/* check, if cloning is possible */

dsc_format = 456;			/* default to new descr. format */
(void) SCKRDI("AUX_MODE",10,1,&iav,&dsc_format,&uni,&nulo);

if (dsc_format == 123)
   stat = 0;				/* no cloning with old descr. format */
else
   stat = MID_TDCLON(simno,datform,sizze);	/* check header of source */

if (stat == 1)
   {					/* Yes. */
   optflg[0] = 1;			/* clone all descriptors of source */
   optflg[1] = simno;
   stat = SCFXCR(name,datform,F_O_MODE,F_IMA_TYPE,sizze,optflg,imno);
   *cloned = 1;
   }
else
   {
   optflg[0] = 0;			/* just create new image */
   stat = SCFXCR(name,datform,F_O_MODE,F_IMA_TYPE,sizze,optflg,imno);
   if (stat == ERR_NORMAL)
      stat = SCDCOP(simno,*imno,2,"  ");	/* only copy standard descr's */
   *cloned = 0;
   }

return stat;
}
/*

*/

int CGN_xCNVT(line,type,maxval,ibuf,rbuf,dbuf,sbuf)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  parse an input line of max. 80 char. and store max. 40 values in integer,
  real or double precision buffer
.ALGORITHM
  use C-functions atoi + atof for the actual conversion
  the actual no. of values, 'actval' is returned as the function return value
  if input line is empty, 'actval' = 0
  if input line contains non-numeric characters, 'actval' < 0
.RETURN
  actval:	I*4		actual no. of values in input string
				if < 0, something wrong in input string
--------------------------------------------------*/
 
char   *line;   /* IN : input line (terminated by \0 )  */
int   type;	/* IN : = 1, for decimal integer
		        = 2, for real;
		        = 3, for hex. integer;
		        = 4, for double prec. 
			= 5, for size_t */
int   maxval;  /* IN : maximal no. of output values */
int   *ibuf;   /* OUT: integer output buffer */
float  *rbuf;   /* OUT: real output buffer */
double *dbuf;   /* OUT: double precision output buffer */
size_t *sbuf;   /* OUT: size_t output buffer */
 
{
int   ic, start, slen, mytype, ml;
register int   kr, ir;

float   rr;

char	*wp, work[84];

double  dbldum;




start = 0;
ml = (int)strlen(line);
mytype = type;
wp = work;
 

/*  extract substrings from input buffer and use `sscanf' for conversion  */

for (ir=0; ir<maxval; ir++)
   {
   slen = CGN_EXTRSS(line,ml,',',&start,wp,80);
   if (slen < 1) return (ir);
 
   if ((*wp == '0') && (*(wp+1) == 'x')) 	/* check for hex input */
      {
      mytype = 3;
      wp += 2;
      }

                                  /*  decimal integer type  */
   if (mytype == 1)
      {
      ic = CGN_INDEXC(wp,'.');
      if (ic < 0) 
         ic = sscanf(wp,"%d",&ibuf[ir]);
      else
         {
         ic = sscanf(wp,"%e",&rr);		/* needed for 2.0E+1 */
         ibuf[ir] = (int) rr;
         }
      }	

                                  /*  float type  */
   else if (mytype == 2)
      {
      ic = sscanf(wp,"%le",&dbldum);
      if (ic == 1) rbuf[ir] = (float) dbldum;
      }

                                  /*  hex. integer type  */
   else if (mytype == 3)
      {
      int  myint;

      ic = sscanf(wp,"%x",&myint);
      if (ic != 1) return (-1);

      if (type == 2)
         rbuf[ir] = (float) myint;
      else if (type == 4)
         dbuf[ir] = (double) myint;
      else 
         ibuf[ir] = myint;

      wp = work;
      mytype = type;		/* reset `wp' and `mytype' */
      }

                                  /*  double type  */
   else if (mytype == 4) 
      {				    /* also type = 3 is treated as double... */
      for (kr=0; kr<slen; kr++)
         {
         if ( (work[kr] == 'D') || (work[kr] == 'd') )
            {
            work[kr] = 'e';
            break;
            }
         }

      ic = sscanf(wp,"%le",&dbuf[ir]);
      }	
 
                                  /*  size_t type  */
   else if (mytype == 5)
      {
      ic = sscanf(wp,"%zd",&sbuf[ir]);
      }

   else
      return (-2);


   if (ic != 1) return (-1);
   }
 
return maxval;
}

