1 /* $NetBSD: ntp_scanner.c,v 1.11 2016/05/01 23:32:01 christos Exp $ */ 2 3 4 /* ntp_scanner.c 5 * 6 * The source code for a simple lexical analyzer. 7 * 8 * Written By: Sachin Kamboj 9 * University of Delaware 10 * Newark, DE 19711 11 * Copyright (c) 2006 12 */ 13 14 #ifdef HAVE_CONFIG_H 15 # include <config.h> 16 #endif 17 18 #include <stdio.h> 19 #include <ctype.h> 20 #include <stdlib.h> 21 #include <errno.h> 22 #include <string.h> 23 24 #include "ntpd.h" 25 #include "ntp_config.h" 26 #include "ntpsim.h" 27 #include "ntp_scanner.h" 28 #include "ntp_parser.h" 29 30 /* ntp_keyword.h declares finite state machine and token text */ 31 #include "ntp_keyword.h" 32 33 34 35 /* SCANNER GLOBAL VARIABLES 36 * ------------------------ 37 */ 38 39 #define MAX_LEXEME (1024 + 1) /* The maximum size of a lexeme */ 40 char yytext[MAX_LEXEME]; /* Buffer for storing the input text/lexeme */ 41 u_int32 conf_file_sum; /* Simple sum of characters read */ 42 43 static struct FILE_INFO * lex_stack = NULL; 44 45 46 47 /* CONSTANTS 48 * --------- 49 */ 50 51 52 /* SCANNER GLOBAL VARIABLES 53 * ------------------------ 54 */ 55 const char special_chars[] = "{}(),;|="; 56 57 58 /* FUNCTIONS 59 * --------- 60 */ 61 62 static int is_keyword(char *lexeme, follby *pfollowedby); 63 64 65 /* 66 * keyword() - Return the keyword associated with token T_ identifier. 67 * See also token_name() for the string-ized T_ identifier. 68 * Example: keyword(T_Server) returns "server" 69 * token_name(T_Server) returns "T_Server" 70 */ 71 const char * 72 keyword( 73 int token 74 ) 75 { 76 size_t i; 77 const char *text; 78 79 i = token - LOWEST_KEYWORD_ID; 80 81 if (i < COUNTOF(keyword_text)) 82 text = keyword_text[i]; 83 else 84 text = NULL; 85 86 return (text != NULL) 87 ? text 88 : "(keyword not found)"; 89 } 90 91 92 /* FILE & STRING BUFFER INTERFACE 93 * ------------------------------ 94 * 95 * This set out as a couple of wrapper functions around the standard C 96 * fgetc and ungetc functions in order to include positional 97 * bookkeeping. Alas, this is no longer a good solution with nested 98 * input files and the possibility to send configuration commands via 99 * 'ntpdc' and 'ntpq'. 100 * 101 * Now there are a few functions to maintain a stack of nested input 102 * sources (though nesting is only allowd for disk files) and from the 103 * scanner / parser point of view there's no difference between both 104 * types of sources. 105 * 106 * The 'fgetc()' / 'ungetc()' replacements now operate on a FILE_INFO 107 * structure. Instead of trying different 'ungetc()' strategies for file 108 * and buffer based parsing, we keep the backup char in our own 109 * FILE_INFO structure. This is sufficient, as the parser does *not* 110 * jump around via 'seek' or the like, and there's no need to 111 * check/clear the backup store in other places than 'lex_getch()'. 112 */ 113 114 /* 115 * Allocate an info structure and attach it to a file. 116 * 117 * Note: When 'mode' is NULL, then the INFO block will be set up to 118 * contain a NULL file pointer, as suited for remote config command 119 * parsing. Otherwise having a NULL file pointer is considered an error, 120 * and a NULL info block pointer is returned to indicate failure! 121 * 122 * Note: We use a variable-sized structure to hold a copy of the file 123 * name (or, more proper, the input source description). This is more 124 * secure than keeping a reference to some other storage that might go 125 * out of scope. 126 */ 127 static struct FILE_INFO * 128 lex_open( 129 const char *path, 130 const char *mode 131 ) 132 { 133 struct FILE_INFO *stream; 134 size_t nnambuf; 135 136 nnambuf = strlen(path); 137 stream = emalloc_zero(sizeof(*stream) + nnambuf); 138 stream->curpos.nline = 1; 139 stream->backch = EOF; 140 /* copy name with memcpy -- trailing NUL already there! */ 141 memcpy(stream->fname, path, nnambuf); 142 143 if (NULL != mode) { 144 stream->fpi = fopen(path, mode); 145 if (NULL == stream->fpi) { 146 free(stream); 147 stream = NULL; 148 } 149 } 150 return stream; 151 } 152 153 /* get next character from buffer or file. This will return any putback 154 * character first; it will also make sure the last line is at least 155 * virtually terminated with a '\n'. 156 */ 157 static int 158 lex_getch( 159 struct FILE_INFO *stream 160 ) 161 { 162 int ch; 163 164 if (NULL == stream || stream->force_eof) 165 return EOF; 166 167 if (EOF != stream->backch) { 168 ch = stream->backch; 169 stream->backch = EOF; 170 if (stream->fpi) 171 conf_file_sum += ch; 172 } else if (stream->fpi) { 173 /* fetch next 7-bit ASCII char (or EOF) from file */ 174 while ((ch = fgetc(stream->fpi)) != EOF && ch > SCHAR_MAX) 175 stream->curpos.ncol++; 176 if (EOF != ch) { 177 conf_file_sum += ch; 178 stream->curpos.ncol++; 179 } 180 } else { 181 /* fetch next 7-bit ASCII char from buffer */ 182 const char * scan; 183 scan = &remote_config.buffer[remote_config.pos]; 184 while ((ch = (u_char)*scan) > SCHAR_MAX) { 185 scan++; 186 stream->curpos.ncol++; 187 } 188 if ('\0' != ch) { 189 scan++; 190 stream->curpos.ncol++; 191 } else { 192 ch = EOF; 193 } 194 remote_config.pos = (int)(scan - remote_config.buffer); 195 } 196 197 /* If the last line ends without '\n', generate one. This 198 * happens most likely on Windows, where editors often have a 199 * sloppy concept of a line. 200 */ 201 if (EOF == ch && stream->curpos.ncol != 0) 202 ch = '\n'; 203 204 /* update scan position tallies */ 205 if (ch == '\n') { 206 stream->bakpos = stream->curpos; 207 stream->curpos.nline++; 208 stream->curpos.ncol = 0; 209 } 210 211 return ch; 212 } 213 214 /* Note: lex_ungetch will fail to track more than one line of push 215 * back. But since it guarantees only one char of back storage anyway, 216 * this should not be a problem. 217 */ 218 static int 219 lex_ungetch( 220 int ch, 221 struct FILE_INFO *stream 222 ) 223 { 224 /* check preconditions */ 225 if (NULL == stream || stream->force_eof) 226 return EOF; 227 if (EOF != stream->backch || EOF == ch) 228 return EOF; 229 230 /* keep for later reference and update checksum */ 231 stream->backch = (u_char)ch; 232 if (stream->fpi) 233 conf_file_sum -= stream->backch; 234 235 /* update position */ 236 if (stream->backch == '\n') { 237 stream->curpos = stream->bakpos; 238 stream->bakpos.ncol = -1; 239 } 240 stream->curpos.ncol--; 241 return stream->backch; 242 } 243 244 /* dispose of an input structure. If the file pointer is not NULL, close 245 * the file. This function does not check the result of 'fclose()'. 246 */ 247 static void 248 lex_close( 249 struct FILE_INFO *stream 250 ) 251 { 252 if (NULL != stream) { 253 if (NULL != stream->fpi) 254 fclose(stream->fpi); 255 free(stream); 256 } 257 } 258 259 /* INPUT STACK 260 * ----------- 261 * 262 * Nested input sources are a bit tricky at first glance. We deal with 263 * this problem using a stack of input sources, that is, a forward 264 * linked list of FILE_INFO structs. 265 * 266 * This stack is never empty during parsing; while an encounter with EOF 267 * can and will remove nested input sources, removing the last element 268 * in the stack will not work during parsing, and the EOF condition of 269 * the outermost input file remains until the parser folds up. 270 */ 271 272 static struct FILE_INFO * 273 _drop_stack_do( 274 struct FILE_INFO * head 275 ) 276 { 277 struct FILE_INFO * tail; 278 while (NULL != head) { 279 tail = head->st_next; 280 lex_close(head); 281 head = tail; 282 } 283 return head; 284 } 285 286 287 288 /* Create a singleton input source on an empty lexer stack. This will 289 * fail if there is already an input source, or if the underlying disk 290 * file cannot be opened. 291 * 292 * Returns TRUE if a new input object was successfully created. 293 */ 294 int/*BOOL*/ 295 lex_init_stack( 296 const char * path, 297 const char * mode 298 ) 299 { 300 if (NULL != lex_stack || NULL == path) 301 return FALSE; 302 303 lex_stack = lex_open(path, mode); 304 return (NULL != lex_stack); 305 } 306 307 /* This removes *all* input sources from the stack, leaving the head 308 * pointer as NULL. Any attempt to parse in that state is likely to bomb 309 * with segmentation faults or the like. 310 * 311 * In other words: Use this to clean up after parsing, and do not parse 312 * anything until the next 'lex_init_stack()' succeeded. 313 */ 314 void 315 lex_drop_stack() 316 { 317 lex_stack = _drop_stack_do(lex_stack); 318 } 319 320 /* Flush the lexer input stack: This will nip all input objects on the 321 * stack (but keeps the current top-of-stack) and marks the top-of-stack 322 * as inactive. Any further calls to lex_getch yield only EOF, and it's 323 * no longer possible to push something back. 324 * 325 * Returns TRUE if there is a head element (top-of-stack) that was not 326 * in the force-eof mode before this call. 327 */ 328 int/*BOOL*/ 329 lex_flush_stack() 330 { 331 int retv = FALSE; 332 333 if (NULL != lex_stack) { 334 retv = !lex_stack->force_eof; 335 lex_stack->force_eof = TRUE; 336 lex_stack->st_next = _drop_stack_do( 337 lex_stack->st_next); 338 } 339 return retv; 340 } 341 342 /* Push another file on the parsing stack. If the mode is NULL, create a 343 * FILE_INFO suitable for in-memory parsing; otherwise, create a 344 * FILE_INFO that is bound to a local/disc file. Note that 'path' must 345 * not be NULL, or the function will fail. 346 * 347 * Returns TRUE if a new info record was pushed onto the stack. 348 */ 349 int/*BOOL*/ lex_push_file( 350 const char * path, 351 const char * mode 352 ) 353 { 354 struct FILE_INFO * next = NULL; 355 356 if (NULL != path) { 357 next = lex_open(path, mode); 358 if (NULL != next) { 359 next->st_next = lex_stack; 360 lex_stack = next; 361 } 362 } 363 return (NULL != next); 364 } 365 366 /* Pop, close & free the top of the include stack, unless the stack 367 * contains only a singleton input object. In that case the function 368 * fails, because the parser does not expect the input stack to be 369 * empty. 370 * 371 * Returns TRUE if an object was successfuly popped from the stack. 372 */ 373 int/*BOOL*/ 374 lex_pop_file(void) 375 { 376 struct FILE_INFO * head = lex_stack; 377 struct FILE_INFO * tail = NULL; 378 379 if (NULL != head) { 380 tail = head->st_next; 381 if (NULL != tail) { 382 lex_stack = tail; 383 lex_close(head); 384 } 385 } 386 return (NULL != tail); 387 } 388 389 /* Get include nesting level. This currently loops over the stack and 390 * counts elements; but since this is of concern only with an include 391 * statement and the nesting depth has a small limit, there's no 392 * bottleneck expected here. 393 * 394 * Returns the nesting level of includes, that is, the current depth of 395 * the lexer input stack. 396 * 397 * Note: 398 */ 399 size_t 400 lex_level(void) 401 { 402 size_t cnt = 0; 403 struct FILE_INFO *ipf = lex_stack; 404 405 while (NULL != ipf) { 406 cnt++; 407 ipf = ipf->st_next; 408 } 409 return cnt; 410 } 411 412 /* check if the current input is from a file */ 413 int/*BOOL*/ 414 lex_from_file(void) 415 { 416 return (NULL != lex_stack) && (NULL != lex_stack->fpi); 417 } 418 419 struct FILE_INFO * 420 lex_current() 421 { 422 /* this became so simple, it could be a macro. But then, 423 * lex_stack needed to be global... 424 */ 425 return lex_stack; 426 } 427 428 429 /* STATE MACHINES 430 * -------------- 431 */ 432 433 /* Keywords */ 434 static int 435 is_keyword( 436 char *lexeme, 437 follby *pfollowedby 438 ) 439 { 440 follby fb; 441 int curr_s; /* current state index */ 442 int token; 443 int i; 444 445 curr_s = SCANNER_INIT_S; 446 token = 0; 447 448 for (i = 0; lexeme[i]; i++) { 449 while (curr_s && (lexeme[i] != SS_CH(sst[curr_s]))) 450 curr_s = SS_OTHER_N(sst[curr_s]); 451 452 if (curr_s && (lexeme[i] == SS_CH(sst[curr_s]))) { 453 if ('\0' == lexeme[i + 1] 454 && FOLLBY_NON_ACCEPTING 455 != SS_FB(sst[curr_s])) { 456 fb = SS_FB(sst[curr_s]); 457 *pfollowedby = fb; 458 token = curr_s; 459 break; 460 } 461 curr_s = SS_MATCH_N(sst[curr_s]); 462 } else 463 break; 464 } 465 466 return token; 467 } 468 469 470 /* Integer */ 471 static int 472 is_integer( 473 char *lexeme 474 ) 475 { 476 int i; 477 int is_neg; 478 u_int u_val; 479 480 i = 0; 481 482 /* Allow a leading minus sign */ 483 if (lexeme[i] == '-') { 484 i++; 485 is_neg = TRUE; 486 } else { 487 is_neg = FALSE; 488 } 489 490 /* Check that all the remaining characters are digits */ 491 for (; lexeme[i] != '\0'; i++) { 492 if (!isdigit((u_char)lexeme[i])) 493 return FALSE; 494 } 495 496 if (is_neg) 497 return TRUE; 498 499 /* Reject numbers that fit in unsigned but not in signed int */ 500 if (1 == sscanf(lexeme, "%u", &u_val)) 501 return (u_val <= INT_MAX); 502 else 503 return FALSE; 504 } 505 506 507 /* U_int -- assumes is_integer() has returned FALSE */ 508 static int 509 is_u_int( 510 char *lexeme 511 ) 512 { 513 int i; 514 int is_hex; 515 516 i = 0; 517 if ('0' == lexeme[i] && 'x' == tolower((u_char)lexeme[i + 1])) { 518 i += 2; 519 is_hex = TRUE; 520 } else { 521 is_hex = FALSE; 522 } 523 524 /* Check that all the remaining characters are digits */ 525 for (; lexeme[i] != '\0'; i++) { 526 if (is_hex && !isxdigit((u_char)lexeme[i])) 527 return FALSE; 528 if (!is_hex && !isdigit((u_char)lexeme[i])) 529 return FALSE; 530 } 531 532 return TRUE; 533 } 534 535 536 /* Double */ 537 static int 538 is_double( 539 char *lexeme 540 ) 541 { 542 u_int num_digits = 0; /* Number of digits read */ 543 u_int i; 544 545 i = 0; 546 547 /* Check for an optional '+' or '-' */ 548 if ('+' == lexeme[i] || '-' == lexeme[i]) 549 i++; 550 551 /* Read the integer part */ 552 for (; lexeme[i] && isdigit((u_char)lexeme[i]); i++) 553 num_digits++; 554 555 /* Check for the optional decimal point */ 556 if ('.' == lexeme[i]) { 557 i++; 558 /* Check for any digits after the decimal point */ 559 for (; lexeme[i] && isdigit((u_char)lexeme[i]); i++) 560 num_digits++; 561 } 562 563 /* 564 * The number of digits in both the decimal part and the 565 * fraction part must not be zero at this point 566 */ 567 if (!num_digits) 568 return 0; 569 570 /* Check if we are done */ 571 if (!lexeme[i]) 572 return 1; 573 574 /* There is still more input, read the exponent */ 575 if ('e' == tolower((u_char)lexeme[i])) 576 i++; 577 else 578 return 0; 579 580 /* Read an optional Sign */ 581 if ('+' == lexeme[i] || '-' == lexeme[i]) 582 i++; 583 584 /* Now read the exponent part */ 585 while (lexeme[i] && isdigit((u_char)lexeme[i])) 586 i++; 587 588 /* Check if we are done */ 589 if (!lexeme[i]) 590 return 1; 591 else 592 return 0; 593 } 594 595 596 /* is_special() - Test whether a character is a token */ 597 static inline int 598 is_special( 599 int ch 600 ) 601 { 602 return strchr(special_chars, ch) != NULL; 603 } 604 605 606 static int 607 is_EOC( 608 int ch 609 ) 610 { 611 if ((old_config_style && (ch == '\n')) || 612 (!old_config_style && (ch == ';'))) 613 return 1; 614 return 0; 615 } 616 617 618 char * 619 quote_if_needed(char *str) 620 { 621 char *ret; 622 size_t len; 623 size_t octets; 624 625 len = strlen(str); 626 octets = len + 2 + 1; 627 ret = emalloc(octets); 628 if ('"' != str[0] 629 && (strcspn(str, special_chars) < len 630 || strchr(str, ' ') != NULL)) { 631 snprintf(ret, octets, "\"%s\"", str); 632 } else 633 strlcpy(ret, str, octets); 634 635 return ret; 636 } 637 638 639 static int 640 create_string_token( 641 char *lexeme 642 ) 643 { 644 char *pch; 645 646 /* 647 * ignore end of line whitespace 648 */ 649 pch = lexeme; 650 while (*pch && isspace((u_char)*pch)) 651 pch++; 652 653 if (!*pch) { 654 yylval.Integer = T_EOC; 655 return yylval.Integer; 656 } 657 658 yylval.String = estrdup(lexeme); 659 return T_String; 660 } 661 662 663 /* 664 * yylex() - function that does the actual scanning. 665 * Bison expects this function to be called yylex and for it to take no 666 * input and return an int. 667 * Conceptually yylex "returns" yylval as well as the actual return 668 * value representing the token or type. 669 */ 670 int 671 yylex(void) 672 { 673 static follby followedby = FOLLBY_TOKEN; 674 size_t i; 675 int instring; 676 int yylval_was_set; 677 int converted; 678 int token; /* The return value */ 679 int ch; 680 681 instring = FALSE; 682 yylval_was_set = FALSE; 683 684 do { 685 /* Ignore whitespace at the beginning */ 686 while (EOF != (ch = lex_getch(lex_stack)) && 687 isspace(ch) && 688 !is_EOC(ch)) 689 690 ; /* Null Statement */ 691 692 if (EOF == ch) { 693 694 if ( ! lex_pop_file()) 695 return 0; 696 token = T_EOC; 697 goto normal_return; 698 699 } else if (is_EOC(ch)) { 700 701 /* end FOLLBY_STRINGS_TO_EOC effect */ 702 followedby = FOLLBY_TOKEN; 703 token = T_EOC; 704 goto normal_return; 705 706 } else if (is_special(ch) && FOLLBY_TOKEN == followedby) { 707 /* special chars are their own token values */ 708 token = ch; 709 /* 710 * '=' outside simulator configuration implies 711 * a single string following as in: 712 * setvar Owner = "The Boss" default 713 */ 714 if ('=' == ch && old_config_style) 715 followedby = FOLLBY_STRING; 716 yytext[0] = (char)ch; 717 yytext[1] = '\0'; 718 goto normal_return; 719 } else 720 lex_ungetch(ch, lex_stack); 721 722 /* save the position of start of the token */ 723 lex_stack->tokpos = lex_stack->curpos; 724 725 /* Read in the lexeme */ 726 i = 0; 727 while (EOF != (ch = lex_getch(lex_stack))) { 728 729 yytext[i] = (char)ch; 730 731 /* Break on whitespace or a special character */ 732 if (isspace(ch) || is_EOC(ch) 733 || '"' == ch 734 || (FOLLBY_TOKEN == followedby 735 && is_special(ch))) 736 break; 737 738 /* Read the rest of the line on reading a start 739 of comment character */ 740 if ('#' == ch) { 741 while (EOF != (ch = lex_getch(lex_stack)) 742 && '\n' != ch) 743 ; /* Null Statement */ 744 break; 745 } 746 747 i++; 748 if (i >= COUNTOF(yytext)) 749 goto lex_too_long; 750 } 751 /* Pick up all of the string inside between " marks, to 752 * end of line. If we make it to EOL without a 753 * terminating " assume it for them. 754 * 755 * XXX - HMS: I'm not sure we want to assume the closing " 756 */ 757 if ('"' == ch) { 758 instring = TRUE; 759 while (EOF != (ch = lex_getch(lex_stack)) && 760 ch != '"' && ch != '\n') { 761 yytext[i++] = (char)ch; 762 if (i >= COUNTOF(yytext)) 763 goto lex_too_long; 764 } 765 /* 766 * yytext[i] will be pushed back as not part of 767 * this lexeme, but any closing quote should 768 * not be pushed back, so we read another char. 769 */ 770 if ('"' == ch) 771 ch = lex_getch(lex_stack); 772 } 773 /* Pushback the last character read that is not a part 774 * of this lexeme. This fails silently if ch is EOF, 775 * but then the EOF condition persists and is handled on 776 * the next turn by the include stack mechanism. 777 */ 778 lex_ungetch(ch, lex_stack); 779 780 yytext[i] = '\0'; 781 } while (i == 0); 782 783 /* Now return the desired token */ 784 785 /* First make sure that the parser is *not* expecting a string 786 * as the next token (based on the previous token that was 787 * returned) and that we haven't read a string. 788 */ 789 790 if (followedby == FOLLBY_TOKEN && !instring) { 791 token = is_keyword(yytext, &followedby); 792 if (token) { 793 /* 794 * T_Server is exceptional as it forces the 795 * following token to be a string in the 796 * non-simulator parts of the configuration, 797 * but in the simulator configuration section, 798 * "server" is followed by "=" which must be 799 * recognized as a token not a string. 800 */ 801 if (T_Server == token && !old_config_style) 802 followedby = FOLLBY_TOKEN; 803 goto normal_return; 804 } else if (is_integer(yytext)) { 805 yylval_was_set = TRUE; 806 errno = 0; 807 if ((yylval.Integer = strtol(yytext, NULL, 10)) == 0 808 && ((errno == EINVAL) || (errno == ERANGE))) { 809 msyslog(LOG_ERR, 810 "Integer cannot be represented: %s", 811 yytext); 812 if (lex_from_file()) { 813 exit(1); 814 } else { 815 /* force end of parsing */ 816 yylval.Integer = 0; 817 return 0; 818 } 819 } 820 token = T_Integer; 821 goto normal_return; 822 } else if (is_u_int(yytext)) { 823 yylval_was_set = TRUE; 824 if ('0' == yytext[0] && 825 'x' == tolower((unsigned long)yytext[1])) 826 converted = sscanf(&yytext[2], "%x", 827 &yylval.U_int); 828 else 829 converted = sscanf(yytext, "%u", 830 &yylval.U_int); 831 if (1 != converted) { 832 msyslog(LOG_ERR, 833 "U_int cannot be represented: %s", 834 yytext); 835 if (lex_from_file()) { 836 exit(1); 837 } else { 838 /* force end of parsing */ 839 yylval.Integer = 0; 840 return 0; 841 } 842 } 843 token = T_U_int; 844 goto normal_return; 845 } else if (is_double(yytext)) { 846 yylval_was_set = TRUE; 847 errno = 0; 848 if ((yylval.Double = atof(yytext)) == 0 && errno == ERANGE) { 849 msyslog(LOG_ERR, 850 "Double too large to represent: %s", 851 yytext); 852 exit(1); 853 } else { 854 token = T_Double; 855 goto normal_return; 856 } 857 } else { 858 /* Default: Everything is a string */ 859 yylval_was_set = TRUE; 860 token = create_string_token(yytext); 861 goto normal_return; 862 } 863 } 864 865 /* 866 * Either followedby is not FOLLBY_TOKEN or this lexeme is part 867 * of a string. Hence, we need to return T_String. 868 * 869 * _Except_ we might have a -4 or -6 flag on a an association 870 * configuration line (server, peer, pool, etc.). 871 * 872 * This is a terrible hack, but the grammar is ambiguous so we 873 * don't have a choice. [SK] 874 * 875 * The ambiguity is in the keyword scanner, not ntp_parser.y. 876 * We do not require server addresses be quoted in ntp.conf, 877 * complicating the scanner's job. To avoid trying (and 878 * failing) to match an IP address or DNS name to a keyword, 879 * the association keywords use FOLLBY_STRING in the keyword 880 * table, which tells the scanner to force the next token to be 881 * a T_String, so it does not try to match a keyword but rather 882 * expects a string when -4/-6 modifiers to server, peer, etc. 883 * are encountered. 884 * restrict -4 and restrict -6 parsing works correctly without 885 * this hack, as restrict uses FOLLBY_TOKEN. [DH] 886 */ 887 if ('-' == yytext[0]) { 888 if ('4' == yytext[1]) { 889 token = T_Ipv4_flag; 890 goto normal_return; 891 } else if ('6' == yytext[1]) { 892 token = T_Ipv6_flag; 893 goto normal_return; 894 } 895 } 896 897 instring = FALSE; 898 if (FOLLBY_STRING == followedby) 899 followedby = FOLLBY_TOKEN; 900 901 yylval_was_set = TRUE; 902 token = create_string_token(yytext); 903 904 normal_return: 905 if (T_EOC == token) 906 DPRINTF(4,("\t<end of command>\n")); 907 else 908 DPRINTF(4, ("yylex: lexeme '%s' -> %s\n", yytext, 909 token_name(token))); 910 911 if (!yylval_was_set) 912 yylval.Integer = token; 913 914 return token; 915 916 lex_too_long: 917 yytext[min(sizeof(yytext) - 1, 50)] = 0; 918 msyslog(LOG_ERR, 919 "configuration item on line %d longer than limit of %lu, began with '%s'", 920 lex_stack->curpos.nline, (u_long)min(sizeof(yytext) - 1, 50), 921 yytext); 922 923 /* 924 * If we hit the length limit reading the startup configuration 925 * file, abort. 926 */ 927 if (lex_from_file()) 928 exit(sizeof(yytext) - 1); 929 930 /* 931 * If it's runtime configuration via ntpq :config treat it as 932 * if the configuration text ended before the too-long lexeme, 933 * hostname, or string. 934 */ 935 yylval.Integer = 0; 936 return 0; 937 } 938