/*===========================================================================
  Copyright (C) 1988-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 Massachusetss Ave, Cambridge, 
  MA 02139, USA.
 
  Corresponding 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
===========================================================================*/

/*+++++++++ 
.MODULE    trfpic.c
.AUTHOR    Francois Ochsenbein [ESO]
.LANGUAGE  C
.CATEGORY  Conversion from character to float (double) using a picture.

.COMMENTS
	Definition of pictures are in edfpic.c

\begin{TeX}
\end{TeX}

.VERSION   1.0	27-May-1988: Creation
.VERSION   1.1	21-Oct-1988: Modified error report
.VERSION   1.2	22-Mar-1990: Added stkfpic (tokenisation)
.VERSION   1.3	16-May-1990: Allow trailing blanks / spaces

 090831		last modif
-----------------------------------------------*/
 
#include <midas_def.h>
#include <macrogen.h>
#include <tra.h>
#include <atype.h>
#include <string.h>

extern int tr_pic(), tr_error();


MID_EXTERN struct trerr_s	*trerror;

#define FINISH			goto FIN

MID_STATIC	char	sign;
MID_RSTATIC char emarks[] = {'.', 'E','e','D','d'};
MID_STATIC	char	stk = 0;	/* Indicator for stkfpic	*/
MID_STATIC	char edited[64];

/*===========================================================================*/
static int Sign(str, len)
/*++++++
.PURPOSE Just scan the beginning of a string: skip leading blanks,
	and get the sign.
.RETURNS Number of valid characters
.REMARKS Not traced. 
--------*/
	char *str;	/* IN: The string to scan	*/
	int  len;	/* IN: Length of the string	*/
{
	char *p, *pe;
  
  sign = 0;
  if (len <= 0)		return(0);

  p = str + oscspan((unsigned char *)str, len, _SPACE_, main_ascii);
  pe = str + len;
  
  if (p < pe)
  {	switch(*p)
  	{ case '-':	sign = 1;
  	  case '+':	p++; 	break;
  	}
	p += oscspan((unsigned char *)p, pe-p, _SPACE_, main_ascii);	/* Skip blanks */
  }

  return(p-str);
}	

/*===========================================================================*/
int tr_fpic(str, len, pic, value)
/*++++++
.PURPOSE Converts a string to a double number according to a picture
	(see module edpic.c)
.RETURNS Number of decimals / -1 for error or no number
.REMARKS returned value is e.g. 101 for 1.01
--------*/
	char	*str;	/* IN: String to scan	*/
	int	len;	/* IN: Length of str	*/
	char	*pic;	/* IN: The picture	*/
	double	*value;	/* OUT: result		*/
{
	char 	*p, *pe, *pdot, *a, x;
	int	nd, i, la;
	long	int_part;
	double	atof();

  p = str + oscspan((unsigned char *)str, len, _SPACE_, main_ascii);
  pe = str + len;
  *value = 0.e0;
  sign = 0;
  trerror->errno = 0;	
  trerror->msg = pic;
  trerror->str = str;
  trerror->len = len;
  
  p += Sign(p, pe-p);		/* Locate Sign	*/
  pdot = pe;

  for (i=0; (i < sizeof(emarks)) && (pdot == pe);  i++)
    	pdot = p + oscloc(p, pe-p, emarks[i]);
  
  la = strlen(pic), a = pic + la;
  for (i=0; (i < sizeof(emarks)) && (*a == EOS);  i++)
    	a = pic + oscloc(pic, la, emarks[i]);

  x = *a, *a = '\0';
  nd = tr_pic(p, pdot-p, pic, &int_part);
  *a = x;
  if (nd < 0)	FINISH;

	/* Edit Number */

  edited[0] = (sign ? '-' : ' ');
  
  for (i=11; --i>0; int_part /= 10)
  	edited[i] = (int_part % 10) + '0';
  edited[11]   = '.';
  
  	/* Copy Remaining part. x is an indicator which takes values
  	   1   when exponent starts
  	   2   wneh number terminated
  	 */
  
  x = 0, p = pdot, i = 12;
  if (p == pe)	goto GET_VALUE;
  if (*p == '.')	nd++, p++;
  
  for ( ; (p < pe) && (trerror->errno == 0); p++)
  { if (isspace(*p))	{ x = 2; continue; } 
    if (x == 2)		{ trerror->errno = TRERR_FLOAT; break; }
    switch(*p)
    {	case 'd': case 'D' : case 'e' : case 'E':
		if (x)	trerror->errno = TRERR_FLOAT;
    		edited[i++] = 'e';
		x = 1;
    		break;
	case '+': case '-': 
		if (x == 0)	/* Error, E missing  */
			trerror->errno = TRERR_FLOAT;
    		edited[i++] = *p;
		break;
	default:
		if (isdigit(*p))	
    			edited[i++] = *p, nd++;
		else	trerror->errno = TRERR_DIGIT;
		break;
    }
    if (i >= (sizeof(edited)-1))	trerror->errno = TRERR_UNDEF;
  }
  if ((p < pe) && (trerror->errno == 0))
  	trerror->errno = TRERR_FLOAT;


  GET_VALUE:
  edited[i] = '\0';
  if (trerror->errno)		/* Bad number */
  {	trerror->offset = (p-str);
	tr_error();
	nd = -1;
  }
  else if (!stk)
  	*value = atof(edited);

  FIN:
  if (stk)	return(p - str);
  return(nd);
}

/*===========================================================================*/
int stkfpic(str, pic)
/*++++++
.PURPOSE Compute the length of the tokenized string
.RETURNS Length of str matched for specified picture
.REMARKS 
--------*/
	char	*str;	/* IN: String to scan	*/
	char	*pic;	/* IN: The picture	*/
{
	int	status;
	double	value;
	
    stk = 1;	/* Tells tr_fpic that we just tokenize */
    status = tr_fpic (str, strlen(str), pic, &value);
    stk = 0;
    
    return(status);
}
