📄 conflex.c
字号:
/* conflex.c Lexical scanner for dhcpd config file... *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1995-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Internet Systems Consortium, Inc. * 950 Charter Street * Redwood City, CA 94063 * <info@isc.org> * http://www.isc.org/ * * This software has been written for Internet Systems Consortium * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. * To learn more about Internet Systems Consortium, see * ``http://www.isc.org/''. To learn more about Vixie Enterprises, * see ``http://www.vix.com''. To learn more about Nominum, Inc., see * ``http://www.nominum.com''. */#ifndef lintstatic char copyright[] ="$Id: conflex.c,v 1.92.2.7 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#include <ctype.h>static int get_char PROTO ((struct parse *));static enum dhcp_token get_token PROTO ((struct parse *));static void skip_to_eol PROTO ((struct parse *));static enum dhcp_token read_string PROTO ((struct parse *));static enum dhcp_token read_number PROTO ((int, struct parse *));static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));static enum dhcp_token intern PROTO ((char *, enum dhcp_token));isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp) struct parse **cfile; int file; char *inbuf; unsigned buflen; const char *name; int eolp;{ struct parse *tmp; tmp = dmalloc (sizeof (struct parse), MDL); if (!tmp) return ISC_R_NOMEMORY; memset (tmp, 0, sizeof *tmp); tmp -> token = 0; tmp -> tlname = name; tmp -> lpos = tmp -> line = 1; tmp -> cur_line = tmp -> line1; tmp -> prev_line = tmp -> line2; tmp -> token_line = tmp -> cur_line; tmp -> cur_line [0] = tmp -> prev_line [0] = 0; tmp -> warnings_occurred = 0; tmp -> file = file; tmp -> eol_token = eolp; tmp -> bufix = 0; tmp -> buflen = buflen; if (inbuf) { tmp -> bufsiz = 0; tmp -> inbuf = inbuf; } else { tmp -> inbuf = dmalloc (8192, MDL); if (!tmp -> inbuf) { dfree (tmp, MDL); return ISC_R_NOMEMORY; } tmp -> bufsiz = 8192; } *cfile = tmp; return ISC_R_SUCCESS;}isc_result_t end_parse (cfile) struct parse **cfile;{ if ((*cfile) -> bufsiz) dfree ((*cfile) -> inbuf, MDL); dfree (*cfile, MDL); *cfile = (struct parse *)0; return ISC_R_SUCCESS;}static int get_char (cfile) struct parse *cfile;{ /* My kingdom for WITH... */ int c; if (cfile -> bufix == cfile -> buflen) { if (cfile -> file != -1) { cfile -> buflen = read (cfile -> file, cfile -> inbuf, cfile -> bufsiz); if (cfile -> buflen == 0) { c = EOF; cfile -> bufix = 0; } else if (cfile -> buflen < 0) { c = EOF; cfile -> bufix = cfile -> buflen = 0; } else { c = cfile -> inbuf [0]; cfile -> bufix = 1; } } else c = EOF; } else { c = cfile -> inbuf [cfile -> bufix]; cfile -> bufix++; } if (!cfile -> ugflag) { if (c == EOL) { if (cfile -> cur_line == cfile -> line1) { cfile -> cur_line = cfile -> line2; cfile -> prev_line = cfile -> line1; } else { cfile -> cur_line = cfile -> line1; cfile -> prev_line = cfile -> line2; } cfile -> line++; cfile -> lpos = 1; cfile -> cur_line [0] = 0; } else if (c != EOF) { if (cfile -> lpos <= 80) { cfile -> cur_line [cfile -> lpos - 1] = c; cfile -> cur_line [cfile -> lpos] = 0; } cfile -> lpos++; } } else cfile -> ugflag = 0; return c; }static enum dhcp_token get_token (cfile) struct parse *cfile;{ int c; enum dhcp_token ttok; static char tb [2]; int l, p, u; do { l = cfile -> line; p = cfile -> lpos; u = cfile -> ugflag; c = get_char (cfile);#ifdef OLD_LEXER if (c == '\n' && p == 1 && !u && cfile -> comment_index < sizeof cfile -> comments) cfile -> comments [cfile -> comment_index++] = '\n';#endif if (!(c == '\n' && cfile -> eol_token) && isascii (c) && isspace (c)) continue; if (c == '#') {#ifdef OLD_LEXER if (cfile -> comment_index < sizeof cfile -> comments) cfile -> comments [cfile -> comment_index++] = '#';#endif skip_to_eol (cfile); continue; } if (c == '"') { cfile -> lexline = l; cfile -> lexchar = p; ttok = read_string (cfile); break; } if ((isascii (c) && isdigit (c)) || c == '-') { cfile -> lexline = l; cfile -> lexchar = p; ttok = read_number (c, cfile); break; } else if (isascii (c) && isalpha (c)) { cfile -> lexline = l; cfile -> lexchar = p; ttok = read_num_or_name (c, cfile); break; } else if (c == EOF) { ttok = END_OF_FILE; cfile -> tlen = 0; break; } else { cfile -> lexline = l; cfile -> lexchar = p; tb [0] = c; tb [1] = 0; cfile -> tval = tb; cfile -> tlen = 1; ttok = c; break; } } while (1); return ttok;}enum dhcp_token next_token (rval, rlen, cfile) const char **rval; unsigned *rlen; struct parse *cfile;{ int rv; if (cfile -> token) { if (cfile -> lexline != cfile -> tline) cfile -> token_line = cfile -> cur_line; cfile -> lexchar = cfile -> tlpos; cfile -> lexline = cfile -> tline; rv = cfile -> token; cfile -> token = 0; } else { rv = get_token (cfile); cfile -> token_line = cfile -> cur_line; } if (rval) *rval = cfile -> tval; if (rlen) *rlen = cfile -> tlen;#ifdef DEBUG_TOKENS fprintf (stderr, "%s:%d ", cfile -> tval, rv);#endif return rv;}enum dhcp_token peek_token (rval, rlen, cfile) const char **rval; unsigned int *rlen; struct parse *cfile;{ int x; if (!cfile -> token) { cfile -> tlpos = cfile -> lexchar; cfile -> tline = cfile -> lexline; cfile -> token = get_token (cfile); if (cfile -> lexline != cfile -> tline) cfile -> token_line = cfile -> prev_line; x = cfile -> lexchar; cfile -> lexchar = cfile -> tlpos; cfile -> tlpos = x; x = cfile -> lexline; cfile -> lexline = cfile -> tline; cfile -> tline = x; } if (rval) *rval = cfile -> tval; if (rlen) *rlen = cfile -> tlen;#ifdef DEBUG_TOKENS fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);#endif return cfile -> token;}static void skip_to_eol (cfile) struct parse *cfile;{ int c; do { c = get_char (cfile); if (c == EOF) return;#ifdef OLD_LEXER if (cfile -> comment_index < sizeof (cfile -> comments)) comments [cfile -> comment_index++] = c;#endif if (c == EOL) { return; } } while (1);}static enum dhcp_token read_string (cfile) struct parse *cfile;{ int i; int bs = 0; int c; int value; int hex; for (i = 0; i < sizeof cfile -> tokbuf; i++) { again: c = get_char (cfile); if (c == EOF) { parse_warn (cfile, "eof in string constant"); break; } if (bs == 1) { switch (c) { case 't': cfile -> tokbuf [i] = '\t'; break; case 'r': cfile -> tokbuf [i] = '\r'; break; case 'n': cfile -> tokbuf [i] = '\n'; break; case 'b': cfile -> tokbuf [i] = '\b'; break; case '0': case '1': case '2': case '3': hex = 0; value = c - '0'; ++bs; goto again; case 'x': hex = 1; value = 0; ++bs; goto again; default: cfile -> tokbuf [i] = c; bs = 0; break; } bs = 0; } else if (bs > 1) { if (hex) { if (c >= '0' && c <= '9') { value = value * 16 + (c - '0'); } else if (c >= 'a' && c <= 'f') { value = value * 16 + (c - 'a' + 10); } else if (c >= 'A' && c <= 'F') { value = value * 16 + (c - 'A' + 10); } else { parse_warn (cfile, "invalid hex digit: %x", c); bs = 0; continue; } if (++bs == 4) { cfile -> tokbuf [i] = value; bs = 0; } else goto again; } else { if (c >= '0' && c <= '9') { value = value * 8 + (c - '0'); } else { if (value != 0) { parse_warn (cfile, "invalid octal digit %x", c); continue; } else cfile -> tokbuf [i] = 0; bs = 0; } if (++bs == 4) { cfile -> tokbuf [i] = value; bs = 0; } else goto again; } } else if (c == '\\') { bs = 1; goto again; } else if (c == '"') break; else cfile -> tokbuf [i] = c; } /* Normally, I'd feel guilty about this, but we're talking about strings that'll fit in a DHCP packet here... */ if (i == sizeof cfile -> tokbuf) { parse_warn (cfile, "string constant larger than internal buffer"); --i; } cfile -> tokbuf [i] = 0; cfile -> tlen = i; cfile -> tval = cfile -> tokbuf; return STRING;}static enum dhcp_token read_number (c, cfile) int c; struct parse *cfile;{ int seenx = 0; int i = 0; int token = NUMBER; cfile -> tokbuf [i++] = c; for (; i < sizeof cfile -> tokbuf; i++) { c = get_char (cfile); if (!seenx && c == 'x') { seenx = 1;#ifndef OLD_LEXER } else if (isascii (c) && !isxdigit (c) && (c == '-' || c == '_' || isalpha (c))) { token = NAME; } else if (isascii (c) && !isdigit (c) && isxdigit (c)) { token = NUMBER_OR_NAME;#endif } else if (!isascii (c) || !isxdigit (c)) { if (c != EOF) { cfile -> bufix--; cfile -> ugflag = 1; } break; } cfile -> tokbuf [i] = c; } if (i == sizeof cfile -> tokbuf) { parse_warn (cfile, "numeric token larger than internal buffer"); --i; } cfile -> tokbuf [i] = 0; cfile -> tlen = i; cfile -> tval = cfile -> tokbuf; return token;}static enum dhcp_token read_num_or_name (c, cfile) int c; struct parse *cfile;{ int i = 0; enum dhcp_token rv = NUMBER_OR_NAME; cfile -> tokbuf [i++] = c; for (; i < sizeof cfile -> tokbuf; i++) { c = get_char (cfile); if (!isascii (c) || (c != '-' && c != '_' && !isalnum (c))) { if (c != EOF) { cfile -> bufix--; cfile -> ugflag = 1; } break; } if (!isxdigit (c)) rv = NAME; cfile -> tokbuf [i] = c; } if (i == sizeof cfile -> tokbuf) { parse_warn (cfile, "token larger than internal buffer"); --i; } cfile -> tokbuf [i] = 0; cfile -> tlen = i; cfile -> tval = cfile -> tokbuf; return intern (cfile -> tval, rv);}static enum dhcp_token intern (atom, dfv) char *atom; enum dhcp_token dfv;{ if (!isascii (atom [0])) return dfv; switch (tolower (atom [0])) { case '-': if (atom [1] == 0) return MINUS; break; case 'a': if (!strncasecmp (atom + 1, "uth", 3)) { if (!strncasecmp (atom + 3, "uthenticat", 10)) { if (!strcasecmp (atom + 13, "ed")) return AUTHENTICATED; if (!strcasecmp (atom + 13, "ion")) return AUTHENTICATION; break; } if (!strcasecmp (atom + 1, "uthoritative")) return AUTHORITATIVE; break; } if (!strcasecmp (atom + 1, "nd")) return AND; if (!strcasecmp (atom + 1, "ppend")) return APPEND; if (!strcasecmp (atom + 1, "llow")) return ALLOW; if (!strcasecmp (atom + 1, "lias")) return ALIAS; if (!strcasecmp (atom + 1, "lgorithm")) return ALGORITHM; if (!strcasecmp (atom + 1, "bandoned")) return TOKEN_ABANDONED; if (!strcasecmp (atom + 1, "dd")) return TOKEN_ADD; if (!strcasecmp (atom + 1, "ll")) return ALL; if (!strcasecmp (atom + 1, "t")) return AT; if (!strcasecmp (atom + 1, "rray")) return ARRAY; if (!strcasecmp (atom + 1, "ddress")) return ADDRESS; if (!strcasecmp (atom + 1, "ctive")) return TOKEN_ACTIVE; break; case 'b': if (!strcasecmp (atom + 1, "ackup")) return TOKEN_BACKUP; if (!strcasecmp (atom + 1, "ootp")) return TOKEN_BOOTP; if (!strcasecmp (atom + 1, "inding")) return BINDING;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -