141 lines
3.0 KiB
C
141 lines
3.0 KiB
C
|
|
/* MODULE HTLex.c
|
|
** LEXICAL ANALYSOR
|
|
**
|
|
** AUTHORS:
|
|
** AL Ari Luotonen luotonen@dxcern.cern.ch
|
|
**
|
|
** HISTORY:
|
|
**
|
|
**
|
|
** BUGS:
|
|
**
|
|
**
|
|
*/
|
|
#include "../config.h"
|
|
#include "HTAAUtil.h"
|
|
#include "HTLex.h" /* Implemented here */
|
|
|
|
|
|
/*
|
|
** Global variables
|
|
*/
|
|
PUBLIC char lex_buffer[40]; /* Read lexical string */
|
|
PUBLIC int lex_line = 1; /* Line number in source file */
|
|
|
|
|
|
/*
|
|
** Module-wide variables
|
|
*/
|
|
PRIVATE int lex_cnt;
|
|
PRIVATE BOOL lex_template;
|
|
PRIVATE LexItem lex_pushed_back = LEX_NONE;
|
|
PRIVATE FILE *cache = NULL;
|
|
|
|
|
|
PUBLIC void unlex ARGS1(LexItem, lex_item)
|
|
{
|
|
lex_pushed_back = lex_item;
|
|
}
|
|
|
|
|
|
PUBLIC LexItem lex ARGS1(FILE *, fp)
|
|
{
|
|
int ch;
|
|
|
|
if (fp != cache) { /* This cache doesn't work ok because the system */
|
|
cache = fp; /* often assign same FILE structure the next open */
|
|
lex_line = 1; /* file. So, if there are syntax errors in setup */
|
|
} /* files it may confuse things later on. */
|
|
|
|
if (lex_pushed_back != LEX_NONE) {
|
|
LexItem ret = lex_pushed_back;
|
|
lex_pushed_back = LEX_NONE;
|
|
return ret;
|
|
}
|
|
|
|
lex_cnt = 0;
|
|
lex_template = NO;
|
|
|
|
for(;;) {
|
|
switch (ch = getc(fp)) {
|
|
case EOF:
|
|
case ' ':
|
|
case '\t':
|
|
case '\r':
|
|
case '\n':
|
|
case ':':
|
|
case ',':
|
|
case '(':
|
|
case ')':
|
|
case '@':
|
|
if (lex_cnt > 0) {
|
|
if (ch != EOF) ungetc(ch,fp);
|
|
if (lex_template) return LEX_TMPL_STR;
|
|
else return LEX_ALPH_STR;
|
|
}
|
|
else switch(ch) {
|
|
case EOF: return LEX_EOF; break;
|
|
case '\n':
|
|
lex_line++; return LEX_REC_SEP; break;
|
|
case ':': return LEX_FIELD_SEP; break;
|
|
case ',': return LEX_ITEM_SEP; break;
|
|
case '(': return LEX_OPEN_PAREN; break;
|
|
case ')': return LEX_CLOSE_PAREN; break;
|
|
case '@': return LEX_AT_SIGN; break;
|
|
default: ; /* Leading white space ignored (SP,TAB,CR) */
|
|
}
|
|
break;
|
|
default:
|
|
lex_buffer[lex_cnt++] = ch;
|
|
lex_buffer[lex_cnt] = (char)0;
|
|
if ('*' == ch) lex_template = YES;
|
|
} /* switch ch */
|
|
} /* forever */
|
|
}
|
|
|
|
|
|
PUBLIC char *lex_verbose ARGS1(LexItem, lex_item)
|
|
{
|
|
static char msg[100];
|
|
|
|
switch (lex_item) {
|
|
case LEX_NONE: /* Internally used */
|
|
return "NO-LEX-ITEM";
|
|
break;
|
|
case LEX_EOF: /* End of file */
|
|
return "end-of-file";
|
|
break;
|
|
case LEX_REC_SEP: /* Record separator */
|
|
return "record separator (newline)";
|
|
break;
|
|
case LEX_FIELD_SEP: /* Field separator */
|
|
return "field separator ':'";
|
|
break;
|
|
case LEX_ITEM_SEP: /* List item separator */
|
|
return "item separator ','";
|
|
break;
|
|
case LEX_OPEN_PAREN: /* Group start tag */
|
|
return "'('";
|
|
break;
|
|
case LEX_CLOSE_PAREN: /* Group end tag */
|
|
return "')'";
|
|
break;
|
|
case LEX_AT_SIGN: /* Address qualifier */
|
|
return "address qualifier '@'";
|
|
break;
|
|
case LEX_ALPH_STR: /* Alphanumeric string */
|
|
sprintf(msg, "alphanumeric string '%s'", lex_buffer);
|
|
return msg;
|
|
break;
|
|
case LEX_TMPL_STR: /* Template string */
|
|
sprintf(msg, "template string '%s'", lex_buffer);
|
|
return msg;
|
|
break;
|
|
default:
|
|
return "UNKNOWN-LEX-ITEM";
|
|
break;
|
|
}
|
|
}
|
|
|