/*
** Copyright 1992
** Patrick Sweeney
*/
#include <stdio.h>
#include <ctype.h>
#include "token.h"

struct _tokentbl {
	char *s;
	token_t type;
} tokentbl[] = {
	{"phone1", TOKEN_PHONE1},
	{"phone2", TOKEN_PHONE2},
	{"timeout", TOKEN_TIMEOUT},
	{"retries", TOKEN_RETRIES},
	{"script", TOKEN_SCRIPT},
	{"end", TOKEN_END},
	{"system", TOKEN_SYSTEM},
	{"baudrate", TOKEN_BAUDRATE},
	{"device", TOKEN_DEVICE},
	{"modem", TOKEN_MODEM},
	{"dialstr", TOKEN_DIALSTR},
	{"resetstr", TOKEN_RESETSTR},
	{"hangupstr", TOKEN_HANGUPSTR},
	{"stopbits", TOKEN_STOPBITS},
	{"databits", TOKEN_DATABITS},
	{"dialer", TOKEN_DIALER},
	{"remote", TOKEN_REMOTE},
	{"local", TOKEN_LOCAL},
	{"wait", TOKEN_WAIT},
	{"nowait", TOKEN_NOWAIT},
	{NULL, 0}
};

int
token_read(Tokenfile *tf, Token *token)
{
	int c;
	int l;

	while(1)
	{
		if ((c = fgetc(tf->f)) == EOF)
		{
			token->type = TOKEN_EOF;
			return 0;
		}
		if (c == '#')
		{
			/* eat up comment */
			while(1)
			{
				if ((c = fgetc(tf->f)) == EOF)
				{
					token->type = TOKEN_EOF;
					return 0;
				}
				if (c == '\n')
					break;
			}
		}
		if (c == '\n')
			tf->linenum++;
		if (!isspace(c))
		{
			if (c == '\\')
			{
				if ((c = fgetc(tf->f)) == EOF)
					return -1;
				switch(c)
				{
				case 'r': c = '\r'; break;
				case 'n': c = '\n'; break;
				default: break;
				}
			}
			break;
		}
	}
	if (c == '"')
	{
		l = 0;
		token->type = TOKEN_LITERAL;
		do {
			if ((c = fgetc(tf->f)) == EOF)
				break;
			if (c == '\\')
			{
				if ((c = fgetc(tf->f)) == EOF)
					return -1;
				switch(c)
				{
				case 'r': c = '\r'; break;
				case 'n': c = '\n'; break;
				default: break;
				}
				token->v.sval[l++] = c;
			}
			else
				if (c != '"')
					token->v.sval[l++] = c;
		} while(c != '"');
		token->v.sval[l] = '\0';
		return 0;
	}
	if (isdigit(c))
	{
		token->type = TOKEN_INTEGER;
		token->v.ival = 0;
		while(isdigit(c))
		{
			token->v.ival *= 10;
			token->v.ival += (c - '0');
			if ((c = fgetc(tf->f)) == EOF)
				break;
		}
		ungetc(c, tf->f);
		return 0;
	}
	if (isalpha(c))
	{
		struct _tokentbl *t;
		
		token->type = TOKEN_LITERAL;
		l = 0;
		while(isalpha(c) || isdigit(c) || c == '_')
		{
			token->v.sval[l++] = c;
			if ((c = fgetc(tf->f)) == EOF)
				break;
			if (c == '\\')
			{
				if ((c = fgetc(tf->f)) == EOF)
					return -1;
				switch(c)
				{
				case 'r': c = '\r'; break;
				case 'n': c = '\n'; break;
				default: break;
				}
			}
		}
		token->v.sval[l] = '\0';
		t = &tokentbl[0];
		while(t->s)
		{
			if (strcmp(t->s, token->v.sval) == 0)
				break;
			t++;
		}
		if (t->s)
			token->type = t->type;
		return 0;
	}
	token->type = TOKEN_PUNCT;
	token->v.cval = c;
	return 0;
}

int
token_error(Tokenfile *tf, char *msg)
{
	fprintf(stderr,"Error! %s...File:%s  Line:%d\n",
		msg, tf->fn, tf->linenum);
	return -1;
}
