/*===========================================================================
  Copyright (C) 1995-2011 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      fitsrkw.c
.LAUGUAGE   C
.AUTHOR     P.Grosbol   ESO/IPG
.KEYWORDS   FITS, decode, keyword
.COMMENT    decode a keyword line in a FITS header
.VERSION    1.0  1988-Dec-10 : Creation,   PJG 
.VERSION    1.1  1990-Jan-02 : Decode hierarchical keywords, PJG 
.VERSION    1.2  1990-Jul-14 : Include small arrays of numbers, PJG 
.VERSION    1.3  1990-Oct-02 : Correct check for COMMENT, PJG 
.VERSION    1.4  1991-Jan-10 : Correct error in hierarch check, PJG 
.VERSION    1.5  1991-Jan-25 : Change include file, PJG 
.VERSION    1.6  1991-Mar-22 : Correct error in 'idx' count, PJG 
.VERSION    1.7  1992-Feb-13 : Define END as comment + correct error, PJG 
.VERSION    1.8  1993-Jul-05 : Correct count error for comment, PJG 
.VERSION    1.9  1993-Sep-03 : Improve hierach kw check, PJG 
.VERSION    2.0  1993-Sep-17 : Change test at end of card, PJG 
.VERSION    2.1  1993-Oct-12 : Save comment when line[8]!='=', PJG 

 110906		last modif
-----------------------------------------------------------------------*/

#include   <fitsfmt.h>
#include   <fitsdef.h>
#include   <stdlib.h>
#include   <stdio.h>
#include   <string.h>
#include   <computer.h>



static char  cdif = 'A' - 'a';
 
static char *ckw[] = {"HISTORY ",     /* define COMMENT Keywords  */
                      "COMMENT ",
                      "END     ",
                      "        ",(char *) 0
                      };

extern int SCTPUT();


/*

*/

int fitsrkw(line,kw,unsig32)
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE       Decode keyword in FITS header
.RETURN        status 0:OK, -1:Illegal keyword syntax
-----------------------------------------------------------------------*/
char      *line;                /* pointer to start of keyword    */
KWORD     *kw;                  /* pointer to keyword structure   */
int       *unsig32;		/* = 1 if unsigned 32bit integers,
				   = 0 otherwise                  */


