/*===========================================================================
  Copyright (C) 1995-2010 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 C  +++++++++++++++++++++++++++++++
.LANGUAGE   C
.IDENTIFICATION Module CGNC
.COMMENTS
  holds  DISPFIL, EXTRSS, COPY, GETLIN, GETLINE, DATE
.AUTHOR  K. Banse	ESO - Garching
.KEYWORDS
  name translation, parsing, filling
.ENVIRONMENT VMS and UNIX

.VERSION [1.00]	920213: pulled over from cgna.c
 
 100616		last modif
-----------------------------------------------------------------------------*/

#include <fileexts.h>
#include <stdlib.h>
#include <stdio.h>

#define  READ  0
/*

*/ 
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  display part of a file
.ALGORITHM
  look for prefix//label
  the display until prefix//... is encountered
.RETURN
  stat:	I*4	= 0, if ok, else -1
--------------------------------------------------*/
 
#ifdef __STDC__
int CGN_DISPFIL(int color, char *file ,char *prefix ,char *label)

#else
int CGN_DISPFIL(color,file,prefix,label)
int    color;		/* IN:  color no. for string, like for SET/GRAPH:
				0 = default, i.e. no colour setting,
				1 = black, 2 = red, 3 = green,
				4 = blue, 5 = yellow, 6 = magenta,
				7 = cyan, 8 = white */
char   *file; 	  	/* IN : file name  */
char   *prefix;   	/* IN : prefix string */
char   *label;	  	/* IN : label string  */
#endif
 
{
int   reclen, jmm, jkk, fp, reto;
 
char	compo[32];
char	work[168];
 


reto = -1;				/* init to BAD */
 

/*  open file */
 
fp = CGN_OPEN(file,READ);
if (fp == -1) return (reto);
 
jmm = CGN_COPY(compo,prefix);
jkk = CGN_COPY(&compo[jmm],label) + jmm;	/* length of search string */
 
 
read_loop:
reclen = osaread(fp,work,80);

if (reclen == 0)
   goto read_loop;
else if (reclen == -1)
   goto end_of_it;

 
if (jmm == 0)
   {
   SCTPUT(work);
   reto = 0;
   goto read_loop;
   }


if (strncmp(work,compo,jkk) == 0) 
   {
   inner_loop:
   reclen = osaread(fp,work,80);

   if (reclen == 0) 
      goto inner_loop;
   else if ( (reclen == -1) || (strncmp(work,prefix,jmm) == 0) )
      goto end_of_it;

   SCTMES(color,work);			/* so we also log */
   reto = 0;
   goto inner_loop;
   }

goto read_loop;


end_of_it:
(void) osaclose(fp);
return (reto);
}
/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  get one line of a file
.ALGORITHM
  look for prefix//label
  then get the following line
.RETURN
  status = 0, if ok, else -1
--------------------------------------------------*/

#ifdef __STDC__
int CGN_GETLIN(char *file ,char *prefix ,char *label, char *line)

#else 
int CGN_GETLIN(file,prefix,label,line)
char   *file;		/* IN : file name  */
char   *prefix;		/* IN : prefix string */
char   *label;		/* IN : label string  */
char   *line;		/* OUT : buffer where the file record is copied to */
#endif

{
int   reclen, jmm, jkk, fp, reto;

char    compo[32], work[168];




reto = -1;


/*  open file */

fp = CGN_OPEN(file,READ);
if (fp == -1) return (reto);

jmm = CGN_COPY(compo,prefix);
jkk = CGN_COPY(&compo[jmm],label) + jmm;	/* length of search string */


read_loop:
reclen = osaread(fp,work,80);

if (reclen == 0)
   goto read_loop;
else if (reclen == -1)
   goto end_of_it;


if (jmm == 0)
   {
   (void) strcpy(line,work);
   reto = 0;
   goto end_of_it;
   }


if (strncmp(work,compo,jkk) == 0)
   {
inner_loop:
   reclen = osaread(fp,work,80);

   if (reclen == 0) 
      goto inner_loop;
   else if (reclen == -1) 
      goto end_of_it;

   (void) strcpy(line,work);
   reto = 0;
   goto end_of_it;
   }

goto read_loop;


end_of_it:
(void) osaclose(fp);
return (reto);
}
/*

*/
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  from a given string extract a substring limited by given delimiter
.ALGORITHM
  find the given delimiter in the string
  copy the relevant part into the substring
  spaces in front of delimiter are ignored
