/*===========================================================================
  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 B  +++++++++++++++++++++++++++++++++
.LANGUAGE   C
.IDENTIFICATION  Characters string handling + general functions
.AUTHOR   K. Banse	[ESO/IPG - Garching]
.COMMENTS
 holds CGN_LOWER, CGN_UPPER, CGN_NINT, CGN_DNINT, CGN_NUMBER, CGN_OPEN
       CGN_EQUAL, CGB_REPLA, CGN_SKIP, CGN_UPSTR, CGN_LOWSTR
       CGN_UPCOPY, CGN_LOWCOPY, CGN_COPYALL, CGN_FUNC
.KEYWORDS 
 name translation, parsing, filling, (((seq-file read)))

.VERSION 
 100608		last modif

---------------------------------------------------------------------------*/
 
 
#include <math.h>
#include <fileexts.h> 


static int	cdifU = 'A' - 'a';
static int	cdifL = 'a' - 'A';

/*

*/

char CGN_LOWER(c)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function converts all uppercase to lowercase
.RETURN the modified character.
--------------------------------------------------*/
char c;       /* character to be eventually translated */

{
if ( (c >= 'A') && (c <= 'Z') )
   return (c + cdifL);
else
   return c;
}

/*

*/

#ifdef __STDC__
int CGN_NINT(float rval)
#else
int CGN_NINT(rval)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 return nearest integer of a floating point number
.RETURN NINT(rval)
--------------------------------------------------*/
float	rval;		/*  input  real number  */
#endif 
 
{
int   ival;
 

if (rval > 1.e-30)
   ival = (int) (rval + 0.5);
else if (rval < -1.e-30)
   ival = (int) (rval - 0.5);
else
   ival = 0;
 
return (ival);
 
}

#ifdef __STDC__
int CGN_DNINT(double dval)
#else
int CGN_DNINT(dval)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 return nearest integer of a double precision number
.RETURN NINT(dval)
--------------------------------------------------*/
double  dval;           /*  input  real number  */
#endif

{
int   ival;


if (dval > 1.e-30)
   ival = (int) (dval + 0.5);
else if (dval < -1.e-30)
   ival = (int) (dval - 0.5);
else
   ival = 0;

return (ival);

}

/*

*/

int CGN_NUMBER(string)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function checks, if a given character string begins as a valid number
.RETURN = 1, if a number
        = 0, else
--------------------------------------------------*/
char   *string;       /* input string */
 
{
char   *cp;
register char cr;
 

cp = string;
cr = *cp;
 

if ((cr == '+') || (cr == '-')) 
   {
   cp ++;
   cr = *cp;
   }

if (cr == '0') 
   {
   cp ++;

   if (*cp == 'x')			/* check for hex. constant */
      {
      char  kr;

      cp ++;
      while (*cp != '\0')
         {
         kr = *cp++;
         if ((kr < '0') || (kr > '9'))
            {
            cr = CGN_LOWER(kr);
            if ((cr < 'a') || (cr > 'f')) return (0);
            }
         }
      return (1);			/* hex. number: 0xabc... */
      }

   else
      {
      if (*cp == '.') cp ++;
      goto step_a;			/* starts with 0, check next chars */
      }
   }


if (cr == '.') cp ++;
 
if ((*cp < '0') || (*cp > '9')) return (0);

/* cp ++;    what the hell is this ??? 060331 */


step_a:					/* here we found first digit */
while (*cp != '\0')
   {
   cr = *cp++;
   if ((cr < '0') || (cr > '9') )
      {
      if ((cr != '.') && (cr != 'D') && (cr != 'd')
                      && (cr != 'E') && (cr != 'e')
                      && (cr != '+') && (cr != '-')
                      && (cr != ','))	/* for several numbers */
      return (0);
      }
   }

return (1);
}

/*

*/

int CGN_OPEN(file,option)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function returns the file id from osaopen,
 but translates first all logical stuff...
.RETURN fid   file no. as expected from osaopen
--------------------------------------------------*/
 
char	*file;	/* IN: file name            */
int	option;	/* IN: open mode as described for osaopen  */
 
{
char	tempo[400];
 
 
CGN_LOGNAM(file,tempo,400);
return (osaopen(tempo,option));
 
}

/*

*/

int CGN_EQUAL(namea,nameb)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 compare two frame names and test, if they are equal
.RETURN 0 or 1, if frame names are equal or not
--------------------------------------------------*/
char   *namea;       /* 1. file name (terminated by \0) */
char   *nameb;       /* 2. file name (terminated by \0) */

