Annotation of embedaddon/dhcp/common/conflex.c, revision 1.1
1.1 ! misho 1: /* conflex.c
! 2:
! 3: Lexical scanner for dhcpd config file... */
! 4:
! 5: /*
! 6: * Copyright (c) 2004-2009,2011 by Internet Systems Consortium, Inc. ("ISC")
! 7: * Copyright (c) 1995-2003 by Internet Software Consortium
! 8: *
! 9: * Permission to use, copy, modify, and distribute this software for any
! 10: * purpose with or without fee is hereby granted, provided that the above
! 11: * copyright notice and this permission notice appear in all copies.
! 12: *
! 13: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
! 14: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 15: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
! 16: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 17: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 18: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 19: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 20: *
! 21: * Internet Systems Consortium, Inc.
! 22: * 950 Charter Street
! 23: * Redwood City, CA 94063
! 24: * <info@isc.org>
! 25: * https://www.isc.org/
! 26: *
! 27: * This software has been written for Internet Systems Consortium
! 28: * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
! 29: * To learn more about Internet Systems Consortium, see
! 30: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
! 31: * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
! 32: * ``http://www.nominum.com''.
! 33: */
! 34:
! 35: #include "dhcpd.h"
! 36: #include <ctype.h>
! 37:
! 38: static int get_char (struct parse *);
! 39: static void unget_char(struct parse *, int);
! 40: static void skip_to_eol (struct parse *);
! 41: static enum dhcp_token read_whitespace(int c, struct parse *cfile);
! 42: static enum dhcp_token read_string (struct parse *);
! 43: static enum dhcp_token read_number (int, struct parse *);
! 44: static enum dhcp_token read_num_or_name (int, struct parse *);
! 45: static enum dhcp_token intern (char *, enum dhcp_token);
! 46:
! 47: isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
! 48: struct parse **cfile;
! 49: int file;
! 50: char *inbuf;
! 51: unsigned buflen;
! 52: const char *name;
! 53: int eolp;
! 54: {
! 55: isc_result_t status = ISC_R_SUCCESS;
! 56: struct parse *tmp;
! 57:
! 58: tmp = dmalloc(sizeof(struct parse), MDL);
! 59: if (tmp == NULL) {
! 60: return (ISC_R_NOMEMORY);
! 61: }
! 62:
! 63: /*
! 64: * We don't need to initialize things to zero here, since
! 65: * dmalloc() returns memory that is set to zero.
! 66: */
! 67: tmp->tlname = name;
! 68: tmp->lpos = tmp -> line = 1;
! 69: tmp->cur_line = tmp->line1;
! 70: tmp->prev_line = tmp->line2;
! 71: tmp->token_line = tmp->cur_line;
! 72: tmp->cur_line[0] = tmp->prev_line[0] = 0;
! 73: tmp->file = file;
! 74: tmp->eol_token = eolp;
! 75:
! 76: if (inbuf != NULL) {
! 77: tmp->inbuf = inbuf;
! 78: tmp->buflen = buflen;
! 79: tmp->bufsiz = 0;
! 80: } else {
! 81: struct stat sb;
! 82:
! 83: if (fstat(file, &sb) < 0) {
! 84: status = ISC_R_IOERROR;
! 85: goto cleanup;
! 86: }
! 87:
! 88: if (sb.st_size == 0)
! 89: goto cleanup;
! 90:
! 91: tmp->bufsiz = tmp->buflen = (size_t) sb.st_size;
! 92: tmp->inbuf = mmap(NULL, tmp->bufsiz, PROT_READ, MAP_SHARED,
! 93: file, 0);
! 94:
! 95: if (tmp->inbuf == MAP_FAILED) {
! 96: status = ISC_R_IOERROR;
! 97: goto cleanup;
! 98: }
! 99: }
! 100:
! 101: *cfile = tmp;
! 102: return (ISC_R_SUCCESS);
! 103:
! 104: cleanup:
! 105: dfree(tmp, MDL);
! 106: return (status);
! 107: }
! 108:
! 109: isc_result_t end_parse (cfile)
! 110: struct parse **cfile;
! 111: {
! 112: /* "Memory" config files have no file. */
! 113: if ((*cfile)->file != -1) {
! 114: munmap((*cfile)->inbuf, (*cfile)->bufsiz);
! 115: close((*cfile)->file);
! 116: }
! 117:
! 118: if ((*cfile)->saved_state != NULL) {
! 119: dfree((*cfile)->saved_state, MDL);
! 120: }
! 121:
! 122: dfree(*cfile, MDL);
! 123: *cfile = NULL;
! 124: return ISC_R_SUCCESS;
! 125: }
! 126:
! 127: /*
! 128: * Save the current state of the parser.
! 129: *
! 130: * Only one state may be saved. Any previous saved state is
! 131: * lost.
! 132: */
! 133: isc_result_t
! 134: save_parse_state(struct parse *cfile) {
! 135: /*
! 136: * Free any previous saved state.
! 137: */
! 138: if (cfile->saved_state != NULL) {
! 139: dfree(cfile->saved_state, MDL);
! 140: }
! 141:
! 142: /*
! 143: * Save our current state.
! 144: */
! 145: cfile->saved_state = dmalloc(sizeof(struct parse), MDL);
! 146: if (cfile->saved_state == NULL) {
! 147: return ISC_R_NOMEMORY;
! 148: }
! 149: memcpy(cfile->saved_state, cfile, sizeof(*cfile));
! 150: return ISC_R_SUCCESS;
! 151: }
! 152:
! 153: /*
! 154: * Return the parser to the previous saved state.
! 155: *
! 156: * You must call save_parse_state() before calling
! 157: * restore_parse_state(), but you can call restore_parse_state() any
! 158: * number of times after that.
! 159: */
! 160: isc_result_t
! 161: restore_parse_state(struct parse *cfile) {
! 162: struct parse *saved_state;
! 163:
! 164: if (cfile->saved_state == NULL) {
! 165: return ISC_R_NOTYET;
! 166: }
! 167:
! 168: saved_state = cfile->saved_state;
! 169: memcpy(cfile, saved_state, sizeof(*cfile));
! 170: cfile->saved_state = saved_state;
! 171: return ISC_R_SUCCESS;
! 172: }
! 173:
! 174: static int get_char (cfile)
! 175: struct parse *cfile;
! 176: {
! 177: /* My kingdom for WITH... */
! 178: int c;
! 179:
! 180: if (cfile->bufix == cfile->buflen)
! 181: c = EOF;
! 182: else {
! 183: c = cfile->inbuf [cfile->bufix];
! 184: cfile->bufix++;
! 185: }
! 186:
! 187: if (!cfile->ugflag) {
! 188: if (c == EOL) {
! 189: if (cfile->cur_line == cfile->line1) {
! 190: cfile->cur_line = cfile->line2;
! 191: cfile->prev_line = cfile->line1;
! 192: } else {
! 193: cfile->cur_line = cfile->line1;
! 194: cfile->prev_line = cfile->line2;
! 195: }
! 196: cfile->line++;
! 197: cfile->lpos = 1;
! 198: cfile->cur_line [0] = 0;
! 199: } else if (c != EOF) {
! 200: if (cfile->lpos <= 80) {
! 201: cfile->cur_line [cfile->lpos - 1] = c;
! 202: cfile->cur_line [cfile->lpos] = 0;
! 203: }
! 204: cfile->lpos++;
! 205: }
! 206: } else
! 207: cfile->ugflag = 0;
! 208: return c;
! 209: }
! 210:
! 211: /*
! 212: * Return a character to our input buffer.
! 213: */
! 214: static void
! 215: unget_char(struct parse *cfile, int c) {
! 216: if (c != EOF) {
! 217: cfile->bufix--;
! 218: cfile->ugflag = 1; /* do not put characters into
! 219: our error buffer on the next
! 220: call to get_char() */
! 221: }
! 222: }
! 223:
! 224: /*
! 225: * GENERAL NOTE ABOUT TOKENS
! 226: *
! 227: * We normally only want non-whitespace tokens. There are some
! 228: * circumstances where we *do* want to see whitespace (for example
! 229: * when parsing IPv6 addresses).
! 230: *
! 231: * Generally we use the next_token() function to read tokens. This
! 232: * in turn calls get_next_token, which does *not* return tokens for
! 233: * whitespace. Rather, it skips these.
! 234: *
! 235: * When we need to see whitespace, we us next_raw_token(), which also
! 236: * returns the WHITESPACE token.
! 237: *
! 238: * The peek_token() and peek_raw_token() functions work as expected.
! 239: *
! 240: * Warning: if you invoke peek_token(), then if there is a whitespace
! 241: * token, it will be lost, and subsequent use of next_raw_token() or
! 242: * peek_raw_token() will NOT see it.
! 243: */
! 244:
! 245: static enum dhcp_token
! 246: get_raw_token(struct parse *cfile) {
! 247: int c;
! 248: enum dhcp_token ttok;
! 249: static char tb [2];
! 250: int l, p;
! 251:
! 252: do {
! 253: l = cfile -> line;
! 254: p = cfile -> lpos;
! 255:
! 256: c = get_char (cfile);
! 257: if (!((c == '\n') && cfile->eol_token) &&
! 258: isascii(c) && isspace(c)) {
! 259: ttok = read_whitespace(c, cfile);
! 260: break;
! 261: }
! 262: if (c == '#') {
! 263: skip_to_eol (cfile);
! 264: continue;
! 265: }
! 266: if (c == '"') {
! 267: cfile -> lexline = l;
! 268: cfile -> lexchar = p;
! 269: ttok = read_string (cfile);
! 270: break;
! 271: }
! 272: if ((isascii (c) && isdigit (c)) || c == '-') {
! 273: cfile -> lexline = l;
! 274: cfile -> lexchar = p;
! 275: ttok = read_number (c, cfile);
! 276: break;
! 277: } else if (isascii (c) && isalpha (c)) {
! 278: cfile -> lexline = l;
! 279: cfile -> lexchar = p;
! 280: ttok = read_num_or_name (c, cfile);
! 281: break;
! 282: } else if (c == EOF) {
! 283: ttok = END_OF_FILE;
! 284: cfile -> tlen = 0;
! 285: break;
! 286: } else {
! 287: cfile -> lexline = l;
! 288: cfile -> lexchar = p;
! 289: tb [0] = c;
! 290: tb [1] = 0;
! 291: cfile -> tval = tb;
! 292: cfile -> tlen = 1;
! 293: ttok = c;
! 294: break;
! 295: }
! 296: } while (1);
! 297: return ttok;
! 298: }
! 299:
! 300: /*
! 301: * The get_next_token() function consumes the next token and
! 302: * returns it to the caller.
! 303: *
! 304: * Since the code is almost the same for "normal" and "raw"
! 305: * input, we pass a flag to alter the way it works.
! 306: */
! 307:
! 308: static enum dhcp_token
! 309: get_next_token(const char **rval, unsigned *rlen,
! 310: struct parse *cfile, isc_boolean_t raw) {
! 311: int rv;
! 312:
! 313: if (cfile -> token) {
! 314: if (cfile -> lexline != cfile -> tline)
! 315: cfile -> token_line = cfile -> cur_line;
! 316: cfile -> lexchar = cfile -> tlpos;
! 317: cfile -> lexline = cfile -> tline;
! 318: rv = cfile -> token;
! 319: cfile -> token = 0;
! 320: } else {
! 321: rv = get_raw_token(cfile);
! 322: cfile -> token_line = cfile -> cur_line;
! 323: }
! 324:
! 325: if (!raw) {
! 326: while (rv == WHITESPACE) {
! 327: rv = get_raw_token(cfile);
! 328: cfile->token_line = cfile->cur_line;
! 329: }
! 330: }
! 331:
! 332: if (rval)
! 333: *rval = cfile -> tval;
! 334: if (rlen)
! 335: *rlen = cfile -> tlen;
! 336: #ifdef DEBUG_TOKENS
! 337: fprintf (stderr, "%s:%d ", cfile -> tval, rv);
! 338: #endif
! 339: return rv;
! 340: }
! 341:
! 342:
! 343: /*
! 344: * Get the next token from cfile and return it.
! 345: *
! 346: * If rval is non-NULL, set the pointer it contains to
! 347: * the contents of the token.
! 348: *
! 349: * If rlen is non-NULL, set the integer it contains to
! 350: * the length of the token.
! 351: */
! 352:
! 353: enum dhcp_token
! 354: next_token(const char **rval, unsigned *rlen, struct parse *cfile) {
! 355: return get_next_token(rval, rlen, cfile, ISC_FALSE);
! 356: }
! 357:
! 358:
! 359: /*
! 360: * The same as the next_token() function above, but will return space
! 361: * as the WHITESPACE token.
! 362: */
! 363:
! 364: enum dhcp_token
! 365: next_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
! 366: return get_next_token(rval, rlen, cfile, ISC_TRUE);
! 367: }
! 368:
! 369:
! 370: /*
! 371: * The do_peek_token() function checks the next token without
! 372: * consuming it, and returns it to the caller.
! 373: *
! 374: * Since the code is almost the same for "normal" and "raw"
! 375: * input, we pass a flag to alter the way it works. (See the
! 376: * warning in the GENERAL NOTES ABOUT TOKENS above though.)
! 377: */
! 378:
! 379: enum dhcp_token
! 380: do_peek_token(const char **rval, unsigned int *rlen,
! 381: struct parse *cfile, isc_boolean_t raw) {
! 382: int x;
! 383:
! 384: if (!cfile->token || (!raw && (cfile->token == WHITESPACE))) {
! 385: cfile -> tlpos = cfile -> lexchar;
! 386: cfile -> tline = cfile -> lexline;
! 387:
! 388: do {
! 389: cfile->token = get_raw_token(cfile);
! 390: } while (!raw && (cfile->token == WHITESPACE));
! 391:
! 392: if (cfile -> lexline != cfile -> tline)
! 393: cfile -> token_line = cfile -> prev_line;
! 394:
! 395: x = cfile -> lexchar;
! 396: cfile -> lexchar = cfile -> tlpos;
! 397: cfile -> tlpos = x;
! 398:
! 399: x = cfile -> lexline;
! 400: cfile -> lexline = cfile -> tline;
! 401: cfile -> tline = x;
! 402: }
! 403: if (rval)
! 404: *rval = cfile -> tval;
! 405: if (rlen)
! 406: *rlen = cfile -> tlen;
! 407: #ifdef DEBUG_TOKENS
! 408: fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);
! 409: #endif
! 410: return cfile -> token;
! 411: }
! 412:
! 413:
! 414: /*
! 415: * Get the next token from cfile and return it, leaving it for a
! 416: * subsequent call to next_token().
! 417: *
! 418: * Note that it WILL consume whitespace tokens.
! 419: *
! 420: * If rval is non-NULL, set the pointer it contains to
! 421: * the contents of the token.
! 422: *
! 423: * If rlen is non-NULL, set the integer it contains to
! 424: * the length of the token.
! 425: */
! 426:
! 427: enum dhcp_token
! 428: peek_token(const char **rval, unsigned *rlen, struct parse *cfile) {
! 429: return do_peek_token(rval, rlen, cfile, ISC_FALSE);
! 430: }
! 431:
! 432:
! 433: /*
! 434: * The same as the peek_token() function above, but will return space
! 435: * as the WHITESPACE token.
! 436: */
! 437:
! 438: enum dhcp_token
! 439: peek_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
! 440: return do_peek_token(rval, rlen, cfile, ISC_TRUE);
! 441: }
! 442:
! 443: static void skip_to_eol (cfile)
! 444: struct parse *cfile;
! 445: {
! 446: int c;
! 447: do {
! 448: c = get_char (cfile);
! 449: if (c == EOF)
! 450: return;
! 451: if (c == EOL) {
! 452: return;
! 453: }
! 454: } while (1);
! 455: }
! 456:
! 457: static enum dhcp_token
! 458: read_whitespace(int c, struct parse *cfile) {
! 459: int ofs;
! 460:
! 461: /*
! 462: * Read as much whitespace as we have available.
! 463: */
! 464: ofs = 0;
! 465: do {
! 466: cfile->tokbuf[ofs++] = c;
! 467: c = get_char(cfile);
! 468: } while (!((c == '\n') && cfile->eol_token) &&
! 469: isascii(c) && isspace(c));
! 470:
! 471: /*
! 472: * Put the last (non-whitespace) character back.
! 473: */
! 474: unget_char(cfile, c);
! 475:
! 476: /*
! 477: * Return our token.
! 478: */
! 479: cfile->tokbuf[ofs] = '\0';
! 480: cfile->tlen = ofs;
! 481: cfile->tval = cfile->tokbuf;
! 482: return WHITESPACE;
! 483: }
! 484:
! 485: static enum dhcp_token read_string (cfile)
! 486: struct parse *cfile;
! 487: {
! 488: int i;
! 489: int bs = 0;
! 490: int c;
! 491: int value = 0;
! 492: int hex = 0;
! 493:
! 494: for (i = 0; i < sizeof cfile -> tokbuf; i++) {
! 495: again:
! 496: c = get_char (cfile);
! 497: if (c == EOF) {
! 498: parse_warn (cfile, "eof in string constant");
! 499: break;
! 500: }
! 501: if (bs == 1) {
! 502: switch (c) {
! 503: case 't':
! 504: cfile -> tokbuf [i] = '\t';
! 505: break;
! 506: case 'r':
! 507: cfile -> tokbuf [i] = '\r';
! 508: break;
! 509: case 'n':
! 510: cfile -> tokbuf [i] = '\n';
! 511: break;
! 512: case 'b':
! 513: cfile -> tokbuf [i] = '\b';
! 514: break;
! 515: case '0':
! 516: case '1':
! 517: case '2':
! 518: case '3':
! 519: hex = 0;
! 520: value = c - '0';
! 521: ++bs;
! 522: goto again;
! 523: case 'x':
! 524: hex = 1;
! 525: value = 0;
! 526: ++bs;
! 527: goto again;
! 528: default:
! 529: cfile -> tokbuf [i] = c;
! 530: bs = 0;
! 531: break;
! 532: }
! 533: bs = 0;
! 534: } else if (bs > 1) {
! 535: if (hex) {
! 536: if (c >= '0' && c <= '9') {
! 537: value = value * 16 + (c - '0');
! 538: } else if (c >= 'a' && c <= 'f') {
! 539: value = value * 16 + (c - 'a' + 10);
! 540: } else if (c >= 'A' && c <= 'F') {
! 541: value = value * 16 + (c - 'A' + 10);
! 542: } else {
! 543: parse_warn (cfile,
! 544: "invalid hex digit: %x",
! 545: c);
! 546: bs = 0;
! 547: continue;
! 548: }
! 549: if (++bs == 4) {
! 550: cfile -> tokbuf [i] = value;
! 551: bs = 0;
! 552: } else
! 553: goto again;
! 554: } else {
! 555: if (c >= '0' && c <= '7') {
! 556: value = value * 8 + (c - '0');
! 557: } else {
! 558: if (value != 0) {
! 559: parse_warn (cfile,
! 560: "invalid octal digit %x",
! 561: c);
! 562: continue;
! 563: } else
! 564: cfile -> tokbuf [i] = 0;
! 565: bs = 0;
! 566: }
! 567: if (++bs == 4) {
! 568: cfile -> tokbuf [i] = value;
! 569: bs = 0;
! 570: } else
! 571: goto again;
! 572: }
! 573: } else if (c == '\\') {
! 574: bs = 1;
! 575: goto again;
! 576: } else if (c == '"')
! 577: break;
! 578: else
! 579: cfile -> tokbuf [i] = c;
! 580: }
! 581: /* Normally, I'd feel guilty about this, but we're talking about
! 582: strings that'll fit in a DHCP packet here... */
! 583: if (i == sizeof cfile -> tokbuf) {
! 584: parse_warn (cfile,
! 585: "string constant larger than internal buffer");
! 586: --i;
! 587: }
! 588: cfile -> tokbuf [i] = 0;
! 589: cfile -> tlen = i;
! 590: cfile -> tval = cfile -> tokbuf;
! 591: return STRING;
! 592: }
! 593:
! 594: static enum dhcp_token read_number (c, cfile)
! 595: int c;
! 596: struct parse *cfile;
! 597: {
! 598: int i = 0;
! 599: int token = NUMBER;
! 600:
! 601: cfile -> tokbuf [i++] = c;
! 602: for (; i < sizeof cfile -> tokbuf; i++) {
! 603: c = get_char (cfile);
! 604:
! 605: /* Promote NUMBER -> NUMBER_OR_NAME -> NAME, never demote.
! 606: * Except in the case of '0x' syntax hex, which gets called
! 607: * a NAME at '0x', and returned to NUMBER_OR_NAME once it's
! 608: * verified to be at least 0xf or less.
! 609: */
! 610: switch(isascii(c) ? token : BREAK) {
! 611: case NUMBER:
! 612: if(isdigit(c))
! 613: break;
! 614: /* FALLTHROUGH */
! 615: case NUMBER_OR_NAME:
! 616: if(isxdigit(c)) {
! 617: token = NUMBER_OR_NAME;
! 618: break;
! 619: }
! 620: /* FALLTHROUGH */
! 621: case NAME:
! 622: if((i == 2) && isxdigit(c) &&
! 623: (cfile->tokbuf[0] == '0') &&
! 624: ((cfile->tokbuf[1] == 'x') ||
! 625: (cfile->tokbuf[1] == 'X'))) {
! 626: token = NUMBER_OR_NAME;
! 627: break;
! 628: } else if(((c == '-') || (c == '_') || isalnum(c))) {
! 629: token = NAME;
! 630: break;
! 631: }
! 632: /* FALLTHROUGH */
! 633: case BREAK:
! 634: /* At this point c is either EOF or part of the next
! 635: * token. If not EOF, rewind the file one byte so
! 636: * the next token is read from there.
! 637: */
! 638: unget_char(cfile, c);
! 639: goto end_read;
! 640:
! 641: default:
! 642: log_fatal("read_number():%s:%d: impossible case", MDL);
! 643: }
! 644:
! 645: cfile -> tokbuf [i] = c;
! 646: }
! 647:
! 648: if (i == sizeof cfile -> tokbuf) {
! 649: parse_warn (cfile,
! 650: "numeric token larger than internal buffer");
! 651: --i;
! 652: }
! 653:
! 654: end_read:
! 655: cfile -> tokbuf [i] = 0;
! 656: cfile -> tlen = i;
! 657: cfile -> tval = cfile -> tokbuf;
! 658:
! 659: /*
! 660: * If this entire token from start to finish was "-", such as
! 661: * the middle parameter in "42 - 7", return just the MINUS token.
! 662: */
! 663: if ((i == 1) && (cfile->tokbuf[i] == '-'))
! 664: return MINUS;
! 665: else
! 666: return token;
! 667: }
! 668:
! 669: static enum dhcp_token read_num_or_name (c, cfile)
! 670: int c;
! 671: struct parse *cfile;
! 672: {
! 673: int i = 0;
! 674: enum dhcp_token rv = NUMBER_OR_NAME;
! 675: cfile -> tokbuf [i++] = c;
! 676: for (; i < sizeof cfile -> tokbuf; i++) {
! 677: c = get_char (cfile);
! 678: if (!isascii (c) ||
! 679: (c != '-' && c != '_' && !isalnum (c))) {
! 680: unget_char(cfile, c);
! 681: break;
! 682: }
! 683: if (!isxdigit (c))
! 684: rv = NAME;
! 685: cfile -> tokbuf [i] = c;
! 686: }
! 687: if (i == sizeof cfile -> tokbuf) {
! 688: parse_warn (cfile, "token larger than internal buffer");
! 689: --i;
! 690: }
! 691: cfile -> tokbuf [i] = 0;
! 692: cfile -> tlen = i;
! 693: cfile -> tval = cfile -> tokbuf;
! 694: return intern(cfile->tval, rv);
! 695: }
! 696:
! 697: static enum dhcp_token
! 698: intern(char *atom, enum dhcp_token dfv) {
! 699: if (!isascii(atom[0]))
! 700: return dfv;
! 701:
! 702: switch (tolower((unsigned char)atom[0])) {
! 703: case '-':
! 704: if (atom [1] == 0)
! 705: return MINUS;
! 706: break;
! 707:
! 708: case 'a':
! 709: if (!strncasecmp (atom + 1, "uth", 3)) {
! 710: if (!strncasecmp (atom + 3, "uthenticat", 10)) {
! 711: if (!strcasecmp (atom + 13, "ed"))
! 712: return AUTHENTICATED;
! 713: if (!strcasecmp (atom + 13, "ion"))
! 714: return AUTHENTICATION;
! 715: break;
! 716: }
! 717: if (!strcasecmp (atom + 1, "uthoritative"))
! 718: return AUTHORITATIVE;
! 719: break;
! 720: }
! 721: if (!strcasecmp (atom + 1, "nd"))
! 722: return AND;
! 723: if (!strcasecmp (atom + 1, "ppend"))
! 724: return APPEND;
! 725: if (!strcasecmp (atom + 1, "llow"))
! 726: return ALLOW;
! 727: if (!strcasecmp (atom + 1, "lias"))
! 728: return ALIAS;
! 729: if (!strcasecmp (atom + 1, "lgorithm"))
! 730: return ALGORITHM;
! 731: if (!strcasecmp (atom + 1, "lso"))
! 732: return TOKEN_ALSO;
! 733: if (!strcasecmp (atom + 1, "bandoned"))
! 734: return TOKEN_ABANDONED;
! 735: if (!strcasecmp (atom + 1, "dd"))
! 736: return TOKEN_ADD;
! 737: if (!strcasecmp (atom + 1, "ll"))
! 738: return ALL;
! 739: if (!strcasecmp (atom + 1, "t"))
! 740: return AT;
! 741: if (!strcasecmp (atom + 1, "rray"))
! 742: return ARRAY;
! 743: if (!strcasecmp (atom + 1, "ddress"))
! 744: return ADDRESS;
! 745: if (!strcasecmp (atom + 1, "ctive"))
! 746: return TOKEN_ACTIVE;
! 747: if (!strcasecmp (atom + 1, "tsfp"))
! 748: return ATSFP;
! 749: if (!strcasecmp (atom + 1, "fter"))
! 750: return AFTER;
! 751: break;
! 752: case 'b':
! 753: if (!strcasecmp (atom + 1, "ackup"))
! 754: return TOKEN_BACKUP;
! 755: if (!strcasecmp (atom + 1, "ootp"))
! 756: return TOKEN_BOOTP;
! 757: if (!strcasecmp (atom + 1, "inding"))
! 758: return BINDING;
! 759: if (!strcasecmp (atom + 1, "inary-to-ascii"))
! 760: return BINARY_TO_ASCII;
! 761: if (!strcasecmp (atom + 1, "ackoff-cutoff"))
! 762: return BACKOFF_CUTOFF;
! 763: if (!strcasecmp (atom + 1, "ooting"))
! 764: return BOOTING;
! 765: if (!strcasecmp (atom + 1, "oot-unknown-clients"))
! 766: return BOOT_UNKNOWN_CLIENTS;
! 767: if (!strcasecmp (atom + 1, "reak"))
! 768: return BREAK;
! 769: if (!strcasecmp (atom + 1, "illing"))
! 770: return BILLING;
! 771: if (!strcasecmp (atom + 1, "oolean"))
! 772: return BOOLEAN;
! 773: if (!strcasecmp (atom + 1, "alance"))
! 774: return BALANCE;
! 775: if (!strcasecmp (atom + 1, "ound"))
! 776: return BOUND;
! 777: break;
! 778: case 'c':
! 779: if (!strcasecmp(atom + 1, "ase"))
! 780: return CASE;
! 781: if (!strcasecmp(atom + 1, "heck"))
! 782: return CHECK;
! 783: if (!strcasecmp(atom + 1, "iaddr"))
! 784: return CIADDR;
! 785: if (isascii(atom[1]) &&
! 786: tolower((unsigned char)atom[1]) == 'l') {
! 787: if (!strcasecmp(atom + 2, "ass"))
! 788: return CLASS;
! 789: if (!strncasecmp(atom + 2, "ient", 4)) {
! 790: if (!strcasecmp(atom + 6, "s"))
! 791: return CLIENTS;
! 792: if (atom[6] == '-') {
! 793: if (!strcasecmp(atom + 7, "hostname"))
! 794: return CLIENT_HOSTNAME;
! 795: if (!strcasecmp(atom + 7, "identifier"))
! 796: return CLIENT_IDENTIFIER;
! 797: if (!strcasecmp(atom + 7, "state"))
! 798: return CLIENT_STATE;
! 799: if (!strcasecmp(atom + 7, "updates"))
! 800: return CLIENT_UPDATES;
! 801: break;
! 802: }
! 803: break;
! 804: }
! 805: if (!strcasecmp(atom + 2, "ose"))
! 806: return TOKEN_CLOSE;
! 807: if (!strcasecmp(atom + 2, "tt"))
! 808: return CLTT;
! 809: break;
! 810: }
! 811: if (isascii(atom[1]) &&
! 812: tolower((unsigned char)atom[1]) == 'o') {
! 813: if (!strcasecmp(atom + 2, "de"))
! 814: return CODE;
! 815: if (isascii(atom[2]) &&
! 816: tolower((unsigned char)atom[2]) == 'm') {
! 817: if (!strcasecmp(atom + 3, "mit"))
! 818: return COMMIT;
! 819: if (!strcasecmp(atom + 3,
! 820: "munications-interrupted"))
! 821: return COMMUNICATIONS_INTERRUPTED;
! 822: if (!strcasecmp(atom + 3, "pressed"))
! 823: return COMPRESSED;
! 824: break;
! 825: }
! 826: if (isascii(atom[2]) &&
! 827: tolower((unsigned char)atom[2]) == 'n') {
! 828: if (!strcasecmp(atom + 3, "cat"))
! 829: return CONCAT;
! 830: if (!strcasecmp(atom + 3, "fig-option"))
! 831: return CONFIG_OPTION;
! 832: if (!strcasecmp(atom + 3, "flict-done"))
! 833: return CONFLICT_DONE;
! 834: if (!strcasecmp(atom + 3, "nect"))
! 835: return CONNECT;
! 836: break;
! 837: }
! 838: break;
! 839: }
! 840: if (!strcasecmp(atom + 1, "reate"))
! 841: return TOKEN_CREATE;
! 842: break;
! 843: case 'd':
! 844: if (!strcasecmp(atom + 1, "b-time-format"))
! 845: return DB_TIME_FORMAT;
! 846: if (!strcasecmp (atom + 1, "ns-update"))
! 847: return DNS_UPDATE;
! 848: if (!strcasecmp (atom + 1, "ns-delete"))
! 849: return DNS_DELETE;
! 850: if (!strcasecmp (atom + 1, "omain"))
! 851: return DOMAIN;
! 852: if (!strncasecmp (atom + 1, "omain-", 6)) {
! 853: if (!strcasecmp(atom + 7, "name"))
! 854: return DOMAIN_NAME;
! 855: if (!strcasecmp(atom + 7, "list"))
! 856: return DOMAIN_LIST;
! 857: }
! 858: if (!strcasecmp (atom + 1, "o-forward-update"))
! 859: return DO_FORWARD_UPDATE;
! 860: if (!strcasecmp (atom + 1, "ebug"))
! 861: return TOKEN_DEBUG;
! 862: if (!strcasecmp (atom + 1, "eny"))
! 863: return DENY;
! 864: if (!strcasecmp (atom + 1, "eleted"))
! 865: return TOKEN_DELETED;
! 866: if (!strcasecmp (atom + 1, "elete"))
! 867: return TOKEN_DELETE;
! 868: if (!strncasecmp (atom + 1, "efault", 6)) {
! 869: if (!atom [7])
! 870: return DEFAULT;
! 871: if (!strcasecmp(atom + 7, "-duid"))
! 872: return DEFAULT_DUID;
! 873: if (!strcasecmp (atom + 7, "-lease-time"))
! 874: return DEFAULT_LEASE_TIME;
! 875: break;
! 876: }
! 877: if (!strncasecmp (atom + 1, "ynamic", 6)) {
! 878: if (!atom [7])
! 879: return DYNAMIC;
! 880: if (!strncasecmp (atom + 7, "-bootp", 6)) {
! 881: if (!atom [13])
! 882: return DYNAMIC_BOOTP;
! 883: if (!strcasecmp (atom + 13, "-lease-cutoff"))
! 884: return DYNAMIC_BOOTP_LEASE_CUTOFF;
! 885: if (!strcasecmp (atom + 13, "-lease-length"))
! 886: return DYNAMIC_BOOTP_LEASE_LENGTH;
! 887: break;
! 888: }
! 889: }
! 890: if (!strcasecmp (atom + 1, "uplicates"))
! 891: return DUPLICATES;
! 892: if (!strcasecmp (atom + 1, "eclines"))
! 893: return DECLINES;
! 894: if (!strncasecmp (atom + 1, "efine", 5)) {
! 895: if (!strcasecmp (atom + 6, "d"))
! 896: return DEFINED;
! 897: if (!atom [6])
! 898: return DEFINE;
! 899: }
! 900: break;
! 901: case 'e':
! 902: if (isascii (atom [1]) &&
! 903: tolower((unsigned char)atom[1]) == 'x') {
! 904: if (!strcasecmp (atom + 2, "tract-int"))
! 905: return EXTRACT_INT;
! 906: if (!strcasecmp (atom + 2, "ists"))
! 907: return EXISTS;
! 908: if (!strcasecmp (atom + 2, "piry"))
! 909: return EXPIRY;
! 910: if (!strcasecmp (atom + 2, "pire"))
! 911: return EXPIRE;
! 912: if (!strcasecmp (atom + 2, "pired"))
! 913: return TOKEN_EXPIRED;
! 914: }
! 915: if (!strcasecmp (atom + 1, "ncode-int"))
! 916: return ENCODE_INT;
! 917: if (!strcasecmp(atom + 1, "poch"))
! 918: return EPOCH;
! 919: if (!strcasecmp (atom + 1, "thernet"))
! 920: return ETHERNET;
! 921: if (!strcasecmp (atom + 1, "nds"))
! 922: return ENDS;
! 923: if (!strncasecmp (atom + 1, "ls", 2)) {
! 924: if (!strcasecmp (atom + 3, "e"))
! 925: return ELSE;
! 926: if (!strcasecmp (atom + 3, "if"))
! 927: return ELSIF;
! 928: break;
! 929: }
! 930: if (!strcasecmp (atom + 1, "rror"))
! 931: return ERROR;
! 932: if (!strcasecmp (atom + 1, "val"))
! 933: return EVAL;
! 934: if (!strcasecmp (atom + 1, "ncapsulate"))
! 935: return ENCAPSULATE;
! 936: if (!strcasecmp(atom + 1, "xecute"))
! 937: return EXECUTE;
! 938: if (!strcasecmp(atom+1, "n")) {
! 939: return EN;
! 940: }
! 941: break;
! 942: case 'f':
! 943: if (!strcasecmp (atom + 1, "atal"))
! 944: return FATAL;
! 945: if (!strcasecmp (atom + 1, "ilename"))
! 946: return FILENAME;
! 947: if (!strcasecmp (atom + 1, "ixed-address"))
! 948: return FIXED_ADDR;
! 949: if (!strcasecmp (atom + 1, "ixed-address6"))
! 950: return FIXED_ADDR6;
! 951: if (!strcasecmp (atom + 1, "ixed-prefix6"))
! 952: return FIXED_PREFIX6;
! 953: if (!strcasecmp (atom + 1, "ddi"))
! 954: return TOKEN_FDDI;
! 955: if (!strcasecmp (atom + 1, "ormerr"))
! 956: return NS_FORMERR;
! 957: if (!strcasecmp (atom + 1, "unction"))
! 958: return FUNCTION;
! 959: if (!strcasecmp (atom + 1, "ailover"))
! 960: return FAILOVER;
! 961: if (!strcasecmp (atom + 1, "ree"))
! 962: return TOKEN_FREE;
! 963: break;
! 964: case 'g':
! 965: if (!strcasecmp (atom + 1, "iaddr"))
! 966: return GIADDR;
! 967: if (!strcasecmp (atom + 1, "roup"))
! 968: return GROUP;
! 969: if (!strcasecmp (atom + 1, "et-lease-hostnames"))
! 970: return GET_LEASE_HOSTNAMES;
! 971: if (!strcasecmp(atom + 1, "ethostbyname"))
! 972: return GETHOSTBYNAME;
! 973: break;
! 974: case 'h':
! 975: if (!strcasecmp(atom + 1, "ash"))
! 976: return HASH;
! 977: if (!strcasecmp (atom + 1, "ba"))
! 978: return HBA;
! 979: if (!strcasecmp (atom + 1, "ost"))
! 980: return HOST;
! 981: if (!strcasecmp (atom + 1, "ost-decl-name"))
! 982: return HOST_DECL_NAME;
! 983: if (!strcasecmp(atom + 1, "ost-identifier"))
! 984: return HOST_IDENTIFIER;
! 985: if (!strcasecmp (atom + 1, "ardware"))
! 986: return HARDWARE;
! 987: if (!strcasecmp (atom + 1, "ostname"))
! 988: return HOSTNAME;
! 989: if (!strcasecmp (atom + 1, "elp"))
! 990: return TOKEN_HELP;
! 991: break;
! 992: case 'i':
! 993: if (!strcasecmp(atom+1, "a-na"))
! 994: return IA_NA;
! 995: if (!strcasecmp(atom+1, "a-ta"))
! 996: return IA_TA;
! 997: if (!strcasecmp(atom+1, "a-pd"))
! 998: return IA_PD;
! 999: if (!strcasecmp(atom+1, "aaddr"))
! 1000: return IAADDR;
! 1001: if (!strcasecmp(atom+1, "aprefix"))
! 1002: return IAPREFIX;
! 1003: if (!strcasecmp (atom + 1, "nclude"))
! 1004: return INCLUDE;
! 1005: if (!strcasecmp (atom + 1, "nteger"))
! 1006: return INTEGER;
! 1007: if (!strcasecmp (atom + 1, "nfinite"))
! 1008: return INFINITE;
! 1009: if (!strcasecmp (atom + 1, "nfo"))
! 1010: return INFO;
! 1011: if (!strcasecmp (atom + 1, "p-address"))
! 1012: return IP_ADDRESS;
! 1013: if (!strcasecmp (atom + 1, "p6-address"))
! 1014: return IP6_ADDRESS;
! 1015: if (!strcasecmp (atom + 1, "nitial-interval"))
! 1016: return INITIAL_INTERVAL;
! 1017: if (!strcasecmp (atom + 1, "nitial-delay"))
! 1018: return INITIAL_DELAY;
! 1019: if (!strcasecmp (atom + 1, "nterface"))
! 1020: return INTERFACE;
! 1021: if (!strcasecmp (atom + 1, "dentifier"))
! 1022: return IDENTIFIER;
! 1023: if (!strcasecmp (atom + 1, "f"))
! 1024: return IF;
! 1025: if (!strcasecmp (atom + 1, "s"))
! 1026: return IS;
! 1027: if (!strcasecmp (atom + 1, "gnore"))
! 1028: return IGNORE;
! 1029: break;
! 1030: case 'k':
! 1031: if (!strncasecmp (atom + 1, "nown", 4)) {
! 1032: if (!strcasecmp (atom + 5, "-clients"))
! 1033: return KNOWN_CLIENTS;
! 1034: if (!atom[5])
! 1035: return KNOWN;
! 1036: break;
! 1037: }
! 1038: if (!strcasecmp (atom + 1, "ey"))
! 1039: return KEY;
! 1040: break;
! 1041: case 'l':
! 1042: if (!strcasecmp (atom + 1, "case"))
! 1043: return LCASE;
! 1044: if (!strcasecmp (atom + 1, "ease"))
! 1045: return LEASE;
! 1046: if (!strcasecmp(atom + 1, "ease6"))
! 1047: return LEASE6;
! 1048: if (!strcasecmp (atom + 1, "eased-address"))
! 1049: return LEASED_ADDRESS;
! 1050: if (!strcasecmp (atom + 1, "ease-time"))
! 1051: return LEASE_TIME;
! 1052: if (!strcasecmp(atom + 1, "easequery"))
! 1053: return LEASEQUERY;
! 1054: if (!strcasecmp(atom + 1, "ength"))
! 1055: return LENGTH;
! 1056: if (!strcasecmp (atom + 1, "imit"))
! 1057: return LIMIT;
! 1058: if (!strcasecmp (atom + 1, "et"))
! 1059: return LET;
! 1060: if (!strcasecmp (atom + 1, "oad"))
! 1061: return LOAD;
! 1062: if (!strcasecmp(atom + 1, "ocal"))
! 1063: return LOCAL;
! 1064: if (!strcasecmp (atom + 1, "og"))
! 1065: return LOG;
! 1066: if (!strcasecmp(atom+1, "lt")) {
! 1067: return LLT;
! 1068: }
! 1069: if (!strcasecmp(atom+1, "l")) {
! 1070: return LL;
! 1071: }
! 1072: break;
! 1073: case 'm':
! 1074: if (!strncasecmp (atom + 1, "ax", 2)) {
! 1075: if (!atom [3])
! 1076: return TOKEN_MAX;
! 1077: if (!strcasecmp (atom + 3, "-balance"))
! 1078: return MAX_BALANCE;
! 1079: if (!strncasecmp (atom + 3, "-lease-", 7)) {
! 1080: if (!strcasecmp(atom + 10, "misbalance"))
! 1081: return MAX_LEASE_MISBALANCE;
! 1082: if (!strcasecmp(atom + 10, "ownership"))
! 1083: return MAX_LEASE_OWNERSHIP;
! 1084: if (!strcasecmp(atom + 10, "time"))
! 1085: return MAX_LEASE_TIME;
! 1086: }
! 1087: if (!strcasecmp(atom + 3, "-life"))
! 1088: return MAX_LIFE;
! 1089: if (!strcasecmp (atom + 3, "-transmit-idle"))
! 1090: return MAX_TRANSMIT_IDLE;
! 1091: if (!strcasecmp (atom + 3, "-response-delay"))
! 1092: return MAX_RESPONSE_DELAY;
! 1093: if (!strcasecmp (atom + 3, "-unacked-updates"))
! 1094: return MAX_UNACKED_UPDATES;
! 1095: }
! 1096: if (!strncasecmp (atom + 1, "in-", 3)) {
! 1097: if (!strcasecmp (atom + 4, "balance"))
! 1098: return MIN_BALANCE;
! 1099: if (!strcasecmp (atom + 4, "lease-time"))
! 1100: return MIN_LEASE_TIME;
! 1101: if (!strcasecmp (atom + 4, "secs"))
! 1102: return MIN_SECS;
! 1103: break;
! 1104: }
! 1105: if (!strncasecmp (atom + 1, "edi", 3)) {
! 1106: if (!strcasecmp (atom + 4, "a"))
! 1107: return MEDIA;
! 1108: if (!strcasecmp (atom + 4, "um"))
! 1109: return MEDIUM;
! 1110: break;
! 1111: }
! 1112: if (!strcasecmp (atom + 1, "atch"))
! 1113: return MATCH;
! 1114: if (!strcasecmp (atom + 1, "embers"))
! 1115: return MEMBERS;
! 1116: if (!strcasecmp (atom + 1, "y"))
! 1117: return MY;
! 1118: if (!strcasecmp (atom + 1, "clt"))
! 1119: return MCLT;
! 1120: break;
! 1121: case 'n':
! 1122: if (!strcasecmp (atom + 1, "ormal"))
! 1123: return NORMAL;
! 1124: if (!strcasecmp (atom + 1, "ameserver"))
! 1125: return NAMESERVER;
! 1126: if (!strcasecmp (atom + 1, "etmask"))
! 1127: return NETMASK;
! 1128: if (!strcasecmp (atom + 1, "ever"))
! 1129: return NEVER;
! 1130: if (!strcasecmp (atom + 1, "ext-server"))
! 1131: return NEXT_SERVER;
! 1132: if (!strcasecmp (atom + 1, "ot"))
! 1133: return TOKEN_NOT;
! 1134: if (!strcasecmp (atom + 1, "o"))
! 1135: return TOKEN_NO;
! 1136: if (!strcasecmp (atom + 1, "s-update"))
! 1137: return NS_UPDATE;
! 1138: if (!strcasecmp (atom + 1, "oerror"))
! 1139: return NS_NOERROR;
! 1140: if (!strcasecmp (atom + 1, "otauth"))
! 1141: return NS_NOTAUTH;
! 1142: if (!strcasecmp (atom + 1, "otimp"))
! 1143: return NS_NOTIMP;
! 1144: if (!strcasecmp (atom + 1, "otzone"))
! 1145: return NS_NOTZONE;
! 1146: if (!strcasecmp (atom + 1, "xdomain"))
! 1147: return NS_NXDOMAIN;
! 1148: if (!strcasecmp (atom + 1, "xrrset"))
! 1149: return NS_NXRRSET;
! 1150: if (!strcasecmp (atom + 1, "ull"))
! 1151: return TOKEN_NULL;
! 1152: if (!strcasecmp (atom + 1, "ext"))
! 1153: return TOKEN_NEXT;
! 1154: if (!strcasecmp (atom + 1, "ew"))
! 1155: return TOKEN_NEW;
! 1156: break;
! 1157: case 'o':
! 1158: if (!strcasecmp (atom + 1, "mapi"))
! 1159: return OMAPI;
! 1160: if (!strcasecmp (atom + 1, "r"))
! 1161: return OR;
! 1162: if (!strcasecmp (atom + 1, "n"))
! 1163: return ON;
! 1164: if (!strcasecmp (atom + 1, "pen"))
! 1165: return TOKEN_OPEN;
! 1166: if (!strcasecmp (atom + 1, "ption"))
! 1167: return OPTION;
! 1168: if (!strcasecmp (atom + 1, "ne-lease-per-client"))
! 1169: return ONE_LEASE_PER_CLIENT;
! 1170: if (!strcasecmp (atom + 1, "f"))
! 1171: return OF;
! 1172: if (!strcasecmp (atom + 1, "wner"))
! 1173: return OWNER;
! 1174: break;
! 1175: case 'p':
! 1176: if (!strcasecmp (atom + 1, "repend"))
! 1177: return PREPEND;
! 1178: if (!strcasecmp(atom + 1, "referred-life"))
! 1179: return PREFERRED_LIFE;
! 1180: if (!strcasecmp (atom + 1, "acket"))
! 1181: return PACKET;
! 1182: if (!strcasecmp (atom + 1, "ool"))
! 1183: return POOL;
! 1184: if (!strcasecmp (atom + 1, "refix6"))
! 1185: return PREFIX6;
! 1186: if (!strcasecmp (atom + 1, "seudo"))
! 1187: return PSEUDO;
! 1188: if (!strcasecmp (atom + 1, "eer"))
! 1189: return PEER;
! 1190: if (!strcasecmp (atom + 1, "rimary"))
! 1191: return PRIMARY;
! 1192: if (!strncasecmp (atom + 1, "artner", 6)) {
! 1193: if (!atom [7])
! 1194: return PARTNER;
! 1195: if (!strcasecmp (atom + 7, "-down"))
! 1196: return PARTNER_DOWN;
! 1197: }
! 1198: if (!strcasecmp (atom + 1, "ort"))
! 1199: return PORT;
! 1200: if (!strcasecmp (atom + 1, "otential-conflict"))
! 1201: return POTENTIAL_CONFLICT;
! 1202: if (!strcasecmp (atom + 1, "ick-first-value") ||
! 1203: !strcasecmp (atom + 1, "ick"))
! 1204: return PICK;
! 1205: if (!strcasecmp (atom + 1, "aused"))
! 1206: return PAUSED;
! 1207: break;
! 1208: case 'r':
! 1209: if (!strcasecmp (atom + 1, "esolution-interrupted"))
! 1210: return RESOLUTION_INTERRUPTED;
! 1211: if (!strcasecmp (atom + 1, "ange"))
! 1212: return RANGE;
! 1213: if (!strcasecmp(atom + 1, "ange6")) {
! 1214: return RANGE6;
! 1215: }
! 1216: if (!strcasecmp (atom + 1, "ecover"))
! 1217: return RECOVER;
! 1218: if (!strcasecmp (atom + 1, "ecover-done"))
! 1219: return RECOVER_DONE;
! 1220: if (!strcasecmp (atom + 1, "ecover-wait"))
! 1221: return RECOVER_WAIT;
! 1222: if (!strcasecmp (atom + 1, "econtact-interval"))
! 1223: return RECONTACT_INTERVAL;
! 1224: if (!strcasecmp (atom + 1, "equest"))
! 1225: return REQUEST;
! 1226: if (!strcasecmp (atom + 1, "equire"))
! 1227: return REQUIRE;
! 1228: if (!strcasecmp (atom + 1, "equire"))
! 1229: return REQUIRE;
! 1230: if (!strcasecmp (atom + 1, "etry"))
! 1231: return RETRY;
! 1232: if (!strcasecmp (atom + 1, "eturn"))
! 1233: return RETURN;
! 1234: if (!strcasecmp (atom + 1, "enew"))
! 1235: return RENEW;
! 1236: if (!strcasecmp (atom + 1, "ebind"))
! 1237: return REBIND;
! 1238: if (!strcasecmp (atom + 1, "eboot"))
! 1239: return REBOOT;
! 1240: if (!strcasecmp (atom + 1, "eject"))
! 1241: return REJECT;
! 1242: if (!strcasecmp (atom + 1, "everse"))
! 1243: return REVERSE;
! 1244: if (!strcasecmp (atom + 1, "elease"))
! 1245: return RELEASE;
! 1246: if (!strcasecmp (atom + 1, "efused"))
! 1247: return NS_REFUSED;
! 1248: if (!strcasecmp (atom + 1, "eleased"))
! 1249: return TOKEN_RELEASED;
! 1250: if (!strcasecmp (atom + 1, "eset"))
! 1251: return TOKEN_RESET;
! 1252: if (!strcasecmp (atom + 1, "eserved"))
! 1253: return TOKEN_RESERVED;
! 1254: if (!strcasecmp (atom + 1, "emove"))
! 1255: return REMOVE;
! 1256: if (!strcasecmp (atom + 1, "efresh"))
! 1257: return REFRESH;
! 1258: break;
! 1259: case 's':
! 1260: if (!strcasecmp(atom + 1, "cript"))
! 1261: return SCRIPT;
! 1262: if (isascii(atom[1]) &&
! 1263: tolower((unsigned char)atom[1]) == 'e') {
! 1264: if (!strcasecmp(atom + 2, "arch"))
! 1265: return SEARCH;
! 1266: if (isascii(atom[2]) &&
! 1267: tolower((unsigned char)atom[2]) == 'c') {
! 1268: if (!strncasecmp(atom + 3, "ond", 3)) {
! 1269: if (!strcasecmp(atom + 6, "ary"))
! 1270: return SECONDARY;
! 1271: if (!strcasecmp(atom + 6, "s"))
! 1272: return SECONDS;
! 1273: break;
! 1274: }
! 1275: if (!strcasecmp(atom + 3, "ret"))
! 1276: return SECRET;
! 1277: break;
! 1278: }
! 1279: if (!strncasecmp(atom + 2, "lect", 4)) {
! 1280: if (atom[6] == '\0')
! 1281: return SELECT;
! 1282: if (!strcasecmp(atom + 6, "-timeout"))
! 1283: return SELECT_TIMEOUT;
! 1284: break;
! 1285: }
! 1286: if (!strcasecmp(atom + 2, "nd"))
! 1287: return SEND;
! 1288: if (!strncasecmp(atom + 2, "rv", 2)) {
! 1289: if (!strncasecmp(atom + 4, "er", 2)) {
! 1290: if (atom[6] == '\0')
! 1291: return TOKEN_SERVER;
! 1292: if (atom[6] == '-') {
! 1293: if (!strcasecmp(atom + 7,
! 1294: "duid"))
! 1295: return SERVER_DUID;
! 1296: if (!strcasecmp(atom + 7,
! 1297: "name"))
! 1298: return SERVER_NAME;
! 1299: if (!strcasecmp(atom + 7,
! 1300: "identifier"))
! 1301: return SERVER_IDENTIFIER;
! 1302: break;
! 1303: }
! 1304: break;
! 1305: }
! 1306: if (!strcasecmp(atom + 4, "fail"))
! 1307: return NS_SERVFAIL;
! 1308: break;
! 1309: }
! 1310: if (!strcasecmp(atom + 2, "t"))
! 1311: return TOKEN_SET;
! 1312: break;
! 1313: }
! 1314: if (isascii(atom[1]) &&
! 1315: tolower((unsigned char)atom[1]) == 'h') {
! 1316: if (!strcasecmp(atom + 2, "ared-network"))
! 1317: return SHARED_NETWORK;
! 1318: if (!strcasecmp(atom + 2, "utdown"))
! 1319: return SHUTDOWN;
! 1320: break;
! 1321: }
! 1322: if (isascii(atom[1]) &&
! 1323: tolower((unsigned char)atom[1]) == 'i') {
! 1324: if (!strcasecmp(atom + 2, "addr"))
! 1325: return SIADDR;
! 1326: if (!strcasecmp(atom + 2, "gned"))
! 1327: return SIGNED;
! 1328: if (!strcasecmp(atom + 2, "ze"))
! 1329: return SIZE;
! 1330: break;
! 1331: }
! 1332: if (isascii(atom[1]) &&
! 1333: tolower((unsigned char)atom[1]) == 'p') {
! 1334: if (isascii(atom[2]) &&
! 1335: tolower((unsigned char)atom[2]) == 'a') {
! 1336: if (!strcasecmp(atom + 3, "ce"))
! 1337: return SPACE;
! 1338: if (!strcasecmp(atom + 3, "wn"))
! 1339: return SPAWN;
! 1340: break;
! 1341: }
! 1342: if (!strcasecmp(atom + 2, "lit"))
! 1343: return SPLIT;
! 1344: break;
! 1345: }
! 1346: if (isascii(atom[1]) &&
! 1347: tolower((unsigned char)atom[1]) == 't') {
! 1348: if (isascii(atom[2]) &&
! 1349: tolower((unsigned char)atom[2]) == 'a') {
! 1350: if(!strncasecmp(atom + 3, "rt", 2)) {
! 1351: if (!strcasecmp(atom + 5, "s"))
! 1352: return STARTS;
! 1353: if (!strcasecmp(atom + 5, "up"))
! 1354: return STARTUP;
! 1355: break;
! 1356: }
! 1357: if (isascii(atom[3]) &&
! 1358: tolower((unsigned char)atom[3]) == 't') {
! 1359: if (!strcasecmp(atom + 4, "e"))
! 1360: return STATE;
! 1361: if (!strcasecmp(atom + 4, "ic"))
! 1362: return STATIC;
! 1363: break;
! 1364: }
! 1365: }
! 1366: if (!strcasecmp(atom + 2, "ring"))
! 1367: return STRING_TOKEN;
! 1368: break;
! 1369: }
! 1370: if (!strncasecmp(atom + 1, "ub", 2)) {
! 1371: if (!strcasecmp(atom + 3, "class"))
! 1372: return SUBCLASS;
! 1373: if (!strcasecmp(atom + 3, "net"))
! 1374: return SUBNET;
! 1375: if (!strcasecmp(atom + 3, "net6"))
! 1376: return SUBNET6;
! 1377: if (!strcasecmp(atom + 3, "string"))
! 1378: return SUBSTRING;
! 1379: break;
! 1380: }
! 1381: if (isascii(atom[1]) &&
! 1382: tolower((unsigned char)atom[1]) == 'u') {
! 1383: if (!strcasecmp(atom + 2, "ffix"))
! 1384: return SUFFIX;
! 1385: if (!strcasecmp(atom + 2, "persede"))
! 1386: return SUPERSEDE;
! 1387: }
! 1388: if (!strcasecmp(atom + 1, "witch"))
! 1389: return SWITCH;
! 1390: break;
! 1391: case 't':
! 1392: if (!strcasecmp (atom + 1, "imestamp"))
! 1393: return TIMESTAMP;
! 1394: if (!strcasecmp (atom + 1, "imeout"))
! 1395: return TIMEOUT;
! 1396: if (!strcasecmp (atom + 1, "oken-ring"))
! 1397: return TOKEN_RING;
! 1398: if (!strcasecmp (atom + 1, "ext"))
! 1399: return TEXT;
! 1400: if (!strcasecmp (atom + 1, "stp"))
! 1401: return TSTP;
! 1402: if (!strcasecmp (atom + 1, "sfp"))
! 1403: return TSFP;
! 1404: if (!strcasecmp (atom + 1, "ransmission"))
! 1405: return TRANSMISSION;
! 1406: if (!strcasecmp(atom + 1, "emporary"))
! 1407: return TEMPORARY;
! 1408: break;
! 1409: case 'u':
! 1410: if (!strcasecmp (atom + 1, "case"))
! 1411: return UCASE;
! 1412: if (!strcasecmp (atom + 1, "nset"))
! 1413: return UNSET;
! 1414: if (!strcasecmp (atom + 1, "nsigned"))
! 1415: return UNSIGNED;
! 1416: if (!strcasecmp (atom + 1, "id"))
! 1417: return UID;
! 1418: if (!strncasecmp (atom + 1, "se", 2)) {
! 1419: if (!strcasecmp (atom + 3, "r-class"))
! 1420: return USER_CLASS;
! 1421: if (!strcasecmp (atom + 3, "-host-decl-names"))
! 1422: return USE_HOST_DECL_NAMES;
! 1423: if (!strcasecmp (atom + 3,
! 1424: "-lease-addr-for-default-route"))
! 1425: return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE;
! 1426: break;
! 1427: }
! 1428: if (!strncasecmp (atom + 1, "nknown", 6)) {
! 1429: if (!strcasecmp (atom + 7, "-clients"))
! 1430: return UNKNOWN_CLIENTS;
! 1431: if (!strcasecmp (atom + 7, "-state"))
! 1432: return UNKNOWN_STATE;
! 1433: if (!atom [7])
! 1434: return UNKNOWN;
! 1435: break;
! 1436: }
! 1437: if (!strcasecmp (atom + 1, "nauthenticated"))
! 1438: return UNAUTHENTICATED;
! 1439: if (!strcasecmp (atom + 1, "pdated-dns-rr"))
! 1440: return UPDATED_DNS_RR;
! 1441: if (!strcasecmp (atom + 1, "pdate"))
! 1442: return UPDATE;
! 1443: break;
! 1444: case 'v':
! 1445: if (!strcasecmp (atom + 1, "endor-class"))
! 1446: return VENDOR_CLASS;
! 1447: if (!strcasecmp (atom + 1, "endor"))
! 1448: return VENDOR;
! 1449: break;
! 1450: case 'w':
! 1451: if (!strcasecmp (atom + 1, "ith"))
! 1452: return WITH;
! 1453: if (!strcasecmp(atom + 1, "idth"))
! 1454: return WIDTH;
! 1455: break;
! 1456: case 'y':
! 1457: if (!strcasecmp (atom + 1, "iaddr"))
! 1458: return YIADDR;
! 1459: if (!strcasecmp (atom + 1, "xdomain"))
! 1460: return NS_YXDOMAIN;
! 1461: if (!strcasecmp (atom + 1, "xrrset"))
! 1462: return NS_YXRRSET;
! 1463: break;
! 1464: case 'z':
! 1465: if (!strcasecmp (atom + 1, "erolen"))
! 1466: return ZEROLEN;
! 1467: if (!strcasecmp (atom + 1, "one"))
! 1468: return ZONE;
! 1469: break;
! 1470: }
! 1471: return dfv;
! 1472: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>