.RETURN
  -3 if input string only blanks
  -2 if extracted substring would be larger than `ssl' chars.
  -1 if end of main string reached,
   else the length of extracted substring
	if two consecutive delimiters => length = 0
------------------------------------------------------------------*/

#ifdef __STDC__
int CGN_EXTRSS(char *string, int lstring, char delim, int *start, char *ss,
               int ssl)
#else
int CGN_EXTRSS(string,lstring,delim,start,ss,ssl)
char  *string;		/* IN: character string which is to be parsed */
int  lstring;		/* IN: length of above */
char  delim;		/* IN: delimiter char. */
int  *start;		/* IO: starting index within the input 
	 		       string - will be set to the position 
			       just following the next delimiter  
			       upon return */
char  *ss;		/* OUT: extracted substring,
				will be set to null string if nothing there */
int  ssl;		/* IN: length of 'ss' */
#endif

{
int    backsl;
register int   slen, off, soss, mm, aapo, apo, bpo, eos;

register char  cc, sc, *cptr, *tptr;
 
 
 
*ss = '\0';				/* init substr `ss' to zero length */
mm = *start;   
if (lstring <= mm) return (-1);		/* already end of string reached */
 

/*  skip leading blanks  */
 
soss = mm;
while(1)
   {
   cc = string[soss];
   if (cc == '\0') 
      return (-3);		/* only blank string */
   else if (cc != ' ') 
      break;
   soss ++;
   }


eos = 1;
backsl = 0;				/* backslash flag */
aapo = 0;				/* start_with_quote flag */
apo = bpo = 0;				/* quote switches */


/*  skip over characters until we hit delimiter or end of string  */
 
off = soss;
while(1)
   {					/* 1st time: `cc' already set above */
   if (cc == delim)
      {
      if (apo == 0) goto done_it;
      }

   else if (cc == '\0')
      break;

   else if (cc == '"') 
      {
      if ((off > 0) && (string[off-1] == '\\'))
         backsl ++;
      else
         {					/* look at next char. */
         sc = string[off+1];

         if (aapo == 1)				/* we started with `"' */
            {
            if (sc == '\0')
               apo = 0;
            else if (sc == delim) 
               {				/* test for _____" in the end */
               bpo = 1 - bpo;

               if (bpo == 1)
                  apo = 0;			/* even no. of ", o.k. */
               else
                  {
                  register int  nr;
                  
                  nr = off + 2;
                  sc = string[nr];
                  while (sc == delim)
                     {
                     nr ++;
                     sc = string[nr];
                     }
                  if (sc == '"')		/* we found trailing blank */
                     {
                     sc = string[nr+1];
                     if (sc != '\0') apo = 0;
                     }
                  }
               }
            else if (sc != '"') 		/* otherwise, update switch */
               bpo = 1 - bpo;
            }

         else 
            {
            if (sc != '"') apo = 1 - apo;
            if (off == soss) aapo = 1;		/* indicate "... string */
            }
         }
      }
   cc = string[++off];
   }


/* no delimiter found or `apo' was 1 */

if (apo == 1)				/* uneven no. of quotes */
   {
   for (off=soss; ; off++)	/* pass through string again */
      {
      cc = string[off];
      if (cc == '\0')
         break;
      else if (cc == delim) 
         goto done_it;
      }
   }

eos = 0;	


/* yes, delimiter found */

done_it:
slen = off - soss;			/* length of substring */

if (slen > ssl) 			/* substring too long ... */
   {					/* copy only what's possible */
   if (backsl > 0)
      {
      if ((slen-backsl) < ssl) goto ok_end;

      tptr = ss;
      cptr = string + soss;
      for (mm=0; mm<ssl; mm++)
         {
         if ((*cptr == '\\') && (*(cptr+1) == '"'))
            cptr++;
         else
            *tptr++ = *cptr++;
         }
      }
   else
      (void) memcpy(ss,(string+soss),(size_t)ssl);
   return(-2);
   }



