/*
     extract - A network log processor
     Copyright (C) 1993 Douglas Lee Schales, David K. Hess, David R. Safford

     Please see the file `COPYING' for the complete copyright notice.

lex.c - 03/20/93

*/
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include "y.tab.h"
#include "lex.h"
#include "chario.h"

#define TRUE 1
#define FALSE 0

extern int atoi(char *);

static int buflen = 0;
static int bufptr = 0;
static char *buffer = (char *)0;

extern struct keywords keywords[];

int     
yylex()
{
     int c, nc;
     int comment = FALSE;
     int number;
     int i;
     int quote;
     
     while((c = fetchar()) != EOF){
	  if(c == '#')
	       comment = TRUE;
	  else if(comment){
	       if(c == '\n')
		    comment = FALSE;
	  }
	  else if(!isspace(c))
	       break;
     }
     if(c == EOF)
	  return 0;
     
     buflen = 16;
     buffer = (char *)malloc(buflen);

     quote = FALSE;
     if(isalnum(c) || c == '"'){
	  bufptr = 0;
	  if(c == '"'){
	       quote = TRUE;
	       number = FALSE;
	  }
	  else {
	       buffer[bufptr++] = c;
	       number = isdigit(c);
	  }
	  while((c=fetchar()) != EOF){
	       if(c == '"'){
		    if(quote)
			 c = fetchar();
		    break;
	       }
	       else if(!quote){
		    if(isspace(c))
			 break;
		    if(c == '<' ||
		       c == '>' ||
		       c == '&' ||
		       c == '|' ||
		       c == '!' ||
		       c == '{' ||
		       c == '}' ||
		       c == ';' ||
		       c == '(' ||
		       c == ')' ||
		       c == ':' ||
		       c == '/' ||
		       c == '=')
			 break;
		    if(bufptr && number && !isdigit(c) && !isalpha(c))
			 break;
		    if(!isdigit(c))
			 number = FALSE;
	       }
	       if(bufptr == buflen){
		    buflen *= 2;
		    buffer = (char *)realloc(buffer, buflen);
	       }
	       buffer[bufptr++] = c;
	  }
	  pushchar(c);
	  if(bufptr == buflen){
	       buflen *= 2;
	       buffer = (char *)realloc(buffer, buflen);
	  }
	  buffer[bufptr] = 0;
	  if(number){
	       int value = atoi(buffer);
	       free(buffer);
	       yylval.intval = value;
	       if(value < 256)
		    return BYTEVAL;
	       return INTEGER;
	  }

	  if(!quote)
	       for(i=0;keywords[i].name;i++)
		    if(!strcmp(buffer, keywords[i].name)){
			 free(buffer);
			 yylval.intval = keywords[i].token;
			 return keywords[i].token;
		    }
	  yylval.strval = buffer;
	  return STRING;
     }

     switch(c){
     case '<':
	  nc = fetchar();
	  if(nc == '='){
	       yylval.intval = LEQ;
	       return LEQ;
	  }
	  pushchar(nc);
	  break;
     case '>':
	  nc = fetchar();
	  if(nc == '='){
	       yylval.intval = GEQ;
	       return GEQ;
	  }
	  pushchar(nc);
	  break;
     case '!':
	  nc = fetchar();
	  if(nc == '='){
	       yylval.intval = NEQ;
	       return NEQ;
	  }
	  pushchar(nc);
	  break;
     case '&':
	  nc = fetchar();
	  if(nc == '&'){
	       yylval.intval = AND;
	       return AND;
	  }
	  pushchar(nc);
	  break;
     case '|':
	  nc = fetchar();
	  if(nc == '|'){
	       yylval.intval = OR;
	       return OR;
	  }
	  pushchar(nc);
	  break;
     default:
	  break;
     }
     yylval.intval = c;
     return c;
}