{
char       *pc, *wpntr;
register char  c;

int        idx, n, no, i;

double     d;

char  *ccc;



/* initiate KWORD structure etc.  */

kw->hkw[0] = (char *) 0; kw->hkn = 0; kw->kvn = 0;
kw->buf[0] = kw->hkb[0] = '\0';
d = kw->val.d[0] = 0.0;
i = no = 0; 
*unsig32 = 0;


for (n=0; n<8; n++)
   {				/* check and transfer prime keyword  */
   c = *line++; 
   if (' ' > c) 	 	/* check string so far */
      {
      if ((n > 3) && (strncmp(kw->kw,"END",3) == 0))
         {				/* correct screwed up END keyword */
         (void) strcpy(kw->kw,"END     ");
         goto comp_done;
         }
      else
         return (-1);			/* illegal character     */
      }
   if (('0' <= c) && (c <= '9'))
      {					/* number - decode it !  */
      no++;
      i = 10*i + (c-'0');
      }
   else if (c != ' ') 
      {
      i = no = 0;
      }

   kw->kw[n] = ('a'<=c && c<='z') ? c+cdif : c;	 
   }

comp_done:
idx = 8;
kw->kw[8] = '\0';
kw->kno = i;				/* keyword index         */
kw->pcom = (char *) 0; 
kw->fmt = '?';


/* check for COMMENT like records (stored in ckw array) */

n = 0;        
while (ckw[n] && strcmp(kw->kw,ckw[n])) n++;
if (ckw[n]) kw->fmt = 'C';


if (kw->fmt == 'C')
   {
   if (n == 2)
      kw->val.pc = (char *) 0; 
   else
      {
      n = 72;                         /* here idx = 8, so 80 - idx = 72 */
      (void) memcpy(kw->buf,line,(size_t)n);  /* save full comment part */

      kw->buf[n] = '\0';
      while (n-- && kw->buf[n] == ' ') kw->buf[n] = '\0';  /* trailing blanks */
      n = 0;
      while (kw->buf[n]==' ') n++;			   /* leading blanks */
      kw->val.pc = &(kw->buf[n]);
      }
   return 0;	
   }


/* check for hierarchical keywords */

if (*line != '=' ) 		/* should be hierarchical keyword */
   {			
   if (strcmp("CONTINUE",kw->kw) == 0)	
      goto usual_keyword;

   i = idx; pc = line; n = no = 0;

   while (i++<80)
       kw->buf[n++] = ((c = *pc++)<' ' || '~'<c) ? ' ' : c;
   kw->buf[n] = '\0';
   while (n-- && kw->buf[n] == ' ') kw->buf[n] = '\0';
   n++;
   kw->pcom = kw->buf;

   i = idx; pc = line;
   do 
      {                                  /* search for hierarch. kw  */
      while (i<80 && *pc==' ') pc++, i++;

      if (80<=i || *pc<'A' || 'z'<*pc || ('Z'<*pc && *pc<'a'))
         {
         if (*pc != '=') kw->hkn = 0;
         break;
         }
    
      kw->hkw[kw->hkn++] = &(kw->hkb[no]);
      while (i<80 && *pc!=' ' && *pc!='/' && *pc!='=') 
         {
         c = (*pc<' ' || '~'<*pc) ? '_' : *pc;
         kw->hkb[no++] = ('a'<=c && c<='z') ? c+cdif : c;
         i++; pc++;
         }
      kw->hkb[no++] = '\0';

      } while (((i<80) && (kw->hkn<MXHKW)));


   if ( !kw->hkn )    		  /* no hierarch. keyword found! */
      {
      char   txt[80];

      kw->hkw[0] = (char *) 0; kw->hkn = 0;
      kw->fmt = 'C';
      n = 0;
      while (kw->buf[n]==' ') n++; 
      kw->val.pc = &(kw->buf[n]);
      sprintf(txt,
              "Warning: No comment nor hierarch keyword - >%s< !",kw->kw);
      SCTPUT(txt);
      return 0;
      }

   idx = i; line = pc; i = 0; 
   pc = kw->hkw[kw->hkn-1];
   while ((c = *pc++)) 		/* for last member decode number */
      {
      if ('0'<=c && c<='9') 
         i = 10*i + (c-'0');
      else if (c!=' ')
         i = 0;
      }
   kw->kno = i;
   }

usual_keyword:
ccc = line;
idx++; line++;                               /* decode keyword value */
while (*line == ' ')
   {                         /* first char in value  */
   if (79 < idx++) return (-1);
   line++;
   }

if ((c = *line) == '\'') 
   {					/* determine type of parameter */
   kw->fmt = 'S';				/* character string */
   line++; 
   kw->val.pc = wpntr = kw->buf;
   while (++idx < 80 && *line!='\'') *wpntr++ = *line++; 
   *wpntr = '\0';
   }
else if	( ('0'<=c && c<='9') || (c=='+') || (c=='-') || (c=='.') ||
	  (c=='e') || (c=='E') || (c=='d') || (c=='D') )
   {					/* numeric value    */
   n = getval(line,80-idx,&i,&d);
   while (n--) idx++, line++;
   while (idx<80 && *line==' ') idx++, line++;

   /* check, if larger than biggest int (BZERO), with unsigned 32bit ints */

   if (i && *line!=',') 
      {
      if ((d < MAXINT) && (d > MININT))
         { 
         kw->val.i = d; kw->fmt = 'I'; kw->kvn = 1; 
         }
      else
         { 
         kw->val.d[0] = d; kw->fmt = 'R'; kw->kvn = 1; 
         *unsig32 = 1;
/*
n = d;
printf("unsig32 = %d for kw = %8.8s]\n",*unsig32,kw->kw);
printf("val.i = %d, d = %lf\n",n,kw->val.d[0]);
*/

         }
      }
   else 
      {
      kw->val.d[kw->kvn++] = d; kw->fmt = 'R';
      while (*line==',' && kw->kvn<MXKVN) 
         {				/* check for array  */
         line++;
	 n = getval(line,72,&i,&d);
	 while (n--) idx++, line++;
	 while (idx<80 && *line==' ') idx++, line++;
	 kw->val.d[kw->kvn++] = d;
         }
      }
   }
else if (c=='T' || c=='t')
   {					/* logical value    */
   kw->fmt = 'L';
   kw->val.i = 1;
   }
else if (c=='F' || c=='f')
   {					/* logical value    */
   kw->fmt = 'L';
   kw->val.i = 0;
   }

while (idx++ < 80 && *line++ != '/');                /* find comment */
while (idx<80 && *line==' ') line++, idx++;
kw->pcom = &kw->hkb[no];
while (idx++ < 80) kw->hkb[no++] = *line++;
kw->hkb[no] = '\0';
while (no-- && kw->hkb[no]==' ') kw->hkb[no] = '\0';

return 0;
}