/* all o.k. - copy string  + update `start'  */

ok_end:
if (backsl > 0)
   {
   tptr = ss;
   cptr = string + soss;
   for (mm=0; mm<slen; mm++)
      {
      if ((*cptr == '\\') && (*(cptr+1) == '"'))
         cptr++;
      else
         *tptr++ = *cptr++;
      }
   slen -= backsl;		/* update length of extracted substring */
   *tptr = '\0';
   }
else
   {
   (void) memcpy(ss,(string+soss),(size_t)slen);
   ss[slen] = '\0';
   }
 
*start = off + eos;
return (slen);
}
/*

*/

int CGN_COPY(outstr,instr)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  copy char. strings + return no. of chars  copied (excluding the \0 )
.RETURN 
  no. of chars. copied (may be = 0)
--------------------------------------------------*/

char   *instr;       /* input string */
char   *outstr;      /* output string */

{
register char  cc, *base;



base = outstr;

while ((cc = *instr++)) *outstr++ = cc;

*outstr = '\0';
return ((int)(outstr-base));

}
/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
  check, if year is leap year

"Most years ending in "00" are not leap
years, but those divisible by 400 (including 2000)
are. The Julian calendar, authorized by Julius
Caesar in 46 B.C., assumed that the year had
365 1/4 days, with a 366-day leap year added
every fourth year.
     In A.D. 730, an Anglo-Saxon monk, the Venerable
Bede, calculated that the Julian year was 11 minutes
and 14 seconds too long, an error of about one day
every 128 years.  But nothing was done about it for
800 years. In 1582, the accumulated error was
estimated at 10 days, and Pope Gregory XIII decreed
that the day following Oct. 4 would be Oct. 15.
     To make future adjustments for the error
(about three days every 400 years), it was decided
that years ending in "00" would be common years rather
than leap years -- except those divisible by 400.
     So 1600 was a leap year and 2000 also will be,
but 1700, 1800 and 1900 were not."

.RETURN return 1 if leap year, else 0
--------------------------------------------------*/
 
#ifdef __STDC__
int leapyr(int year)

#else
int leapyr(year)
int  year;
#endif

{

if ( ( ((year%4) == 0) && ((year%100) != 0) ) ||
     ((year%400) == 0) )
   return 1;
else
   return 0;

}
/*

*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.KEYWORDS
  current date
.PURPOSE
  return current date from host system incremented by `daydiff'
.ALGORITHM
  get current date via OSY_ASCTIM and convert it
.RETURNS
  actual length of date string
--------------------------------------------------*/

#ifdef __STDC__
int CGN_DATE(int isoflag, int daydiff, char *s)

#else
int CGN_DATE(isoflag,daydiff,s)
int   isoflag;	/* IN: 0 -> get date as yyyy-mm-dd
		       1 -> get date as yyyy-mm-ddThh:mm:ss (ISO 8601) 
		            in this case `daydiff' is ignored...  */
int   daydiff;	/* IN: 0 -> get current date, else get date + daydiff */
char *s;	/* OUT: date string */
#endif

