/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/* This filke contains a set of routines for parsing objects */

#include "../h/cdefs.h"
#include <ctype.h>

static validdigit ();
static char *scanBareInteger ();

static validdigit (c, base)
char c;
int base;
{
	int value;
	
	value = c - '0';
	if (value < base && value >= 0)
	 { return (value);
	 }
	value = c - 'a' + 10;
	if (value < base && value >= 10)
	 { return (value);
	 }
	return (-1);
}

static char *scanBareInteger (ip, str, base)
int *ip;
char *str;
int base;
{
	register char *cp;
	register int result = 0;
	int value;

	cp = str;
	if (validdigit(*cp, base) >= 0)
	 { while ((value = validdigit(*cp, base)) >= 0)
	    { result = result*base + value;
	      cp++;
	    }
	   *ip = result;
	   return (cp);
	 }
	return (NULL);	
}

char *scanIdentifier (result, size, str)
char *result;
int size;
char *str;
{
	char *cp = str;
	int count = 1;
	
	if ((isalpha(*cp) || *cp == '_' || *cp == '$') && size > count)
	 { *result++ = *cp++;
	   count++;
	 }
	else
	 { return (NULL);
	 }
	while ((isalnum(*cp) || *cp == '_' || *cp == '$') && size > count)
	 { *result++ = *cp++;
	   count++;
	 }
	*result = '\0';
	return (cp);
}

char *scanWhiteSpace (str)
char *str;
{
	char *cp = str;

	if (isspace (*cp))
	 { while (isspace (*cp))
	    { cp++;
	    }
	   return (cp);
	 }
	else
	 { return (NULL);
	 }
}

char *scanInteger (ip, str)
int *ip;
char *str;
{
	int negate = 0;
	int base = 10;
	register char *cp;
	int result;

	cp = str;
	while (isspace(*cp))
	 { cp++;
	 }
	if (*cp == '-')
	 { negate = 1;
	   cp++;
	 }
	else if (*cp == '+')
	 { cp++;
	 }
	if (cp = scanBareInteger (&result, cp, base))
	 { *ip = negate ? -result : result;
	   return (cp);
	 }
	return (NULL);	
}

char *scanOctalInteger (ip, str)
int *ip;
char *str;
{
	int negate = 0;
	int base = 8;
	register char *cp;
	int result;

	cp = str;
	while (isspace(*cp))
	 { cp++;
	 }
	if (*cp == '-')
	 { negate = 1;
	   cp++;
	 }
	else if (*cp == '+')
	 { cp++;
	 }
	if (cp[0] != '0')
	 { return (NULL);
	 }
	if (cp = scanBareInteger (&result, cp, base))
	 { *ip = negate ? -result : result;
	   return (cp);
	 }
	return (NULL);	
}

char *scanHexInteger (ip, str)
int *ip;
char *str;
{
	int negate = 0;
	int base = 16;
	register char *cp;
	int result;

	cp = str;
	while (isspace(*cp))
	 { cp++;
	 }
	if (*cp == '-')
	 { negate = 1;
	   cp++;
	 }
	else if (*cp == '+')
	 { cp++;
	 }
	if (cp[0] != '0' || cp[1] != 'x')
	 { return (NULL);
	 }
	cp += 2;
	if (cp = scanBareInteger (&result, cp, base))
	 { *ip = negate ? -result : result;
	   return (cp);
	 }
	return (NULL);	
}

extern double atof();

char *scanDouble (dp, str)
double *dp;
char *str;
{
	register char *cp;
	char *sp;
	double result;

	int leftOfPoint = 0;
	int rightOfPoint = 0;
	int leftInt = 0;
	int rightInt = 0;
	int negate = 0;
	int negateExponent = 0;
	int exponent = 0;

	cp = str;
	while (isspace(*cp))
	 { cp++;
	 }
	if (*cp == '-')
	 { negate = 1;
	   cp++;
	 }
	else if (*cp == '+')
	 { cp++;
	 }
	if (sp = scanBareInteger (&leftInt, cp, 10))
	 { cp = sp;
	   leftOfPoint = 1;
	 }
	if (*cp == '.')
	 { cp++;
	 }
	if (sp = scanBareInteger (&rightInt, cp, 10))
	 { cp = sp;
	   rightOfPoint = 1;
	 }
	if (!leftOfPoint && !rightOfPoint)
	 { return (NULL);
	 }
	if (*cp == 'e' || *cp == 'E')
	 { cp++;
	   if (*cp == '-')
	    { negateExponent = 1;
	      cp++;
	    }
	   else if (*cp == '+')
	    { cp++;
	    }
	   if (sp = scanBareInteger (&exponent, cp, 10))
	    { cp = sp;
	    }
	 }
	sscanf (str, "%lf", dp); /* punt */
	return (cp);
}

#if TEST

#include <stdio.h>

main()
{
	char buf[256];
	char *cp;
	int i;
	double d;

	while (gets(buf))
	 { 
	   i = 0;
	   d = 0.0;
	   cp = scanInteger (&i, buf);
	   printf ("ilen = %d i = %d atoi = %d\n", cp-buf, i, atoi(buf));
	   cp = scanDouble (&d, buf);
	   printf ("dlen = %d d = %g atof = %g\n", cp-buf, d, atof(buf));
	 }
}

#endif
