x86_64: Fix a warning.
[dragonfly.git] / usr.sbin / atm / scspd / scsp_config_lex.c
blob79ccc480cf489ae4da77683a5d0e81e4b7cdcb6a
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_config_lex.c,v 1.3 1999/08/28 01:15:32 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_config_lex.c,v 1.3 2003/11/15 20:33:43 eirikn Exp $
31 * Server Cache Synchronization Protocol (SCSP) Support
32 * ----------------------------------------------------
34 * Parse a configuration file into tokens
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/socket.h>
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <netatm/port.h>
44 #include <netatm/queue.h>
45 #include <netatm/atm.h>
46 #include <netatm/atm_if.h>
47 #include <netatm/atm_sap.h>
48 #include <netatm/atm_sys.h>
49 #include <netatm/atm_ioctl.h>
51 #include <ctype.h>
52 #include <errno.h>
53 #include <libatm.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <syslog.h>
59 #include "scsp_msg.h"
60 #include "scsp_if.h"
61 #include "scsp_var.h"
62 #include "scsp_config_parse.h"
65 * Global variables
67 int parse_line = 1;
70 * Local definitions
72 #define TOK_MAX_LEN 128
75 * Character classes
77 #define CHAR_INVALID 0 /* Not allowed */
78 #define CHAR_ALPHA 1 /* G-W, Y, Z */
79 #define CHAR_HEX_DIGIT 2 /* A-F */
80 #define CHAR_X 3 /* X */
81 #define CHAR_0 4 /* '0' */
82 #define CHAR_DIGIT 5 /* 1-9 */
83 #define CHAR_SPACE 6 /* space, tab */
84 #define CHAR_DECIMAL 7 /* period */
85 #define CHAR_SLASH 8 /* slash */
86 #define CHAR_ASTERISK 9 /* asterisk */
87 #define CHAR_HASH 10 /* pound sign */
88 #define CHAR_SPECIAL 11 /* semicolon, braces */
89 #define CHAR_MISC 12 /* chars allowd in file names */
90 #define CHAR_EOL 13 /* new line */
91 #define CHAR_EOF 14 /* EOF */
92 #define CHAR_CNT CHAR_EOF + 1
95 * Character class table (initialized by init_class_tbl())
97 static char class_tbl[128];
100 * State table element structure
102 struct state_entry {
103 int action;
104 int next;
108 * Scanner states
110 #define TS_INIT 0
111 #define TS_ALPHA 1
112 #define TS_INT_1 2
113 #define TS_INT 3
114 #define TS_HEX 4
115 #define TS_SLASH_1 5
116 #define TS_COMMENT 6
117 #define TS_COMMENT_1 7
118 #define TS_FLUSH 8
119 #define TS_HEX_1 9
120 #define TS_CNT TS_HEX_1 + 1
123 * Token scanner state table
125 static struct state_entry token_state_tbl[CHAR_CNT][TS_CNT] = {
126 /* 0 1 2 3 4 5 6 7 8 9 */
127 /* bad */{{2,0},{2,0},{2,0},{2,0},{2,0},{2,0},{0,6},{0,6},{0,8},{2,0}},
128 /* g-z */{{1,1},{1,1},{1,1},{1,1},{2,0},{1,1},{0,6},{0,6},{0,8},{2,0}},
129 /* a-f */{{1,1},{1,1},{1,1},{1,1},{1,9},{1,1},{0,6},{0,6},{0,8},{1,4}},
130 /* x */{{1,1},{1,1},{1,4},{1,4},{2,0},{1,1},{0,6},{0,6},{0,8},{2,0}},
131 /* 0 */{{1,2},{1,1},{1,3},{1,3},{1,9},{1,1},{0,6},{0,6},{0,8},{1,4}},
132 /* 1-9 */{{1,3},{1,1},{1,3},{1,3},{1,9},{1,1},{0,6},{0,6},{0,8},{1,4}},
133 /* sp */{{0,0},{6,0},{8,0},{8,0},{7,0},{6,0},{0,6},{0,6},{0,8},{2,0}},
134 /* . */{{2,0},{1,1},{1,1},{1,1},{1,4},{1,1},{0,6},{0,6},{0,8},{2,0}},
135 /* / */{{1,5},{1,1},{1,1},{1,1},{7,0},{4,8},{0,6},{0,0},{0,8},{2,0}},
136 /* * */{{2,0},{6,0},{8,0},{8,0},{7,0},{4,6},{0,7},{0,7},{0,8},{2,0}},
137 /* # */{{0,8},{6,0},{8,0},{8,0},{7,0},{6,0},{0,6},{0,6},{0,8},{2,0}},
138 /* ;{} */{{3,0},{6,0},{8,0},{8,0},{7,0},{6,0},{0,6},{0,6},{0,8},{2,0}},
139 /* Msc */{{2,0},{1,1},{1,1},{1,1},{2,0},{1,1},{0,6},{0,6},{0,8},{2,0}},
140 /* EOL */{{0,0},{6,0},{8,0},{8,0},{7,0},{6,0},{0,6},{0,6},{0,0},{2,0}},
141 /* EOF */{{9,0},{6,0},{8,0},{8,0},{7,0},{6,0},{2,0},{2,0},{9,0},{2,0}},
146 * Reserved words
148 static struct {
149 char *word;
150 int token;
151 } rsvd_word_tbl[] = {
152 { "ATMaddr", TOK_DCS_ADDR },
153 { "ATMARP", TOK_ATMARP },
154 { "CAReXmitInt", TOK_DCS_CA_REXMIT_INT },
155 { "CSUSReXmitInt", TOK_DCS_CSUS_REXMIT_INT },
156 { "CSUReXmitInt", TOK_DCS_CSU_REXMIT_INT },
157 { "CSUReXmitMax", TOK_DCS_CSU_REXMIT_MAX },
158 { "DCS", TOK_DCS },
159 { "DHCP", TOK_DHCP },
160 { "familyID", TOK_FAMILY },
161 { "file", TOK_LFN },
162 { "hops", TOK_DCS_HOP_CNT },
163 { "HelloDead", TOK_DCS_HELLO_DF },
164 { "HelloInt", TOK_DCS_HELLO_INT },
165 { "ID", TOK_DCS_ID },
166 { "LNNI", TOK_LNNI },
167 { "log", TOK_LOG },
168 { "MARS", TOK_MARS },
169 { "netif", TOK_NETIF },
170 { "NHRP", TOK_NHRP },
171 { "protocol", TOK_PROTOCOL },
172 { "server", TOK_SERVER },
173 { "ServerGroupID", TOK_SRVGRP },
174 { "syslog", TOK_SYSLOG },
175 { NULL, 0 },
180 * Copy a character string
182 * Make a copy of a character string, using strdup. If strdup fails,
183 * meaning we're out of memory, then print an error message and exit.
185 * Arguments:
186 * s string to be copied
188 * Returns:
189 * char * pointer to area provided by strdup
192 static char *
193 copy_buffer(char *s)
195 char *t;
197 t = strdup(s);
199 if (!t) {
200 fprintf(stderr, "%s: strdup failed\n", prog);
201 exit(1);
204 return(t);
209 * Push a character back onto the input stream.
211 * Arguments:
212 * c character to be pushed
214 * Returns:
215 * none
218 static void
219 push_char(char c)
221 if (c == '\n')
222 parse_line--;
224 ungetc(c, cfg_file);
229 * Initialize the character class table.
231 * Set each entry in the character class table to the class
232 * corresponding to the character.
234 * Arguments:
235 * tbl pointer to table to be initialized
237 * Returns:
238 * None
240 static void
241 init_class_tbl(char *tbl)
243 int i;
244 char c;
247 * Set up the table for all ASCII characters
249 for (i=0; isascii((char)i); i++) {
251 * Clear entry
253 tbl[i] = CHAR_INVALID;
256 * Set entries depending on character type
258 c = (char)i;
259 if (c == 'a' || c == 'b' || c == 'c' ||
260 c == 'd' || c == 'e' || c == 'f' ||
261 c == 'A' || c == 'B' || c == 'C' ||
262 c == 'D' || c == 'E' || c == 'F')
263 tbl[i] = CHAR_HEX_DIGIT;
264 else if (c == 'x' || c == 'X')
265 tbl[i] = CHAR_X;
266 else if (isalpha(c))
267 tbl[i] = CHAR_ALPHA;
268 else if (c == '0')
269 tbl[i] = CHAR_0;
270 else if (isdigit(c))
271 tbl[i] = CHAR_DIGIT;
272 else if (c == '\n')
273 tbl[i] = CHAR_EOL;
274 else if (c == ' ' || c == '\t')
275 tbl[i] = CHAR_SPACE;
276 else if (c == '#')
277 tbl[i] = CHAR_HASH;
278 else if (c == '*')
279 tbl[i] = CHAR_ASTERISK;
280 else if (c == '.')
281 tbl[i] = CHAR_DECIMAL;
282 else if (c == '/')
283 tbl[i] = CHAR_SLASH;
284 else if (c == ';' || c == '{' || c == '}')
285 tbl[i] = CHAR_SPECIAL;
286 else if (c == '-' || c == '_' || c == '&' || c == '@' ||
287 c == '~')
288 tbl[i] = CHAR_MISC;
294 * Get the class of a character.
296 * Arguments:
297 * c character being scanned
299 * Returns:
300 * int character class
302 static int
303 char_class(char c)
305 int class = CHAR_INVALID;
307 if (c == EOF) {
308 class = CHAR_EOF;
309 } else if (c < 0 || !isascii(c)) {
310 class = CHAR_INVALID;
311 } else {
312 class = class_tbl[(int)c];
315 return(class);
320 * Print an error message when the scanner finds an error
322 * Arguments:
323 * c character on which the error was recognized
324 * state scanner state at error
326 * Returns:
327 * None
329 static void
330 scan_error(char c, int state)
333 * Check for invalid character
335 if (char_class(c) == CHAR_INVALID) {
336 parse_error("Invalid character 0x%x encountered",
338 return;
342 * Check for unexpected EOF
344 if (char_class(c) == CHAR_EOF) {
345 parse_error("Unexpected end of file");
346 return;
350 * Error depends on state
352 switch(state) {
353 case TS_INIT:
354 parse_error("Syntax error at '%c'", c);
355 break;
356 case TS_ALPHA:
357 case TS_INT_1:
358 case TS_INT:
359 case TS_SLASH_1:
360 case TS_COMMENT:
361 case TS_COMMENT_1:
362 case TS_FLUSH:
363 parse_error("Syntax error");
364 break;
365 case TS_HEX:
366 case TS_HEX_1:
367 parse_error("Syntax error in hex string");
368 break;
374 * Assemble a token
376 * Read a character at a time from the input file, assembling the
377 * characters into tokens as specified by the token scanner state
378 * table. Return the completed token.
380 * Arguments:
381 * None
383 * Returns:
384 * token the type of the token found
387 yylex(void)
389 int i, state;
390 char c, token_buffer[TOK_MAX_LEN];
393 * Initialize
395 if (class_tbl['A'] != CHAR_HEX_DIGIT)
396 init_class_tbl(class_tbl);
397 state = TS_INIT;
398 UM_ZERO(token_buffer, sizeof(token_buffer));
399 UM_ZERO(&yylval, sizeof(yylval));
402 * Handle a character at a time until a token is built
404 while(1) {
406 * Read a character from the input file.
408 c = (char)getc(cfg_file);
409 if (c == '\n') {
410 parse_line++;
413 #ifdef NOTDEF
414 printf("token_state: state=%d, char=%c, class=%d, action=%d, next=%d\n",
415 state,
417 char_class(c),
418 token_state_tbl[char_class][state].action,
419 token_state_tbl[char_class][state].next);
420 #endif
423 * Perform an action based on the state table
425 switch(token_state_tbl[char_class(c)][state].action) {
426 case 0:
428 * Ignore the character
430 break;
431 case 1:
433 * Add character to buffer
435 if (strlen(token_buffer) < TOK_MAX_LEN) {
436 token_buffer[strlen(token_buffer)] = c;
438 break;
439 case 2:
441 * Error--print a message and start over
443 scan_error(c, state);
444 break;
445 case 3:
447 * Return special character
449 return(c);
450 break;
451 case 4:
453 * Clear the token buffer
455 UM_ZERO(token_buffer, sizeof(token_buffer));
456 break;
457 case 5:
459 * Not used
461 break;
462 case 6:
464 * Return character token
466 push_char(c);
469 * Check for reserved words
471 for (i=0; rsvd_word_tbl[i].word; i++) {
472 if (strcasecmp(token_buffer,
473 rsvd_word_tbl[i].word) == 0)
474 break;
476 if (rsvd_word_tbl[i].word) {
477 return(rsvd_word_tbl[i].token);
481 * Word isn't reserved, return alpha string
483 yylval.tv_alpha = copy_buffer(token_buffer);
484 return(TOK_NAME);
485 break;
486 case 7:
488 * Return hex string (ATM address)
490 push_char(c);
491 yylval.tv_hex = copy_buffer(token_buffer);
492 return(TOK_HEX);
493 break;
494 case 8:
496 * Return integer
498 push_char(c);
499 yylval.tv_int = atoi(token_buffer);
500 return(TOK_INTEGER);
501 break;
502 case 9:
504 * Return EOF
506 return(0);
507 break;
508 default:
509 fprintf(stderr, "Invalid action indicator, state=%d, char=0x%02x\n",
510 state, c);
511 break;
515 * Set the next state and bump to the next character
517 state = token_state_tbl[char_class(c)][state].next;