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