File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / keyword-gen.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * keyword-gen.c -- generate keyword scanner finite state machine and
    3:  *		    keyword_text array.
    4:  *		    This program is run to generate ntp_keyword.h
    5:  */
    6: #include <config.h>
    7: #include <stdio.h>
    8: #include <stdlib.h>
    9: #include <time.h>
   10: 
   11: #include <ntp_stdlib.h>
   12: #include <ntp_config.h>
   13: #include <lib_strbuf.h>
   14: #include "ntp_scanner.h"
   15: #include "ntp_parser.h"
   16: 
   17: 
   18: #ifdef QSORT_USES_VOID_P
   19: typedef const void *	QSORTP;
   20: #else
   21: typedef char *		QSORTP;
   22: #endif
   23: 
   24: /* Define a structure to hold a (keyword, token) pair */
   25: struct key_tok {
   26: 	char *	key;		/* Keyword */
   27: 	int	token;		/* Associated Token */
   28: 	follby	followedby;	/* nonzero indicates the next token(s)
   29: 				   forced to be string(s) */
   30: };
   31: 
   32: struct key_tok ntp_keywords[] = {
   33: { "...",		T_Ellipsis,		FOLLBY_TOKEN },
   34: { "automax",		T_Automax,		FOLLBY_TOKEN },
   35: { "broadcast",		T_Broadcast,		FOLLBY_STRING },
   36: { "broadcastclient",	T_Broadcastclient,	FOLLBY_TOKEN },
   37: { "broadcastdelay",	T_Broadcastdelay,	FOLLBY_TOKEN },
   38: { "calldelay",		T_Calldelay,		FOLLBY_TOKEN },
   39: { "disable",		T_Disable,		FOLLBY_TOKEN },
   40: { "driftfile",		T_Driftfile,		FOLLBY_STRING },
   41: { "enable",		T_Enable,		FOLLBY_TOKEN },
   42: { "end",		T_End,			FOLLBY_TOKEN },
   43: { "filegen",		T_Filegen,		FOLLBY_TOKEN },
   44: { "fudge",		T_Fudge,		FOLLBY_STRING },
   45: { "includefile",	T_Includefile,		FOLLBY_STRING },
   46: { "leapfile",		T_Leapfile,		FOLLBY_STRING },
   47: { "logconfig",		T_Logconfig,		FOLLBY_STRINGS_TO_EOC },
   48: { "logfile",		T_Logfile,		FOLLBY_STRING },
   49: { "manycastclient",	T_Manycastclient,	FOLLBY_STRING },
   50: { "manycastserver",	T_Manycastserver,	FOLLBY_STRINGS_TO_EOC },
   51: { "multicastclient",	T_Multicastclient,	FOLLBY_STRINGS_TO_EOC },
   52: { "peer",		T_Peer,			FOLLBY_STRING },
   53: { "phone",		T_Phone,		FOLLBY_STRINGS_TO_EOC },
   54: { "pidfile",		T_Pidfile,		FOLLBY_STRING },
   55: { "pool",		T_Pool,			FOLLBY_STRING },
   56: { "discard",		T_Discard,		FOLLBY_TOKEN },
   57: { "restrict",		T_Restrict,		FOLLBY_TOKEN },
   58: { "server",		T_Server,		FOLLBY_STRING },
   59: { "setvar",		T_Setvar,		FOLLBY_STRING },
   60: { "statistics",		T_Statistics,		FOLLBY_TOKEN },
   61: { "statsdir",		T_Statsdir,		FOLLBY_STRING },
   62: { "tick",		T_Tick,			FOLLBY_TOKEN },
   63: { "tinker",		T_Tinker,		FOLLBY_TOKEN },
   64: { "tos",		T_Tos,			FOLLBY_TOKEN },
   65: { "trap",		T_Trap,			FOLLBY_STRING },
   66: { "unconfig",		T_Unconfig,		FOLLBY_STRING },
   67: { "unpeer",		T_Unpeer,		FOLLBY_STRING },
   68: /* authentication_command */
   69: { "controlkey",		T_ControlKey,		FOLLBY_TOKEN },
   70: { "crypto",		T_Crypto,		FOLLBY_TOKEN },
   71: { "keys",		T_Keys,			FOLLBY_STRING },
   72: { "keysdir",		T_Keysdir,		FOLLBY_STRING },
   73: { "ntpsigndsocket",	T_NtpSignDsocket,	FOLLBY_STRING },
   74: { "requestkey",		T_Requestkey,		FOLLBY_TOKEN },
   75: { "revoke",		T_Revoke,		FOLLBY_TOKEN },
   76: { "trustedkey",		T_Trustedkey,		FOLLBY_TOKEN },
   77: /* IPv4/IPv6 protocol override flag */
   78: { "-4",			T_Ipv4_flag,		FOLLBY_TOKEN },
   79: { "-6",			T_Ipv6_flag,		FOLLBY_TOKEN },
   80: /* option */
   81: { "autokey",		T_Autokey,		FOLLBY_TOKEN },
   82: { "bias",		T_Bias,			FOLLBY_TOKEN },
   83: { "burst",		T_Burst,		FOLLBY_TOKEN },
   84: { "iburst",		T_Iburst,		FOLLBY_TOKEN },
   85: { "key",		T_Key,			FOLLBY_TOKEN },
   86: { "maxpoll",		T_Maxpoll,		FOLLBY_TOKEN },
   87: { "minpoll",		T_Minpoll,		FOLLBY_TOKEN },
   88: { "mode",		T_Mode,			FOLLBY_TOKEN },
   89: { "noselect",		T_Noselect,		FOLLBY_TOKEN },
   90: { "preempt",		T_Preempt,		FOLLBY_TOKEN },
   91: { "true",		T_True,			FOLLBY_TOKEN },
   92: { "prefer",		T_Prefer,		FOLLBY_TOKEN },
   93: { "ttl",		T_Ttl,			FOLLBY_TOKEN },
   94: { "version",		T_Version,		FOLLBY_TOKEN },
   95: { "xleave",		T_Xleave,		FOLLBY_TOKEN },
   96: /* crypto_command */
   97: { "host",		T_Host,			FOLLBY_STRING },
   98: { "ident",		T_Ident,		FOLLBY_STRING },
   99: { "pw",			T_Pw,			FOLLBY_STRING },
  100: { "randfile",		T_Randfile,		FOLLBY_STRING },
  101: { "sign",		T_Sign,			FOLLBY_STRING },
  102: { "digest",		T_Digest,		FOLLBY_STRING },
  103: /*** MONITORING COMMANDS ***/
  104: /* stat */
  105: { "clockstats",		T_Clockstats,		FOLLBY_TOKEN },
  106: { "cryptostats",	T_Cryptostats,		FOLLBY_TOKEN },
  107: { "loopstats",		T_Loopstats,		FOLLBY_TOKEN },
  108: { "peerstats",		T_Peerstats,		FOLLBY_TOKEN },
  109: { "rawstats",		T_Rawstats,		FOLLBY_TOKEN },
  110: { "sysstats", 		T_Sysstats,		FOLLBY_TOKEN },
  111: { "protostats",		T_Protostats,		FOLLBY_TOKEN },
  112: { "timingstats",	T_Timingstats,		FOLLBY_TOKEN },
  113: /* filegen_option */
  114: { "file",		T_File,			FOLLBY_STRING },
  115: { "link",		T_Link,			FOLLBY_TOKEN },
  116: { "nolink",		T_Nolink,		FOLLBY_TOKEN },
  117: { "type",		T_Type,			FOLLBY_TOKEN },
  118: /* filegen_type */
  119: { "age",		T_Age,			FOLLBY_TOKEN },
  120: { "day",		T_Day,			FOLLBY_TOKEN },
  121: { "month",		T_Month,		FOLLBY_TOKEN },
  122: { "none",		T_None,			FOLLBY_TOKEN },
  123: { "pid",		T_Pid,			FOLLBY_TOKEN },
  124: { "week",		T_Week,			FOLLBY_TOKEN },
  125: { "year",		T_Year,			FOLLBY_TOKEN },
  126: /*** ORPHAN MODE COMMANDS ***/
  127: /* tos_option */
  128: { "minclock",		T_Minclock,		FOLLBY_TOKEN },
  129: { "maxclock",		T_Maxclock,		FOLLBY_TOKEN },
  130: { "minsane",		T_Minsane,		FOLLBY_TOKEN },
  131: { "floor",		T_Floor,		FOLLBY_TOKEN },
  132: { "ceiling",		T_Ceiling,		FOLLBY_TOKEN },
  133: { "cohort",		T_Cohort,		FOLLBY_TOKEN },
  134: { "mindist",		T_Mindist,		FOLLBY_TOKEN },
  135: { "maxdist",		T_Maxdist,		FOLLBY_TOKEN },
  136: { "beacon",		T_Beacon,		FOLLBY_TOKEN },
  137: { "orphan",		T_Orphan,		FOLLBY_TOKEN },
  138: /* access_control_flag */
  139: { "default",		T_Default,		FOLLBY_TOKEN },
  140: { "flake",		T_Flake,		FOLLBY_TOKEN },
  141: { "ignore",		T_Ignore,		FOLLBY_TOKEN },
  142: { "limited",		T_Limited,		FOLLBY_TOKEN },
  143: { "mssntp",		T_Mssntp,		FOLLBY_TOKEN },
  144: { "kod",		T_Kod,			FOLLBY_TOKEN },
  145: { "lowpriotrap",	T_Lowpriotrap,		FOLLBY_TOKEN },
  146: { "mask",		T_Mask,			FOLLBY_TOKEN },
  147: { "nomodify",		T_Nomodify,		FOLLBY_TOKEN },
  148: { "nopeer",		T_Nopeer,		FOLLBY_TOKEN },
  149: { "noquery",		T_Noquery,		FOLLBY_TOKEN },
  150: { "noserve",		T_Noserve,		FOLLBY_TOKEN },
  151: { "notrap",		T_Notrap,		FOLLBY_TOKEN },
  152: { "notrust",		T_Notrust,		FOLLBY_TOKEN },
  153: { "ntpport",		T_Ntpport,		FOLLBY_TOKEN },
  154: /* discard_option */
  155: { "average",		T_Average,		FOLLBY_TOKEN },
  156: { "minimum",		T_Minimum,		FOLLBY_TOKEN },
  157: { "monitor",		T_Monitor,		FOLLBY_TOKEN },
  158: /* fudge_factor */
  159: { "flag1",		T_Flag1,		FOLLBY_TOKEN },
  160: { "flag2",		T_Flag2,		FOLLBY_TOKEN },
  161: { "flag3",		T_Flag3,		FOLLBY_TOKEN },
  162: { "flag4",		T_Flag4,		FOLLBY_TOKEN },
  163: { "refid",		T_Refid,		FOLLBY_STRING },
  164: { "stratum",		T_Stratum,		FOLLBY_TOKEN },
  165: { "time1",		T_Time1,		FOLLBY_TOKEN },
  166: { "time2",		T_Time2,		FOLLBY_TOKEN },
  167: /* system_option */
  168: { "auth",		T_Auth,			FOLLBY_TOKEN },
  169: { "bclient",		T_Bclient,		FOLLBY_TOKEN },
  170: { "calibrate",		T_Calibrate,		FOLLBY_TOKEN },
  171: { "kernel",		T_Kernel,		FOLLBY_TOKEN },
  172: { "ntp",		T_Ntp,			FOLLBY_TOKEN },
  173: { "stats",		T_Stats,		FOLLBY_TOKEN },
  174: /* tinker_option */
  175: { "step",		T_Step,			FOLLBY_TOKEN },
  176: { "panic",		T_Panic,		FOLLBY_TOKEN },
  177: { "dispersion",		T_Dispersion,		FOLLBY_TOKEN },
  178: { "stepout",		T_Stepout,		FOLLBY_TOKEN },
  179: { "allan",		T_Allan,		FOLLBY_TOKEN },
  180: { "huffpuff",		T_Huffpuff,		FOLLBY_TOKEN },
  181: { "freq",		T_Freq,			FOLLBY_TOKEN },
  182: /* miscellaneous_command */
  183: { "port",		T_Port,			FOLLBY_TOKEN },
  184: { "interface",		T_Interface,		FOLLBY_TOKEN },
  185: { "qos",		T_Qos,			FOLLBY_TOKEN },
  186: { "saveconfigdir",	T_Saveconfigdir,	FOLLBY_STRING },
  187: /* interface_command (ignore and interface already defined) */
  188: { "nic",		T_Nic,			FOLLBY_TOKEN },
  189: { "all",		T_All,			FOLLBY_TOKEN },
  190: { "ipv4",		T_Ipv4,			FOLLBY_TOKEN },
  191: { "ipv6",		T_Ipv6,			FOLLBY_TOKEN },
  192: { "wildcard",		T_Wildcard,		FOLLBY_TOKEN },
  193: { "listen",		T_Listen,		FOLLBY_TOKEN },
  194: { "drop",		T_Drop,			FOLLBY_TOKEN },
  195: /* simulator commands */
  196: { "simulate",		T_Simulate,		FOLLBY_TOKEN },
  197: { "simulation_duration",T_Sim_Duration,		FOLLBY_TOKEN },
  198: { "beep_delay",		T_Beep_Delay,		FOLLBY_TOKEN },
  199: { "duration",		T_Duration,		FOLLBY_TOKEN },
  200: { "server_offset",	T_Server_Offset,	FOLLBY_TOKEN },
  201: { "freq_offset",	T_Freq_Offset,		FOLLBY_TOKEN },
  202: { "wander",		T_Wander,		FOLLBY_TOKEN },
  203: { "jitter",		T_Jitter,		FOLLBY_TOKEN },
  204: { "prop_delay",		T_Prop_Delay,		FOLLBY_TOKEN },
  205: { "proc_delay",		T_Proc_Delay,		FOLLBY_TOKEN },
  206: };
  207: 
  208: 
  209: typedef struct big_scan_state_tag {
  210: 	char	ch;		/* Character this state matches on */
  211: 	char	followedby;	/* Forces next token(s) to T_String */
  212: 	u_short	finishes_token;	/* nonzero ID if last keyword char */
  213: 	u_short	match_next_s;	/* next state to check matching ch */
  214: 	u_short	other_next_s;	/* next state to check if not ch */
  215: } big_scan_state;
  216: 
  217: /*
  218:  * Note: to increase MAXSTATES beyond 2048, be aware it is currently
  219:  * crammed into 11 bits in scan_state form.  Raising to 4096 would be
  220:  * relatively easy by storing the followedby value in a separate
  221:  * array with one entry per token, and shrinking the char value to
  222:  * 7 bits to free a bit for accepting/non-accepting.  More than 4096
  223:  * states will require expanding scan_state beyond 32 bits each.
  224:  */
  225: #define MAXSTATES 2048
  226: 
  227: const char *	current_keyword;/* for error reporting */
  228: big_scan_state	sst[MAXSTATES];	/* scanner FSM state entries */
  229: int		sst_highwater;	/* next entry index to consider */
  230: char *		symb[1024];	/* map token ID to symbolic name */
  231: 
  232: /* for libntp */
  233: const char *	progname = "keyword-gen";
  234: volatile int	debug = 1;
  235: 
  236: int		main			(int, char **);
  237: static void	generate_preamble	(void);
  238: static void	generate_fsm		(void);
  239: static void	generate_token_text	(void);
  240: static int	create_keyword_scanner	(void);
  241: static int	create_scan_states	(char *, int, follby, int);
  242: int		compare_key_tok_id	(QSORTP, QSORTP);
  243: int		compare_key_tok_text	(QSORTP, QSORTP);
  244: void		populate_symb		(char *);
  245: const char *	symbname		(int);
  246: 
  247: 
  248: int main(int argc, char **argv)
  249: {
  250: 	if (argc < 2) {
  251: 		fprintf(stderr, "Usage:\n%s t_header.h\n", argv[0]);
  252: 		exit(1);
  253: 	}
  254: 	populate_symb(argv[1]);
  255: 
  256: 	generate_preamble();
  257: 	generate_token_text();
  258: 	generate_fsm();
  259: 
  260: 	return 0;
  261: }
  262: 
  263: 
  264: static void
  265: generate_preamble(void)
  266: {
  267: 	time_t now;
  268: 	char timestamp[128];
  269: 	char preamble[] =
  270: "/*\n"
  271: " * ntp_keyword.h\n"
  272: " * \n"
  273: " * NOTE: edit this file with caution, it is generated by keyword-gen.c\n"
  274: " *\t Generated %s UTC	  diff_ignore_line\n"
  275: " *\n"
  276: " */\n"
  277: "#include \"ntp_scanner.h\"\n"
  278: "#include \"ntp_parser.h\"\n"
  279: "\n";
  280: 
  281: 	time(&now);
  282: 	if (!strftime(timestamp, sizeof(timestamp),
  283: 		      "%Y-%m-%d %H:%M:%S", gmtime(&now)))
  284: 		timestamp[0] = '\0';
  285: 
  286: 	printf(preamble, timestamp);
  287: }
  288: 
  289: 
  290: static void
  291: generate_fsm(void)
  292: {
  293: 	char token_id_comment[128];
  294: 	int initial_state;
  295: 	int i;
  296: 	int token;
  297: 
  298: 	/* 
  299: 	 * Sort ntp_keywords in alphabetical keyword order.  This is
  300: 	 * not necessary, but minimizes nonfunctional changes in the
  301: 	 * generated finite state machine when keywords are modified.
  302: 	 */
  303: 	qsort(ntp_keywords, COUNTOF(ntp_keywords),
  304: 	      sizeof(ntp_keywords[0]), compare_key_tok_text);
  305: 
  306: 	/*
  307: 	 * To save space, reserve the state array entry matching each 
  308: 	 * token number for its terminal state, so the token identifier
  309: 	 * does not need to be stored in each state, but can be
  310: 	 * recovered trivially.  To mark the entry reserved,
  311: 	 * finishes_token is nonzero.
  312: 	 */
  313: 
  314: 	for (i = 0; i < COUNTOF(ntp_keywords); i++) {
  315: 		token = ntp_keywords[i].token;
  316: 		if (1 > token || token >= COUNTOF(sst)) {
  317: 			fprintf(stderr,
  318: 				"keyword-gen sst[%u] too small "
  319: 				"for keyword '%s' id %d\n",
  320: 				COUNTOF(sst),
  321: 				ntp_keywords[i].key,
  322: 				token);
  323: 			exit(4);
  324: 		}
  325: 		sst[token].finishes_token = token;
  326: 	}
  327: 
  328: 	initial_state = create_keyword_scanner();
  329: 
  330: 	fprintf(stderr,
  331: 		"%d keywords consumed %d states of %d max.\n",
  332: 		(int)COUNTOF(ntp_keywords),
  333: 		sst_highwater - 1,
  334: 		(int)COUNTOF(sst) - 1);
  335: 
  336: 	printf("#define SCANNER_INIT_S %d\n\n", initial_state);
  337: 
  338: 	printf("const scan_state sst[%d] = {\n"
  339: 	       "/*SS_T( ch,\tf-by, match, other ),\t\t\t\t */\n"
  340: 	       "  0,\t\t\t\t      /* %5d %-17s */\n",
  341: 	       sst_highwater,
  342: 	       0, "");
  343: 
  344: 	for (i = 1; i < sst_highwater; i++) {
  345: 
  346: 		/* verify fields will fit */
  347: 		if (sst[i].followedby & ~0x3) {
  348: 			fprintf(stderr,
  349: 				"keyword-gen internal error "
  350: 				"sst[%d].followedby %d too big\n",
  351: 				i, sst[i].followedby);
  352: 			exit(7);
  353: 		}
  354: 
  355: 		if (sst_highwater <= sst[i].match_next_s
  356: 		    || sst[i].match_next_s & ~0x7ff) {
  357: 			fprintf(stderr,
  358: 				"keyword-gen internal error "
  359: 				"sst[%d].match_next_s %d too big\n",
  360: 				i, sst[i].match_next_s);
  361: 			exit(8);
  362: 		}
  363: 
  364: 		if (sst_highwater <= sst[i].other_next_s
  365: 		    || sst[i].other_next_s & ~0x7ff) {
  366: 			fprintf(stderr,
  367: 				"keyword-gen internal error "
  368: 				"sst[%d].other_next_s %d too big\n",
  369: 				i, sst[i].other_next_s);
  370: 			exit(9);
  371: 		}
  372: 
  373: 		if (!sst[i].finishes_token)
  374: 			snprintf(token_id_comment,
  375: 				 sizeof(token_id_comment), "%5d %-17s",
  376: 				 i, (initial_state == i) 
  377: 					? "initial state" 
  378: 					: "");
  379: 		else {
  380: 			snprintf(token_id_comment, 
  381: 				 sizeof(token_id_comment), "%5d %-17s",
  382: 				 i, symbname(sst[i].finishes_token));
  383: 			if (i != sst[i].finishes_token) {
  384: 				fprintf(stderr,
  385: 					"keyword-gen internal error "
  386: 					"entry %d finishes token %d\n",
  387: 					i, sst[i].finishes_token);
  388: 				exit(5);
  389: 			}
  390: 		}
  391: 
  392: 		printf("  S_ST( '%c',\t%d,    %5u, %5u )%s /* %s */\n",
  393: 		       sst[i].ch,
  394: 		       sst[i].followedby,
  395: 		       sst[i].match_next_s,
  396: 		       sst[i].other_next_s,
  397: 		       (i + 1 < sst_highwater)
  398: 			   ? ","
  399: 			   : " ",
  400: 		       token_id_comment);
  401: 	}
  402: 
  403: 	printf("};\n\n");
  404: }
  405: 
  406: 
  407: /* Define a function to create the states of the scanner. This function
  408:  * is used by the create_keyword_scanner function below.
  409:  *
  410:  * This function takes a suffix of a keyword, the token to be returned on
  411:  * recognizing the complete keyword, and any pre-existing state that exists
  412:  * for some other keyword that has the same prefix as the current one.
  413:  */
  414: static int
  415: create_scan_states(
  416: 	char *	text, 
  417: 	int	token, 
  418: 	follby	followedby,
  419: 	int	prev_state
  420: 	)
  421: {
  422: 	int my_state;
  423: 	int return_state;
  424: 	int prev_char_s;
  425: 	int curr_char_s;
  426: 
  427: 	return_state = prev_state;
  428: 	curr_char_s = prev_state;
  429: 	prev_char_s = 0;
  430: 
  431: 	/* Find the correct position to insert the state. 
  432: 	 * All states should be in alphabetical order
  433: 	 */
  434: 	while (curr_char_s && (text[0] < sst[curr_char_s].ch)) {
  435: 		prev_char_s = curr_char_s;
  436: 		curr_char_s = sst[curr_char_s].other_next_s;
  437: 	}
  438: 
  439: 	/* 
  440: 	 * Check if a previously seen keyword has the same prefix as
  441: 	 * the current keyword.  If so, simply use the state for that
  442: 	 * keyword as my_state, otherwise, allocate a new state.
  443: 	 */
  444: 	if (curr_char_s && (text[0] == sst[curr_char_s].ch)) {
  445: 		my_state = curr_char_s;
  446: 		if ('\0' == text[1]) {
  447: 			fprintf(stderr,
  448: 				"Duplicate entries for keyword '%s' in"
  449: 				" keyword_gen.c ntp_keywords[].\n",
  450: 				current_keyword);
  451: 			exit(2);
  452: 		}
  453: 	} else {
  454: 		do
  455: 			my_state = sst_highwater++;
  456: 		while (my_state < COUNTOF(sst)
  457: 		       && sst[my_state].finishes_token);
  458: 		if (my_state >= COUNTOF(sst)) {
  459: 			fprintf(stderr,
  460: 				"fatal, keyword scanner state array "
  461: 				"sst[%d] is too small, modify\n"
  462: 				"keyword-gen.c to increase.\n",
  463: 				(int)COUNTOF(sst));
  464: 			exit(3);
  465: 		}
  466: 		/* Store the next character of the keyword */
  467: 		sst[my_state].ch = text[0]; 
  468: 		sst[my_state].other_next_s = curr_char_s;
  469: 		sst[my_state].followedby = FOLLBY_NON_ACCEPTING;
  470: 
  471: 		if (prev_char_s)
  472: 			sst[prev_char_s].other_next_s = my_state;
  473: 		else
  474: 			return_state = my_state;
  475: 	}
  476: 
  477: 	/* Check if the next character is '\0'.
  478: 	 * If yes, we are done with the recognition and this is an accepting
  479: 	 * state.
  480: 	 * If not, we need to continue scanning
  481: 	 */
  482: 	if ('\0' == text[1]) {
  483: 		sst[my_state].finishes_token = (u_short)token;
  484: 		sst[my_state].followedby = (char)followedby;
  485: 
  486: 		if (sst[token].finishes_token != (u_short)token) {
  487: 			fprintf(stderr,
  488: 				"fatal, sst[%d] not reserved for %s.\n",
  489: 				token, symbname(token));
  490: 			exit(6);
  491: 		}
  492: 		/* relocate so token id is sst[] index */
  493: 		if (my_state != token) {
  494: 			sst[token] = sst[my_state];
  495: 			memset(&sst[my_state], 0,
  496: 			       sizeof(sst[my_state]));
  497: 			do
  498: 				sst_highwater--;
  499: 			while (sst[sst_highwater].finishes_token);
  500: 			my_state = token;
  501: 			if (prev_char_s)
  502: 				sst[prev_char_s].other_next_s = my_state;
  503: 			else
  504: 				return_state = my_state;
  505: 		}
  506: 	} else
  507: 		sst[my_state].match_next_s = 
  508: 		    create_scan_states(
  509: 			&text[1],
  510: 			token,
  511: 			followedby,
  512: 			sst[my_state].match_next_s);
  513: 
  514: 	return return_state;
  515: }
  516: 
  517: 
  518: /* Define a function that takes a list of (keyword, token) values and
  519:  * creates a keywords scanner out of it.
  520:  */
  521: 
  522: static int
  523: create_keyword_scanner(void)
  524: {
  525: 	int scanner;
  526: 	int i;
  527: 
  528: 	sst_highwater = 1;	/* index 0 invalid, unused */
  529: 	scanner = 0;
  530: 
  531: 	for (i = 0; i < COUNTOF(ntp_keywords); i++) {
  532: 		current_keyword = ntp_keywords[i].key;
  533: 		scanner =
  534: 		    create_scan_states(
  535: 			ntp_keywords[i].key, 
  536: 			ntp_keywords[i].token, 
  537: 			ntp_keywords[i].followedby,
  538: 			scanner);
  539: 	}
  540: 
  541: 	return scanner;
  542: }
  543: 
  544: 
  545: static void
  546: generate_token_text(void)
  547: {
  548: 	int lowest_id;
  549: 	int highest_id;
  550: 	int id_count;
  551: 	int id;
  552: 	int i;
  553: 
  554: 	/* sort ntp_keywords in token ID order */
  555: 	qsort(ntp_keywords, COUNTOF(ntp_keywords),
  556: 	      sizeof(ntp_keywords[0]), compare_key_tok_id);
  557: 
  558: 	lowest_id = ntp_keywords[0].token;
  559: 	highest_id = ntp_keywords[COUNTOF(ntp_keywords) - 1].token;
  560: 	id_count = highest_id - lowest_id + 1;
  561: 
  562: 	printf("#define LOWEST_KEYWORD_ID %d\n\n", lowest_id);
  563: 
  564: 	printf("const char * const keyword_text[%d] = {", id_count);
  565: 
  566: 	id = lowest_id;
  567: 	i = 0;
  568: 	while (i < COUNTOF(ntp_keywords)) {
  569: 		while (id < ntp_keywords[i].token) {
  570: 			printf(",\n\t/* %-5d %5d %20s */\tNULL",
  571: 			       id - lowest_id, id, symbname(id));
  572: 			id++;
  573: 		}
  574: 		if (i > 0)
  575: 			printf(",");
  576: 		printf("\n\t/* %-5d %5d %20s */\t\"%s\"",
  577: 		       id - lowest_id, id, symbname(id), 
  578: 		       ntp_keywords[i].key);
  579: 		i++;
  580: 		id++;
  581: 	}
  582: 
  583: 	printf("\n};\n\n");
  584: }
  585: 
  586: 	
  587: int
  588: compare_key_tok_id(
  589: 	QSORTP a1,
  590: 	QSORTP a2
  591: 	)
  592: {
  593: 	const struct key_tok *p1 = (const void *)a1;
  594: 	const struct key_tok *p2 = (const void *)a2;
  595: 
  596: 	if (p1->token == p2->token)
  597: 		return 0;
  598: 
  599: 	if (p1->token < p2->token)
  600: 		return -1;
  601: 	else
  602: 		return 1;
  603: }
  604: 
  605: 
  606: int
  607: compare_key_tok_text(
  608: 	QSORTP a1,
  609: 	QSORTP a2
  610: 	)
  611: {
  612: 	const struct key_tok *p1 = (const void *)a1;
  613: 	const struct key_tok *p2 = (const void *)a2;
  614: 
  615: 	return strcmp(p1->key, p2->key);
  616: }
  617: 
  618: 
  619: /*
  620:  * populate_symb() - populate symb[] lookup array with symbolic token
  621:  *		     names such that symb[T_Age] == "T_Age", etc.
  622:  */
  623: void
  624: populate_symb(
  625: 	char *header_file
  626: 	)
  627: {
  628: 	FILE *	yh;
  629: 	char	line[128];
  630: 	char	name[128];
  631: 	int	token;
  632: 
  633: 	yh = fopen(header_file, "r");
  634: 	if (NULL == yh) {
  635: 		perror("unable to open yacc/bison header file");
  636: 		exit(4);
  637: 	}
  638: 
  639: 	while (NULL != fgets(line, sizeof(line), yh))
  640: 		if (2 == sscanf(line, "#define %s %d", name, &token)
  641: 		    && 'T' == name[0] && '_' == name[1] && token >= 0
  642: 		    && token < COUNTOF(symb))
  643: 
  644: 			symb[token] = estrdup(name);
  645: 
  646: 	fclose(yh);
  647: }
  648: 
  649: 
  650: const char *
  651: symbname(
  652: 	int token
  653: 	)
  654: {
  655: 	char *name;
  656: 
  657: 	if (token >= 0 && token < COUNTOF(symb) && symb[token] != NULL)
  658: 		return symb[token];
  659: 
  660: 	LIB_GETBUF(name);
  661: 	snprintf(name, LIB_BUFLENGTH, "%d", token);
  662: 	return name;
  663: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>