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

extern char *salloc(char *);

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
    }
    ,
    {
	"password", TOKEN_PASSWORD
    }
    ,
    {
	NULL, 0
    }
};

int token_read(Tokenfile * tf, Token * token)
{
    int c;
    int l;
    char tbuf[MAX_TOKENLEN];

    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;
		}
		tbuf[l++] = c;
		c = ' ';	/* in case it was a quote */
	    } else if (c != '"')
		tbuf[l++] = c;
	}
	while (c != '"');
	tbuf[l] = '\0';
	token->v.sval = salloc(tbuf);
	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 == '_') {
	    tbuf[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;
		}
	    }
	}
	tbuf[l] = '\0';
	token->v.sval = salloc(tbuf);
	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;
}
