/*	token.c
 *
 * Licensed under the GPL. <www.gnu.org>
 *
 *  $Log: tokens.c,v $
 *  Revision 1.1  1997/07/03 19:26:31  warwick
 *  Initial revision
 *
 */

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <strings.h>

#include "tokens.h"
#include "vars.h"

static char *un_token=NULL;

extern void backtoken( char *back ) {
	if ( un_token ) {
		printf("Too many backtoken()s\n");
		exit(0);
	}
	un_token=back;
}

extern char *nexttoken( char *old, enum Context context, FILE *IN ) {
	static char *buf=NULL;
	static int buflen=0;
	int ch;
	free(old);
	if ( un_token ) {
		char *ret=un_token;
		un_token=NULL;
		return ret;
	}
	for (;;) {
		do {
			ch = fgetc(IN);
		} while ( isspace(ch) );
		if ( ch == '#' ) {
			do {
				ch = fgetc(IN);
			} while ( ch != '\n' );
			ungetc(ch,IN);
			continue;
		}
		if ( context != CON_EXPRESSION ) {
			if ( ch == ',' ) return strdup(",");
			if ( ch == ':' ) return strdup(":");
			if ( ch == '=' ) return strdup("=");
		}
		if ( ch == '"' ) { // Gather "..."
			int p=0;
			char expr='"';
			do {
				if ( ch=='$' ) expr='$';
				if ( ch=='\\' ) ch=fgetc(IN);
				if ( p==buflen ) buf=realloc(buf,buflen+=80);
				buf[p++]=ch;
				ch=fgetc(IN);
			} while ( ch!='"' );
			ungetc(ch,IN);
			buf[p]=0; *buf=expr;
			return strdup(buf);	// Includes an initial " as type-indicator
		}
		if ( !feof(IN) ) { // Gather until space (or : = if !expression)
			int p=0, impure=-1;
			char expr='"';
			ungetc(ch,IN);
			ch='"';	// Fake quotes...
			do {
				if ( ch=='$' ) expr='$';
				if ( !(isalnum(ch)||ch=='_') ) impure++;
				if ( p==buflen ) buf=realloc(buf,buflen+=80);
				buf[p++]=ch;
				ch=fgetc(IN);
			} while ( !isspace(ch) &&
					  ( context==CON_EXPRESSION ||
						( ch!=':' && ch!='=' && ch!=',' ) ) );
			ungetc(ch,IN);
			if ( !impure ) expr=' ';
			buf[p]=0; *buf=expr;
			return strdup(buf);
		}
		return NULL;
	}
}

extern char *seetoken(enum Context context, FILE *IN) {
	char *ret;
	backtoken(ret=nexttoken(NULL,context,IN));
	return ret;
}

