xref: /netbsd-src/external/bsd/ntp/dist/ntpd/ntp_scanner.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: ntp_scanner.c,v 1.13 2018/04/07 00:19:53 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 		stream->curpos.ncol++;
173 	} else if (stream->fpi) {
174 		/* fetch next 7-bit ASCII char (or EOF) from file */
175 		while ((ch = fgetc(stream->fpi)) != EOF && ch > SCHAR_MAX)
176 			stream->curpos.ncol++;
177 		if (EOF != ch) {
178 			conf_file_sum += ch;
179 			stream->curpos.ncol++;
180 		}
181 	} else {
182 		/* fetch next 7-bit ASCII char from buffer */
183 		const char * scan;
184 		scan = &remote_config.buffer[remote_config.pos];
185 		while ((ch = (u_char)*scan) > SCHAR_MAX) {
186 			scan++;
187 			stream->curpos.ncol++;
188 		}
189 		if ('\0' != ch) {
190 			scan++;
191 			stream->curpos.ncol++;
192 		} else {
193 			ch = EOF;
194 		}
195 		remote_config.pos = (int)(scan - remote_config.buffer);
196 	}
197 
198 	/* If the last line ends without '\n', generate one. This
199 	 * happens most likely on Windows, where editors often have a
200 	 * sloppy concept of a line.
201 	 */
202 	if (EOF == ch && stream->curpos.ncol != 0)
203 		ch = '\n';
204 
205 	/* update scan position tallies */
206 	if (ch == '\n') {
207 		stream->bakpos = stream->curpos;
208 		stream->curpos.nline++;
209 		stream->curpos.ncol = 0;
210 	}
211 
212 	return ch;
213 }
214 
215 /* Note: lex_ungetch will fail to track more than one line of push
216  * back. But since it guarantees only one char of back storage anyway,
217  * this should not be a problem.
218  */
219 static int
220 lex_ungetch(
221 	int ch,
222 	struct FILE_INFO *stream
223 	)
224 {
225 	/* check preconditions */
226 	if (NULL == stream || stream->force_eof)
227 		return EOF;
228 	if (EOF != stream->backch || EOF == ch)
229 		return EOF;
230 
231 	/* keep for later reference and update checksum */
232 	stream->backch = (u_char)ch;
233 	if (stream->fpi)
234 		conf_file_sum -= stream->backch;
235 
236 	/* update position */
237 	if (stream->backch == '\n') {
238 	    stream->curpos = stream->bakpos;
239 	    stream->bakpos.ncol = -1;
240 	}
241 	stream->curpos.ncol--;
242 	return stream->backch;
243 }
244 
245 /* dispose of an input structure. If the file pointer is not NULL, close
246  * the file. This function does not check the result of 'fclose()'.
247  */
248 static void
249 lex_close(
250 	struct FILE_INFO *stream
251 	)
252 {
253 	if (NULL != stream) {
254 		if (NULL != stream->fpi)
255 			fclose(stream->fpi);
256 		free(stream);
257 	}
258 }
259 
260 /* INPUT STACK
261  * -----------
262  *
263  * Nested input sources are a bit tricky at first glance. We deal with
264  * this problem using a stack of input sources, that is, a forward
265  * linked list of FILE_INFO structs.
266  *
267  * This stack is never empty during parsing; while an encounter with EOF
268  * can and will remove nested input sources, removing the last element
269  * in the stack will not work during parsing, and the EOF condition of
270  * the outermost input file remains until the parser folds up.
271  */
272 
273 static struct FILE_INFO *
274 _drop_stack_do(
275 	struct FILE_INFO * head
276 	)
277 {
278 	struct FILE_INFO * tail;
279 	while (NULL != head) {
280 		tail = head->st_next;
281 		lex_close(head);
282 		head = tail;
283 	}
284 	return head;
285 }
286 
287 
288 
289 /* Create a singleton input source on an empty lexer stack. This will
290  * fail if there is already an input source, or if the underlying disk
291  * file cannot be opened.
292  *
293  * Returns TRUE if a new input object was successfully created.
294  */
295 int/*BOOL*/
296 lex_init_stack(
297 	const char * path,
298 	const char * mode
299 	)
300 {
301 	if (NULL != lex_stack || NULL == path)
302 		return FALSE;
303 
304 	lex_stack = lex_open(path, mode);
305 	return (NULL != lex_stack);
306 }
307 
308 /* This removes *all* input sources from the stack, leaving the head
309  * pointer as NULL. Any attempt to parse in that state is likely to bomb
310  * with segmentation faults or the like.
311  *
312  * In other words: Use this to clean up after parsing, and do not parse
313  * anything until the next 'lex_init_stack()' succeeded.
314  */
315 void
316 lex_drop_stack()
317 {
318 	lex_stack = _drop_stack_do(lex_stack);
319 }
320 
321 /* Flush the lexer input stack: This will nip all input objects on the
322  * stack (but keeps the current top-of-stack) and marks the top-of-stack
323  * as inactive. Any further calls to lex_getch yield only EOF, and it's
324  * no longer possible to push something back.
325  *
326  * Returns TRUE if there is a head element (top-of-stack) that was not
327  * in the force-eof mode before this call.
328  */
329 int/*BOOL*/
330 lex_flush_stack()
331 {
332 	int retv = FALSE;
333 
334 	if (NULL != lex_stack) {
335 		retv = !lex_stack->force_eof;
336 		lex_stack->force_eof = TRUE;
337 		lex_stack->st_next = _drop_stack_do(
338 					lex_stack->st_next);
339 	}
340 	return retv;
341 }
342 
343 /* Push another file on the parsing stack. If the mode is NULL, create a
344  * FILE_INFO suitable for in-memory parsing; otherwise, create a
345  * FILE_INFO that is bound to a local/disc file. Note that 'path' must
346  * not be NULL, or the function will fail.
347  *
348  * Returns TRUE if a new info record was pushed onto the stack.
349  */
350 int/*BOOL*/ lex_push_file(
351 	const char * path,
352 	const char * mode
353 	)
354 {
355 	struct FILE_INFO * next = NULL;
356 
357 	if (NULL != path) {
358 		next = lex_open(path, mode);
359 		if (NULL != next) {
360 			next->st_next = lex_stack;
361 			lex_stack = next;
362 		}
363 	}
364 	return (NULL != next);
365 }
366 
367 /* Pop, close & free the top of the include stack, unless the stack
368  * contains only a singleton input object. In that case the function
369  * fails, because the parser does not expect the input stack to be
370  * empty.
371  *
372  * Returns TRUE if an object was successfuly popped from the stack.
373  */
374 int/*BOOL*/
375 lex_pop_file(void)
376 {
377 	struct FILE_INFO * head = lex_stack;
378 	struct FILE_INFO * tail = NULL;
379 
380 	if (NULL != head) {
381 		tail = head->st_next;
382 		if (NULL != tail) {
383 			lex_stack = tail;
384 			lex_close(head);
385 		}
386 	}
387 	return (NULL != tail);
388 }
389 
390 /* Get include nesting level. This currently loops over the stack and
391  * counts elements; but since this is of concern only with an include
392  * statement and the nesting depth has a small limit, there's no
393  * bottleneck expected here.
394  *
395  * Returns the nesting level of includes, that is, the current depth of
396  * the lexer input stack.
397  *
398  * Note:
399  */
400 size_t
401 lex_level(void)
402 {
403 	size_t            cnt = 0;
404 	struct FILE_INFO *ipf = lex_stack;
405 
406 	while (NULL != ipf) {
407 		cnt++;
408 		ipf = ipf->st_next;
409 	}
410 	return cnt;
411 }
412 
413 /* check if the current input is from a file */
414 int/*BOOL*/
415 lex_from_file(void)
416 {
417 	return (NULL != lex_stack) && (NULL != lex_stack->fpi);
418 }
419 
420 struct FILE_INFO *
421 lex_current()
422 {
423 	/* this became so simple, it could be a macro. But then,
424 	 * lex_stack needed to be global...
425 	 */
426 	return lex_stack;
427 }
428 
429 
430 /* STATE MACHINES
431  * --------------
432  */
433 
434 /* Keywords */
435 static int
436 is_keyword(
437 	char *lexeme,
438 	follby *pfollowedby
439 	)
440 {
441 	follby fb;
442 	int curr_s;		/* current state index */
443 	int token;
444 	int i;
445 
446 	curr_s = SCANNER_INIT_S;
447 	token = 0;
448 
449 	for (i = 0; lexeme[i]; i++) {
450 		while (curr_s && (lexeme[i] != SS_CH(sst[curr_s])))
451 			curr_s = SS_OTHER_N(sst[curr_s]);
452 
453 		if (curr_s && (lexeme[i] == SS_CH(sst[curr_s]))) {
454 			if ('\0' == lexeme[i + 1]
455 			    && FOLLBY_NON_ACCEPTING
456 			       != SS_FB(sst[curr_s])) {
457 				fb = SS_FB(sst[curr_s]);
458 				*pfollowedby = fb;
459 				token = curr_s;
460 				break;
461 			}
462 			curr_s = SS_MATCH_N(sst[curr_s]);
463 		} else
464 			break;
465 	}
466 
467 	return token;
468 }
469 
470 
471 /* Integer */
472 static int
473 is_integer(
474 	char *lexeme
475 	)
476 {
477 	int	i;
478 	int	is_neg;
479 	u_int	u_val;
480 
481 	i = 0;
482 
483 	/* Allow a leading minus sign */
484 	if (lexeme[i] == '-') {
485 		i++;
486 		is_neg = TRUE;
487 	} else {
488 		is_neg = FALSE;
489 	}
490 
491 	/* Check that all the remaining characters are digits */
492 	for (; lexeme[i] != '\0'; i++) {
493 		if (!isdigit((u_char)lexeme[i]))
494 			return FALSE;
495 	}
496 
497 	if (is_neg)
498 		return TRUE;
499 
500 	/* Reject numbers that fit in unsigned but not in signed int */
501 	if (1 == sscanf(lexeme, "%u", &u_val))
502 		return (u_val <= INT_MAX);
503 	else
504 		return FALSE;
505 }
506 
507 
508 /* U_int -- assumes is_integer() has returned FALSE */
509 static int
510 is_u_int(
511 	char *lexeme
512 	)
513 {
514 	int	i;
515 	int	is_hex;
516 
517 	i = 0;
518 	if ('0' == lexeme[i] && 'x' == tolower((u_char)lexeme[i + 1])) {
519 		i += 2;
520 		is_hex = TRUE;
521 	} else {
522 		is_hex = FALSE;
523 	}
524 
525 	/* Check that all the remaining characters are digits */
526 	for (; lexeme[i] != '\0'; i++) {
527 		if (is_hex && !isxdigit((u_char)lexeme[i]))
528 			return FALSE;
529 		if (!is_hex && !isdigit((u_char)lexeme[i]))
530 			return FALSE;
531 	}
532 
533 	return TRUE;
534 }
535 
536 
537 /* Double */
538 static int
539 is_double(
540 	char *lexeme
541 	)
542 {
543 	u_int num_digits = 0;  /* Number of digits read */
544 	u_int i;
545 
546 	i = 0;
547 
548 	/* Check for an optional '+' or '-' */
549 	if ('+' == lexeme[i] || '-' == lexeme[i])
550 		i++;
551 
552 	/* Read the integer part */
553 	for (; lexeme[i] && isdigit((u_char)lexeme[i]); i++)
554 		num_digits++;
555 
556 	/* Check for the optional decimal point */
557 	if ('.' == lexeme[i]) {
558 		i++;
559 		/* Check for any digits after the decimal point */
560 		for (; lexeme[i] && isdigit((u_char)lexeme[i]); i++)
561 			num_digits++;
562 	}
563 
564 	/*
565 	 * The number of digits in both the decimal part and the
566 	 * fraction part must not be zero at this point
567 	 */
568 	if (!num_digits)
569 		return 0;
570 
571 	/* Check if we are done */
572 	if (!lexeme[i])
573 		return 1;
574 
575 	/* There is still more input, read the exponent */
576 	if ('e' == tolower((u_char)lexeme[i]))
577 		i++;
578 	else
579 		return 0;
580 
581 	/* Read an optional Sign */
582 	if ('+' == lexeme[i] || '-' == lexeme[i])
583 		i++;
584 
585 	/* Now read the exponent part */
586 	while (lexeme[i] && isdigit((u_char)lexeme[i]))
587 		i++;
588 
589 	/* Check if we are done */
590 	if (!lexeme[i])
591 		return 1;
592 	else
593 		return 0;
594 }
595 
596 
597 /* is_special() - Test whether a character is a token */
598 static inline int
599 is_special(
600 	int ch
601 	)
602 {
603 	return strchr(special_chars, ch) != NULL;
604 }
605 
606 
607 static int
608 is_EOC(
609 	int ch
610 	)
611 {
612 	if ((old_config_style && (ch == '\n')) ||
613 	    (!old_config_style && (ch == ';')))
614 		return 1;
615 	return 0;
616 }
617 
618 
619 char *
620 quote_if_needed(char *str)
621 {
622 	char *ret;
623 	size_t len;
624 	size_t octets;
625 
626 	len = strlen(str);
627 	octets = len + 2 + 1;
628 	ret = emalloc(octets);
629 	if ('"' != str[0]
630 	    && (strcspn(str, special_chars) < len
631 		|| strchr(str, ' ') != NULL)) {
632 		snprintf(ret, octets, "\"%s\"", str);
633 	} else
634 		strlcpy(ret, str, octets);
635 
636 	return ret;
637 }
638 
639 
640 static int
641 create_string_token(
642 	char *lexeme
643 	)
644 {
645 	char *pch;
646 
647 	/*
648 	 * ignore end of line whitespace
649 	 */
650 	pch = lexeme;
651 	while (*pch && isspace((u_char)*pch))
652 		pch++;
653 
654 	if (!*pch) {
655 		yylval.Integer = T_EOC;
656 		return yylval.Integer;
657 	}
658 
659 	yylval.String = estrdup(lexeme);
660 	return T_String;
661 }
662 
663 
664 /*
665  * yylex() - function that does the actual scanning.
666  * Bison expects this function to be called yylex and for it to take no
667  * input and return an int.
668  * Conceptually yylex "returns" yylval as well as the actual return
669  * value representing the token or type.
670  */
671 int
672 yylex(void)
673 {
674 	static follby	followedby = FOLLBY_TOKEN;
675 	size_t		i;
676 	int		instring;
677 	int		yylval_was_set;
678 	int		converted;
679 	int		token;		/* The return value */
680 	int		ch;
681 
682 	instring = FALSE;
683 	yylval_was_set = FALSE;
684 
685 	do {
686 		/* Ignore whitespace at the beginning */
687 		while (EOF != (ch = lex_getch(lex_stack)) &&
688 		       isspace(ch) &&
689 		       !is_EOC(ch))
690 
691 			; /* Null Statement */
692 
693 		if (EOF == ch) {
694 
695 			if ( ! lex_pop_file())
696 				return 0;
697 			token = T_EOC;
698 			goto normal_return;
699 
700 		} else if (is_EOC(ch)) {
701 
702 			/* end FOLLBY_STRINGS_TO_EOC effect */
703 			followedby = FOLLBY_TOKEN;
704 			token = T_EOC;
705 			goto normal_return;
706 
707 		} else if (is_special(ch) && FOLLBY_TOKEN == followedby) {
708 			/* special chars are their own token values */
709 			token = ch;
710 			/*
711 			 * '=' outside simulator configuration implies
712 			 * a single string following as in:
713 			 * setvar Owner = "The Boss" default
714 			 */
715 			if ('=' == ch && old_config_style)
716 				followedby = FOLLBY_STRING;
717 			yytext[0] = (char)ch;
718 			yytext[1] = '\0';
719 			goto normal_return;
720 		} else
721 			lex_ungetch(ch, lex_stack);
722 
723 		/* save the position of start of the token */
724 		lex_stack->tokpos = lex_stack->curpos;
725 
726 		/* Read in the lexeme */
727 		i = 0;
728 		while (EOF != (ch = lex_getch(lex_stack))) {
729 
730 			yytext[i] = (char)ch;
731 
732 			/* Break on whitespace or a special character */
733 			if (isspace(ch) || is_EOC(ch)
734 			    || '"' == ch
735 			    || (FOLLBY_TOKEN == followedby
736 				&& is_special(ch)))
737 				break;
738 
739 			/* Read the rest of the line on reading a start
740 			   of comment character */
741 			if ('#' == ch) {
742 				while (EOF != (ch = lex_getch(lex_stack))
743 				       && '\n' != ch)
744 					; /* Null Statement */
745 				break;
746 			}
747 
748 			i++;
749 			if (i >= COUNTOF(yytext))
750 				goto lex_too_long;
751 		}
752 		/* Pick up all of the string inside between " marks, to
753 		 * end of line.  If we make it to EOL without a
754 		 * terminating " assume it for them.
755 		 *
756 		 * XXX - HMS: I'm not sure we want to assume the closing "
757 		 */
758 		if ('"' == ch) {
759 			instring = TRUE;
760 			while (EOF != (ch = lex_getch(lex_stack)) &&
761 			       ch != '"' && ch != '\n') {
762 				yytext[i++] = (char)ch;
763 				if (i >= COUNTOF(yytext))
764 					goto lex_too_long;
765 			}
766 			/*
767 			 * yytext[i] will be pushed back as not part of
768 			 * this lexeme, but any closing quote should
769 			 * not be pushed back, so we read another char.
770 			 */
771 			if ('"' == ch)
772 				ch = lex_getch(lex_stack);
773 		}
774 		/* Pushback the last character read that is not a part
775 		 * of this lexeme. This fails silently if ch is EOF,
776 		 * but then the EOF condition persists and is handled on
777 		 * the next turn by the include stack mechanism.
778 		 */
779 		lex_ungetch(ch, lex_stack);
780 
781 		yytext[i] = '\0';
782 	} while (i == 0);
783 
784 	/* Now return the desired token */
785 
786 	/* First make sure that the parser is *not* expecting a string
787 	 * as the next token (based on the previous token that was
788 	 * returned) and that we haven't read a string.
789 	 */
790 
791 	if (followedby == FOLLBY_TOKEN && !instring) {
792 		token = is_keyword(yytext, &followedby);
793 		if (token) {
794 			/*
795 			 * T_Server is exceptional as it forces the
796 			 * following token to be a string in the
797 			 * non-simulator parts of the configuration,
798 			 * but in the simulator configuration section,
799 			 * "server" is followed by "=" which must be
800 			 * recognized as a token not a string.
801 			 */
802 			if (T_Server == token && !old_config_style)
803 				followedby = FOLLBY_TOKEN;
804 			goto normal_return;
805 		} else if (is_integer(yytext)) {
806 			yylval_was_set = TRUE;
807 			errno = 0;
808 			if ((yylval.Integer = strtol(yytext, NULL, 10)) == 0
809 			    && ((errno == EINVAL) || (errno == ERANGE))) {
810 				msyslog(LOG_ERR,
811 					"Integer cannot be represented: %s",
812 					yytext);
813 				if (lex_from_file()) {
814 					exit(1);
815 				} else {
816 					/* force end of parsing */
817 					yylval.Integer = 0;
818 					return 0;
819 				}
820 			}
821 			token = T_Integer;
822 			goto normal_return;
823 		} else if (is_u_int(yytext)) {
824 			yylval_was_set = TRUE;
825 			if ('0' == yytext[0] &&
826 			    'x' == tolower((unsigned long)yytext[1]))
827 				converted = sscanf(&yytext[2], "%x",
828 						   &yylval.U_int);
829 			else
830 				converted = sscanf(yytext, "%u",
831 						   &yylval.U_int);
832 			if (1 != converted) {
833 				msyslog(LOG_ERR,
834 					"U_int cannot be represented: %s",
835 					yytext);
836 				if (lex_from_file()) {
837 					exit(1);
838 				} else {
839 					/* force end of parsing */
840 					yylval.Integer = 0;
841 					return 0;
842 				}
843 			}
844 			token = T_U_int;
845 			goto normal_return;
846 		} else if (is_double(yytext)) {
847 			yylval_was_set = TRUE;
848 			errno = 0;
849 			if ((yylval.Double = atof(yytext)) == 0 && errno == ERANGE) {
850 				msyslog(LOG_ERR,
851 					"Double too large to represent: %s",
852 					yytext);
853 				exit(1);
854 			} else {
855 				token = T_Double;
856 				goto normal_return;
857 			}
858 		} else {
859 			/* Default: Everything is a string */
860 			yylval_was_set = TRUE;
861 			token = create_string_token(yytext);
862 			goto normal_return;
863 		}
864 	}
865 
866 	/*
867 	 * Either followedby is not FOLLBY_TOKEN or this lexeme is part
868 	 * of a string.  Hence, we need to return T_String.
869 	 *
870 	 * _Except_ we might have a -4 or -6 flag on a an association
871 	 * configuration line (server, peer, pool, etc.).
872 	 *
873 	 * This is a terrible hack, but the grammar is ambiguous so we
874 	 * don't have a choice.  [SK]
875 	 *
876 	 * The ambiguity is in the keyword scanner, not ntp_parser.y.
877 	 * We do not require server addresses be quoted in ntp.conf,
878 	 * complicating the scanner's job.  To avoid trying (and
879 	 * failing) to match an IP address or DNS name to a keyword,
880 	 * the association keywords use FOLLBY_STRING in the keyword
881 	 * table, which tells the scanner to force the next token to be
882 	 * a T_String, so it does not try to match a keyword but rather
883 	 * expects a string when -4/-6 modifiers to server, peer, etc.
884 	 * are encountered.
885 	 * restrict -4 and restrict -6 parsing works correctly without
886 	 * this hack, as restrict uses FOLLBY_TOKEN.  [DH]
887 	 */
888 	if ('-' == yytext[0]) {
889 		if ('4' == yytext[1]) {
890 			token = T_Ipv4_flag;
891 			goto normal_return;
892 		} else if ('6' == yytext[1]) {
893 			token = T_Ipv6_flag;
894 			goto normal_return;
895 		}
896 	}
897 
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