{
int   m, extflg;
char  tempa[400], tempb[400];


CGN_CLEANF(namea,F_IMA_TYPE,tempa,399,&m,&extflg);
CGN_CLEANF(nameb,F_IMA_TYPE,tempb,399,&m,&extflg);

if (strcmp(tempa,tempb) != 0)
   return (1);
else
   return (0);
}

/*

*/

void CGN_REPLA(string,lstring,chara,charb)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function replaces a given character by another
.RETURN nothing
--------------------------------------------------*/
char   *string;       /* input string */
int   lstring;        /* length of string */
char   chara;          /* character to be replaced */
char   charb;	      /* replacing char */
 
{
register int   nr;

 
for (nr=0; nr<lstring; nr++)
   {
   if (string[nr] == chara) string[nr] = charb;
   }
}

/*

*/

#ifdef __STDC__
int CGN_SKIP(char * string , char skipchar , char flag , int * indx)
#else
int CGN_SKIP(string,skipchar,flag,indx)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 finds position of first character different from skip_char.
   depending upon flag (= 'f' or 'r') we start at the beginning
   or the end of the input string
.RETURN
   returns 1 if o.k.
   returns 0 and length(string) if no other char. found
--------------------------------------------------*/
char   *string;   /* IN : Input string */
char   skipchar;  /* IN : skip-character */
char   flag;      /* IN : start atthe end or at the beginning of the string 
			  'f' => from the beginning, else from the end   */
int   *indx;     /* OUT: position of the first char != from CHAR 
			 or length of string if only skip chars in string */
#endif

{
register int   	mm, i;
 

if (flag == 'f')		/* forward skip */
   {
   for (i=0; string[i] != '\0'; i++)
      {
      if (string[i] != skipchar)
	 {
	 *indx = i;
         return (1);
	 }
      }
   }
 
else				/* reverse skip */
   {
   mm = -1;
   for (i=0; string[i] != '\0'; i++)
      {
      if (string[i] != skipchar) mm = i;
      }
   if (mm >= 0)
      {
      *indx = mm;
      return (1);
      }
   }

 
/* no other character found - so we return total length of input string */
 
*indx = i;
return (0);			
}

/*

*/

char CGN_UPPER(c)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function converts all lowercase to uppercase
.RETURN character.
--------------------------------------------------*/
char c;    /* character to eventually be 'uppercased' */

{
if ( (c >= 'a') && (c <= 'z') )
   return (c + cdifU);
else
   return (c);
}

/*

*/

int CGN_UPCOPY(strb,stra,lim)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function copies + converts all lowercase to uppercase for a given
 number of chars. of input string
.RETURN
 nothing
--------------------------------------------------*/
 
char *stra;	/* IN: input string */
char *strb;	/* IN: output string in uppercase  */
int   lim;	/* IN: no. of chars. to do */
 
{
register int  count;

register char   rp;
 
 
 
for (count=0; count<lim; count++)
   {
   rp = *stra++;
   if (rp == '\0')
      {
      *strb = rp;
      return count;
      }

   if ((rp >= 'a') && (rp <= 'z')) rp += cdifU;

   *strb++ = rp;
   }

return lim;
}

/*

*/

void CGN_UPSTR(string)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function converts all lowercase to uppercase for a complete string
.RETURN uppercase character string
--------------------------------------------------*/
char *string;    /* character string to eventually be 'uppercased' */
 
{
register int	c, n;
 

 
for (n=0; string[n] != '\0'; n++)
   {
   c = string[n];
   if ((c >= 'a') && (c <= 'z'))
      string[n] = c + cdifU;
   }
}

/*

*/

void CGN_LOWSTR(string)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function converts all uppercase to lowercase for a complete string
.RETURN lowercase character string
--------------------------------------------------*/
 
char *string;    /* character string to eventually be 'lowercased' */
 
{
register int	c, n;

 
 
for (n=0; string[n] != '\0'; n++)
   {
   c = string[n];
   if ((c >= 'A') && (c <= 'Z'))
      string[n] = c + cdifL;
   }
}

/*

*/

int CGN_LOWCOPY(strb,stra,lim)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 this function copies + converts all lowercase to uppercase for a given
 number of chars. of input string
.RETURN
 nothing
--------------------------------------------------*/
 
char *stra;	/* IN: input string */
char *strb;	/* IN: output string in uppercase  */
int   lim;	/* IN: no. of chars. to do */
 
