/*
 * gettok: get next token from the input stream.
 *
 * Copyright 1988 by J.A. Lydiatt.  Permission is hereby given to 
 * freely distribute this code for non-commercial use.
 * Maintenance Notes:
 *   18Jun88 - V1.0 Created by Jal.
 *
 */

#include "genstubs.h"
#include <ctype.h>

#define MAXLINE		128

typedef struct lineinfo {
	int  next;
	int  length;
	char line[MAXLINE];
	} LINEINFO;


/*
 * External variables:
 */

extern FILE *fi;

static LINEINFO curline;
static int nextchar;

void nextline()
{
	register LINEINFO *l = &curline;
	register char *p;
	extern char *fgets();
	extern int strlen();

	p = fgets( l->line, MAXLINE, fi);
	if ( p == NULL )
		l->line[0] = '\0';

	l->length = strlen( l->line );
	l->next = 0;
	nextchar = l->length == 0 ? EOF : l->line[ l->next++ ];  
}

/*
 * getcurline: return the current line in line.
 */

void getcurline( line )
char *line;
{
	register char *p;
	register char *q;

	for ( p=line, q=curline.line; q && *q != '\n'; ++p,++q )
		*p = *q;
	*p = '\0';
}

/*
 * warn: prints the current line followed by the warning message.
 */

void warn( msg )
char *msg;
{
	extern int fputs();

	(void) fprintf( stderr, "%s", curline.line );
	(void) fputs( msg, stderr );
	(void) fputs( "\n\n", stderr );
}

/*
 * gnc: get next character from the input stream.
 */

static int gnc()
{
	register LINEINFO *l = &curline;

	if ( l->next >= l->length )
		if ( l->length > 0 )
			nextline();	
		else
			return EOF;
	else
		nextchar = l->line[ l->next++ ];  
	return nextchar;
}

/*
 * getid: get a variable name from the input file.
 */

static void getid( t )
register TOKEN *t;
{
	int i = 0;

	while ( (isalpha(nextchar) || isdigit(nextchar) || nextchar == '_')
		 && i < MAXSTR-1 ){
		t->id[ i++ ] = nextchar;
		(void) gnc();
	}
	t->id[ i ] = '\0';
}

/*
 * gettok: get the next token from the current line.
 */

int gettok( t )
register TOKEN *t;
{
	int value, i;

	while ( nextchar == ' ' || nextchar == '\t' )
		(void) gnc();

	if ( nextchar == EOF )
		return EOF;

	if ( nextchar == '#' ){
		if ( gnc() != '#' ){
			t->value = nextchar;
			(void) gnc();
			return UNKNOWN;
		} else {
			(void) gnc();
			getid( t );
			return DIRECTIVE;
		}
	} else if ( isalpha(nextchar) || nextchar == '_' ){
		getid( t );
		return ID;

	} else if ( isdigit( nextchar ) ){
		value = 0;
		do {		
			value = value * 10 + (nextchar - '0');
			(void) gnc();
		}
		   while ( isdigit( nextchar ) );
		t->value = value;
		return NUMBER;
	} else {
		t->value = nextchar;
		(void) gnc();
		switch( t->value ){
			case '\n':return EOL;
			case '(': return LPAREN;
			case ')': return RPAREN;
			case ',': return COMMA;
			case '/': return SLASH;
			case '*': return COMMENT;
			default:  return UNKNOWN;
		}
	}
}
