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