/*-=-=-=-=-=-=-=-=-=-=-=- 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.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

		Little package to read tokens from a file

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */

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

static FILE *stream;
static char *textp;
static char textBuf[256] = {'\0'};
static char lineBuf[256] = {'\0'};
static int lineNo = 0;
static int atEOF = 0;
static char *delimiters;

static nextToken();

readInit (fp, dstring)
FILE *fp;
char *dstring;
{
	stream = fp;
	textp = textBuf;
	textBuf[0] = '\0';
	lineNo = 0;
	atEOF = 0;
	delimiters = dstring;
}

endOfInput()
{
	return (atEOF);
}

lineNumber()
{
	return (lineNo);
}

static nextToken()
{
	while (1)
	 { while (isspace(*textp))
	    { textp++;
	    }
	   if (*textp == '\0')
	    { textp = textBuf;
	      if (fgets (lineBuf, 256, stream) == NULL)
	       { atEOF = 1;
		 *textp = '\0';
		 return;
	       }
	      else
	       { char *lp = lineBuf;
		 char *tp = textBuf;
		 while (*lp)
		  { if (*lp == '#')
		     { if (lp > lineBuf && lp[-1] == '\\')
			{ tp--;
			}
		       else
			{ break;
			}
		     }
		    *tp++ = *lp++;
		  }
		 *tp = '\0';
		 lineNo++;
	       }
	    }
	   else
	    { return;
	    }
	 }
}

#define DELIMITER(c) \
	(isspace(c) || (c) == '\0' || index(delimiters,(c)) )

readDouble(dp)
double *dp;
{
	char *cp;

	if (atEOF)
	 { return (0);
	 }
	nextToken();
	if (cp = (char*)scanDouble (dp, textp))
	 { if (!isalnum (*cp))
	    { textp = cp;
	      return (1);
	    }
	 }
	return (0);
}

readFloat(fp)
float *fp;
{
	double d;
	char *cp;

	if (atEOF)
	 { return (0);
	 }
	nextToken();
	if (cp = (char*)scanDouble (&d, textp))
	 { if (!isalnum (*cp))
	    { textp = cp;
	      *fp = d;
	      return (1);
	    }
	 }
	return (0);
}

readInteger(ip)
int *ip;
{
	char *cp;

	if (atEOF)
	 { return (0);
	 }
	nextToken();
	if ((cp = (char*)scanHexInteger(ip, textp)) &&
	    !isalnum(*cp) && *cp != '.')
	 { textp = cp;
	   return (1);
	 }
	else if ((cp = (char*)scanOctalInteger(ip, textp)) &&
	    !isalnum(*cp) && *cp != '.')
	 { textp = cp;
	   return (1);
	 }
	else if ((cp = (char*)scanInteger(ip, textp)) && 
	    !isalnum(*cp) && *cp != '.')
	 { textp = cp;
	   return (1);
	 }
	else
	 { return (0);
	 }
}

readCharacter()
{
	char *cp;

	if (atEOF)
	 { return (0);
	 }
	nextToken();
	cp = textp;
	textp++;
	return (*cp);
}

readIdentifier(result, size)
char *result;
int size;
{
	char *cp;

	if (atEOF)
	 { return (0);
	 }
	nextToken();
	if ((cp = (char*)scanIdentifier (result, size, textp)) &&
	    DELIMITER(*cp))
	 { textp = cp;
	   return (1);
	 }
	else
	 { return (0);
	 }
}

readString(result, size)
char *result;
int size;
{
	char *cp, *rp;

	if (atEOF)
	 { return (0);
	 }
	nextToken();
	if (atEOF)
	 { return (0);
	 }
	cp = textp;
	rp = result;
	if (*cp == '"')
	 { /* looks like a quotedString. Pass escaped quotes, and continue
	      until we hit a closing (non-escaped) quote */
	   cp++;
	   while (*cp != '"' && *cp != '\n')
	    { if (cp[0] == '\\')
	       { if (cp[1] == '"')
		  { *rp++ = '"';
		    cp += 2;
		  }
		 else if (cp[1] == '\\')
		  { *rp++ = '\\';
		    cp += 2;
		  }
		 else if (cp[1] == 'n')
		  { *rp++ = '\n';
		    cp += 2;
		  }
		 else if (cp[1] == 't')
		  { *rp++ = '\t';
		    cp += 2;
		  }
		 else if (cp[1] == 'f')
		  { *rp++ = '\f';
		    cp += 2;
		  }
		 else if (cp[1] == 'r')
		  { *rp++ = '\r';
		    cp += 2;
		  }
		 else if (cp[1] == 'b')
		  { *rp++ = '\b';
		    cp += 2;
		  }
		 else if (isdigit(cp[1]))
		  { int v, i;
		    v = cp[1] - '0';
		    cp += 2;
		    for (i=0; isdigit(*cp) && i<2; i++)
		     { v = v*8 + *cp++ - '0';
		     }
		    *rp++ = MIN(v,255);
		  }
	       }
	      else
	       { *rp++ = *cp++;
	       }
	    }	   
	   if (*cp == '"')
	    { /* verify the closing quote. If we don't have the closing
		 quote, then we just fall through and ship this out as
		 a verbatim (unquoted) string */
	      textp = ++cp;
	      *rp = '\0';
	      return (1);
	    }
	 }
	cp = textp;
	rp = result;
	while (!isspace(*cp))
	 { *rp++ = *cp++;
	 }
	textp = cp;
	*rp = '\0';
	return (1);
}

readExactString(match)
char *match;
{
	char *cp;

	if (atEOF)
	 { return (0);
	 }
	nextToken();
	if (atEOF)
	 { return (0);
	 }
	cp = textp;
	while (!isspace(*cp))
	 { if (*match++ != *cp++)
	    { return(0);
	    }
	 }
	if (*match != '\0')
	 { return (0);
	 }
	textp = cp;
	return (1);
}
	
#if TEST

main()
{
	int status;
	int ival;
	double dval;
	char *buf[256];

	readInit(stdin, "=");

	while (!endOfInput())
	 { if (readIdentifier (buf, 256))
	    { printf ("Identifier: %s\n", buf);
	    }
	   else if (readInteger (&ival))
	    { printf ("Integer: %d\n", ival);
	    }
	   else if (readDouble (&dval))
	    { printf ("Double: %g\n", dval);
	    }
	   else if (readString (buf, 256))
	    { printf ("String: %s\n", buf);
	    }
	 }
}

#endif
