1 
2 /* MODULE							HTLex.c
3  *		LEXICAL ANALYSOR
4  *
5  * AUTHORS:
6  *	AL	Ari Luotonen	luotonen@dxcern.cern.ch
7  *
8  * HISTORY:
9  *
10  *
11  * BUGS:
12  *
13  *
14  */
15 
16 #include <HTUtils.h>
17 
18 #include <HTLex.h>		/* Implemented here */
19 
20 #include <LYLeaks.h>
21 
22 /*
23  * Global variables
24  */
25 char HTlex_buffer[40];		/* Read lexical string          */
26 int HTlex_line = 1;		/* Line number in source file   */
27 
28 /*
29  * Module-wide variables
30  */
31 static int lex_cnt;
32 static BOOL lex_template;
33 static LexItem lex_pushed_back = LEX_NONE;
34 static FILE *cache = NULL;
35 
unlex(LexItem lex_item)36 void unlex(LexItem lex_item)
37 {
38     lex_pushed_back = lex_item;
39 }
40 
lex(FILE * fp)41 LexItem lex(FILE *fp)
42 {
43     int ch = 0;
44 
45     if (fp != cache) {		/* This cache doesn't work ok because the system  */
46 	cache = fp;		/* often assign same FILE structure the next open */
47 	HTlex_line = 1;		/* file.  So, if there are syntax errors in setup *
48 				   files it may confuse things later on.      */
49     }
50     if (lex_pushed_back != LEX_NONE) {
51 	LexItem ret = lex_pushed_back;
52 
53 	lex_pushed_back = LEX_NONE;
54 	return ret;
55     }
56 
57     lex_cnt = 0;
58     lex_template = NO;
59 
60     for (;;) {
61 	switch (ch = getc(fp)) {
62 	case EOF:
63 	case ' ':
64 	case '\t':
65 	case '\r':
66 	case '\n':
67 	case ':':
68 	case ',':
69 	case '(':
70 	case ')':
71 	case '@':
72 	    if (lex_cnt > 0) {
73 		if (ch != EOF)
74 		    ungetc(ch, fp);
75 		if (lex_template)
76 		    return LEX_TMPL_STR;
77 		else
78 		    return LEX_ALPH_STR;
79 	    } else
80 		switch (ch) {
81 		case EOF:
82 		    return LEX_EOF;
83 		case '\n':
84 		    HTlex_line++;
85 		    return LEX_REC_SEP;
86 		case ':':
87 		    return LEX_FIELD_SEP;
88 		case ',':
89 		    return LEX_ITEM_SEP;
90 		case '(':
91 		    return LEX_OPEN_PAREN;
92 		case ')':
93 		    return LEX_CLOSE_PAREN;
94 		case '@':
95 		    return LEX_AT_SIGN;
96 		default:	/* Leading white space ignored (SP,TAB,CR) */
97 		    break;
98 		}
99 	    break;
100 	default:
101 	    if (lex_cnt < (int) (sizeof(HTlex_buffer) - 1))
102 		HTlex_buffer[lex_cnt++] = (char) ch;
103 	    HTlex_buffer[lex_cnt] = '\0';
104 	    if ('*' == ch)
105 		lex_template = YES;
106 	}			/* switch ch */
107     }				/* forever */
108 }
109 
lex_verbose(LexItem lex_item)110 const char *lex_verbose(LexItem lex_item)
111 {
112     static char msg[sizeof(HTlex_buffer) + 30];		/* @@@@@@@@ */
113 
114     switch (lex_item) {
115     case LEX_NONE:		/* Internally used      */
116 	return "NO-LEX-ITEM";
117     case LEX_EOF:		/* End of file          */
118 	return "end-of-file";
119     case LEX_REC_SEP:		/* Record separator     */
120 	return "record separator (newline)";
121     case LEX_FIELD_SEP:	/* Field separator      */
122 	return "field separator ':'";
123     case LEX_ITEM_SEP:		/* List item separator  */
124 	return "item separator ','";
125     case LEX_OPEN_PAREN:	/* Group start tag      */
126 	return "'('";
127     case LEX_CLOSE_PAREN:	/* Group end tag        */
128 	return "')'";
129     case LEX_AT_SIGN:		/* Address qualifier    */
130 	return "address qualifier '@'";
131     case LEX_ALPH_STR:		/* Alphanumeric string  */
132 	sprintf(msg, "alphanumeric string '%.*s'",
133 		(int) sizeof(HTlex_buffer), HTlex_buffer);
134 	return msg;
135     case LEX_TMPL_STR:		/* Template string      */
136 	sprintf(msg, "template string '%.*s'",
137 		(int) sizeof(HTlex_buffer), HTlex_buffer);
138 	return msg;
139     default:
140 	return "UNKNOWN-LEX-ITEM";
141     }
142 }
143