{
register char  rp;

register int count;

 
 
for (count=0; count<lim; count++)
   {
   rp = *stra++;
   if (rp == '\0')
      {
      *strb = rp;
      return count;
      }

   if ((rp >= 'A') && (rp <= 'Z')) rp += cdifL;

   *strb++ = rp;
   }

return lim;
}

/*

*/

void CGN_COPYALL(cpntra,cpntrb,slen)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
   copy entire string b on string a.
   (Doesn't take '\0' characters as end-of-string).
.RETURNS nothing.
----------------------------------------------------------------------*/
 
char    *cpntra 	/* OUT: string to receive the result) */;
char    *cpntrb 	/* IN: string to be copied */;
int    slen 		/* IN: number of bytes to copy */;
 
{
register int   n;
 
for (n=0; n<slen; n++)
   *cpntra++ = *cpntrb++;

}

/*

*/

void CGN_strcpy(dest,src)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
   copy '\0' limited string
   like strcpy (except the const source) but copies in a controlled
   way, i.e. starting with 1st char.
   thus, src and dest may overlap (unlike system strcpy)
.RETURNS nothing.
----------------------------------------------------------------------*/

char    *dest;	 	/* OUT: dest. string */
char    *src;	 	/* IN: source string */
 
{
register char cc;
register char *da, *sa;



da = dest;
sa = src;

cc = *sa++;
while (cc != '\0')
   {
   *da++ = cc;
   cc = *sa++;
   }

*da = '\0';                     /* terminate dest string */
}

/*

*/

void CGN_strncpy(dest,src,n)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
   copy exactly n elements of source string
   like strcnpy (except the const source) but copies in a controlled
   way, i.e. starting with 1st char.
   thus, src and dest may overlap (unlike system strncpy)
.RETURNS nothing.
----------------------------------------------------------------------*/

char    *dest;	 	/* OUT: dest. string */
char    *src;	 	/* IN: source string */
size_t  n;		/* no. of elements to copy */
 
{
size_t i;

for (i=0; i<n && src[i]!='\0'; i++)
   dest[i] = src[i];

for ( ; i<n; i++) dest[i] = '\0';	/* fill up with '\0' */
}

/*

*/

void CGN_FUNC(fno,dval)
 
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
   support calculation of ln, log10, exp, exp10, sin, cos, tan
                          asin, acos, atan
.RETURNS nothing.
----------------------------------------------------------------------*/
 
int    fno;            /* IN : function no.  */
double  *dval;          /* IN/OUT: function argument + result  */
 
{
double x, y;
static double  facto = 0.0174532925;		/*  Pi/180.0 */



x = *dval;

switch(fno)
   {
 case 1:				/* y = log(x) */

   if (x <= 0.0)
      y = 0.0;
   else
      y = log(x);
   break;

 case 2:				/* y = log10(x)  */

   if (x <= 0.0)
      y = 0.0;
   else
      y = log10(x);
   break;

 case 3:				/* y = exp(x)  */

   y = exp(x);
   break;

 case 4:				/* y = exp10(x)  */

   x *= log(10.0);		/* use: 10**x = e**(x*ln(10))  */
   y = exp(x);
   break;

 case 5:				/* y = sin(x)  */

   x *= facto;
   y = sin(x);
   break;

 case 6:				/* y = cos(x) */

   x *= facto;
   y = cos(x);
   break;

 case 7:				/* y = tan(x)  */

   x *= facto;
   y = tan(x);
   break;

 case 8:				/* y = sqrt(x)  */

   y = sqrt(x);
   break;

 case 9:				/* y = asin(x) in degrees  */

   y = asin(x);
   y /= facto;
   break;

 case 10:				/* y = acos(x) in degrees  */

   y = acos(x);
   y /= facto;
   break;

 case 11:				/* y = atan(x) in degrees  */
 default:

   y = atan(x);
   y /= facto;
   }

*dval = y;
}

/*

*/

void CGN_CUTOFF(instr,outstr)
/*++++++++++++++++++++++++++++++++++++++++++++++++++
.PURPOSE
 cut off trailing blanks
.RETURN nothing
--------------------------------------------------*/
char   *instr;       /* input string */
char   *outstr;      /* output string */

{
register int   nr, mr;
 

mr = -1;			/* we'll set `mr' to last non-blank char. */
nr = 0;
while (nr > -1)
   {
   outstr[nr] = instr[nr];
   if (outstr[nr] != ' ')
      {
      if (outstr[nr] == '\0')
         {
         outstr[mr+1] = '\0';
         return;
         }
      else
         mr = nr;
      }
   nr ++;
   }
} 