{
char  base[40], newbase[12], daysign;
register char  cc;

int  leng, adiff;
int  ibuf[3], iyear, imonth, iday;
static int modays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
register int  mr, nr;

float  rval;

double dval;




OSY_ASCTIM(base);
mr = CGN_INDEXC(base,' ');
CGN_strcpy(base,&base[mr+1]);


mr = 7;                                /* point to begin of year string */
for (nr=0; nr<4; nr++) newbase[nr] = base[mr++];

newbase[4] = '-';
newbase[5] = '0';
cc = base[3];

if (cc == 'J')
   {
   if (base[4] == 'a')
      newbase[6] = '1';                         /* January */
   else
      {
      if (base[5] == 'n')
         newbase[6] = '6';			/* June */
      else
         newbase[6] = '7';			/* July */
      }
   }
else if (cc == 'F')				/* February */
   newbase[6] = '2';
else if (cc == 'M')
   {
   if (base[5] == 'r')
      newbase[6] = '3';				/* March */
   else
      newbase[6] = '5';				/* May */
   }
else if (cc == 'A')
   {
   if (base[4] == 'p')
      newbase[6] = '4';				/* April */
   else
      newbase[6] = '8';				/* August */
   }
else if (cc == 'S')				/* September */
   newbase[6] = '9';
else if (cc == 'O')				/* October */
   {
   newbase[5] = '1';
   newbase[6] = '0';
   }
else if (cc == 'N')				/* November */
   {
   newbase[5] = '1';
   newbase[6] = '1';
   }
else						/* December */
   {
   newbase[5] = '1';
   newbase[6] = '2';
   }

newbase[7] = '-';
newbase[8] = base[0];
newbase[9] = base[1];
newbase[10] = '\0';


if (isoflag == 1)				/* ISO date only for today! */
   {
   newbase[10] = 'T';
   newbase[11] = '\0';
   leng = CGN_COPY(s,newbase);

   while(base[mr] == ' ') mr++;
   nr = CGN_COPY(s+leng,&base[mr]);
   leng += nr;
   return(leng);
   }

else if (daydiff == 0)
   {
   leng = CGN_COPY(s,newbase);
   return(leng);
   }


/* here the real work starts */

if (daydiff < 0)
   {
   daysign = '-';
   adiff = -daydiff;
   }
else
   {
   daysign = '+';
   adiff = daydiff;
   }


more_days:
if (daysign == '-')
   daydiff = -1;
else
   daydiff = 1;
adiff --;

(void) strcpy(base,newbase);
base[4] = ','; base[7] = ',';

(void) CGN_CNVT(base,1,3,ibuf,&rval,&dval);
iyear = ibuf[0]; imonth = ibuf[1]; iday = ibuf[2];


/* here we handle the one day difference */

if (daysign == '+')			/* tomorrow */
   {
   iday ++;				/* get day after */
   if (imonth != 2)			/* worry about February */
      nr = modays[imonth-1] + 1;	/* nr = last day + 1 */
   else
      {
      nr = leapyr(iyear);
      if (nr == 1)			/* leap year */
         nr = 30;
      else
         nr = 29;
      }
   if (iday < nr)			/* still in same month? */
      {
      (void) sprintf(&newbase[8],"%2.2d",iday);
      goto final_task;
      }
  
   imonth ++;                           /* get month after */
   if (imonth < 13)
      {
      (void) sprintf(&newbase[5],"%2.2d-01",imonth);
      goto final_task;
      }

   iyear ++;
   (void) sprintf(newbase,"%d-01-01",iyear);
   }

else					/* yesterday */
   {
   iday --;				/* get day before */
   if (iday > 0)
      {
      (void) sprintf(&newbase[8],"%2.2d",iday);
      goto final_task;
      }
   
   imonth --;				/* get month before */
   if (imonth > 0)
      {
      if (imonth != 2)			/* worry about February */
         (void) sprintf(&newbase[5],"%2.2d-%d",imonth,modays[imonth-1]);
      else
         {
         nr = leapyr(iyear);
         if (nr == 1)
            (void) strcpy(&newbase[5],"02-29");		/* leap year */
         else
            (void) strcpy(&newbase[5],"02-28");
         }
      goto final_task;
      }

   iyear --;
   (void) sprintf(newbase,"%d-12-31",iyear);
   }


final_task:
if (adiff > 0) goto more_days;

leng = CGN_COPY(s,newbase);
return(leng);
}
/*

*/
 
void CGN_GETLINE(s,lim)

/*++++++++++++++++++++++++++++++++++++++++++++++++++
.KEYWORDS
  terminal
.PURPOSE
  get an input line from the terminal
.ALGORITHM
  use C-function getchar
.RETURNS
  nothing
--------------------------------------------------*/

char s[];        /* OUT: input line from terminal  */
int  lim;        /* IN: max. length of input string  */

{
register int  nr;


lim --;
for (nr=0; nr<lim; nr++)
   {
   s[nr] = getchar();
   if ( (s[nr] == '\n') || (s[nr] == '\r') || (s[nr] == EOF) )
      {
      s[nr] = '\0';
      return;
      }
   }

if (lim < 0)			/* check for bad input value */
   s[0] = '\0';
else
   s[lim] = '\0';
}


