xref: /titanic_51/usr/src/cmd/abi/spectrans/spec2map/versions.c (revision 753d2d2e8e7fd0c9bcf736d9bf2f2faf4d6234cc)
1*753d2d2eSraf /*
2*753d2d2eSraf  * CDDL HEADER START
3*753d2d2eSraf  *
4*753d2d2eSraf  * The contents of this file are subject to the terms of the
5*753d2d2eSraf  * Common Development and Distribution License, Version 1.0 only
6*753d2d2eSraf  * (the "License").  You may not use this file except in compliance
7*753d2d2eSraf  * with the License.
8*753d2d2eSraf  *
9*753d2d2eSraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*753d2d2eSraf  * or http://www.opensolaris.org/os/licensing.
11*753d2d2eSraf  * See the License for the specific language governing permissions
12*753d2d2eSraf  * and limitations under the License.
13*753d2d2eSraf  *
14*753d2d2eSraf  * When distributing Covered Code, include this CDDL HEADER in each
15*753d2d2eSraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*753d2d2eSraf  * If applicable, add the following below this CDDL HEADER, with the
17*753d2d2eSraf  * fields enclosed by brackets "[]" replaced with your own identifying
18*753d2d2eSraf  * information: Portions Copyright [yyyy] [name of copyright owner]
19*753d2d2eSraf  *
20*753d2d2eSraf  * CDDL HEADER END
21*753d2d2eSraf  */
22*753d2d2eSraf /*
23*753d2d2eSraf  * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
24*753d2d2eSraf  * All rights reserved.
25*753d2d2eSraf  */
26*753d2d2eSraf #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*753d2d2eSraf 
28*753d2d2eSraf #include <stdio.h>
29*753d2d2eSraf #include <string.h>
30*753d2d2eSraf #include <ctype.h>
31*753d2d2eSraf #include "xlator.h"
32*753d2d2eSraf #include "util.h"
33*753d2d2eSraf #include "bucket.h"
34*753d2d2eSraf #include "errlog.h"
35*753d2d2eSraf 
36*753d2d2eSraf /* Types: */
37*753d2d2eSraf #define	TRUE	1
38*753d2d2eSraf #define	FALSE	0
39*753d2d2eSraf #define	MAXLINE 1024
40*753d2d2eSraf 
41*753d2d2eSraf 
42*753d2d2eSraf typedef enum {
43*753d2d2eSraf 	PARENT, UNCLE
44*753d2d2eSraf } RELATION;
45*753d2d2eSraf 
46*753d2d2eSraf 
47*753d2d2eSraf /* Statics: */
48*753d2d2eSraf /* The parser is a dfa, driven by the following: */
49*753d2d2eSraf static FILE *Fp;
50*753d2d2eSraf static const char *Filename;
51*753d2d2eSraf static char Previous[MAXLINE];
52*753d2d2eSraf static char LeftMostChild[MAXLINE];
53*753d2d2eSraf static int Selected = FALSE;
54*753d2d2eSraf static int Line;
55*753d2d2eSraf static int Errors;
56*753d2d2eSraf 
57*753d2d2eSraf 
58*753d2d2eSraf /* The grammar is: */
59*753d2d2eSraf static int arch(void);
60*753d2d2eSraf static int comment(void);
61*753d2d2eSraf static int arch_name(void);
62*753d2d2eSraf static int set_list(void);
63*753d2d2eSraf static int set(void);
64*753d2d2eSraf 
65*753d2d2eSraf /* The supporting code is: */
66*753d2d2eSraf static int accept_token(char *);
67*753d2d2eSraf static void skip_to(char *);
68*753d2d2eSraf 
69*753d2d2eSraf /* And the tokenizer is: */
70*753d2d2eSraf static char *tokenize(char *);
71*753d2d2eSraf static char *currtok(void);
72*753d2d2eSraf static char *nexttok(void);
73*753d2d2eSraf static char *skipb(char *);
74*753d2d2eSraf static char *skipover(char *);
75*753d2d2eSraf static char *CurrTok = NULL;
76*753d2d2eSraf 
77*753d2d2eSraf static int set_parents(void);
78*753d2d2eSraf 
79*753d2d2eSraf static table_t *Vers;
80*753d2d2eSraf static table_t *Varch;
81*753d2d2eSraf 
82*753d2d2eSraf static void init_tables(void);
83*753d2d2eSraf 
84*753d2d2eSraf static void add_valid_arch(char *);
85*753d2d2eSraf static void add_valid_version(char *vers_name);
86*753d2d2eSraf 
87*753d2d2eSraf 
88*753d2d2eSraf #define	in_specials(c)  ((c) == '{' || (c) == '}' || (c) == '+' || \
89*753d2d2eSraf 	(c) == '-' || (c) == ';' || (c) == ':' || (c) == ',' || \
90*753d2d2eSraf 	(c) == '[' || (c) == ']')
91*753d2d2eSraf 
92*753d2d2eSraf #define	eq(s1, s2)	(strcmp((s1), (s2)) == 0)
93*753d2d2eSraf 
94*753d2d2eSraf 
95*753d2d2eSraf /*
96*753d2d2eSraf  * parse_versions -- parse the file whose name is passed, return
97*753d2d2eSraf  *	the number of (fatal) errors encountered. Currently only
98*753d2d2eSraf  *	knows about reading set files and writing vers files.
99*753d2d2eSraf  */
100*753d2d2eSraf int
101*753d2d2eSraf parse_versions(const char *fileName)
102*753d2d2eSraf {
103*753d2d2eSraf 
104*753d2d2eSraf 	/* Prime the set-file parser dfa: */
105*753d2d2eSraf 	assert(fileName != NULL, "passed null filename to parse_versions");
106*753d2d2eSraf 	errlog(BEGIN, "parse_versions(%s) {", fileName);
107*753d2d2eSraf 
108*753d2d2eSraf 
109*753d2d2eSraf 	if ((Fp = fopen(fileName, "r")) == NULL) {
110*753d2d2eSraf 		(void) fprintf(stderr, "Cannot open version file \"%s\"\n",
111*753d2d2eSraf 		    fileName);
112*753d2d2eSraf 		errlog(END, "} /* parse_versions */");
113*753d2d2eSraf 		return (1);
114*753d2d2eSraf 	}
115*753d2d2eSraf 	Filename = fileName;
116*753d2d2eSraf 	Line = 0;
117*753d2d2eSraf 
118*753d2d2eSraf 	errlog(VERBOSE, "reading set file %s looking for architecture %s",
119*753d2d2eSraf 	    Filename, TargetArchStr);
120*753d2d2eSraf 
121*753d2d2eSraf 	/* Run the dfa. */
122*753d2d2eSraf 	while (arch())
123*753d2d2eSraf 		continue;
124*753d2d2eSraf 
125*753d2d2eSraf 	(void) fclose(Fp);
126*753d2d2eSraf 	/* print_all_buckets(); */
127*753d2d2eSraf 	errlog(END, "} /* parse_versions */");
128*753d2d2eSraf 	return (Errors);
129*753d2d2eSraf }
130*753d2d2eSraf 
131*753d2d2eSraf 
132*753d2d2eSraf /*
133*753d2d2eSraf  * The parser. This implements the grammar:
134*753d2d2eSraf  *    setfile::= (arch())+ <EOF>
135*753d2d2eSraf  *             | <EOF>
136*753d2d2eSraf  *    arch::= <ARCHITECTURE> "{" (set_list())* "}"
137*753d2d2eSraf  *    set_list::= (set())+ ";"
138*753d2d2eSraf  *    set::= <IDENTIFIER> ["[" "WEAK" "]"] ":" "{" (ancestors) "}" ";"
139*753d2d2eSraf  *    ancestors::= <IDENTIFIER> | <ancestors> "," <IDENTIFIER>
140*753d2d2eSraf  *    where <ARCHITECTURE> and <IDENTIFIER> are tokens.
141*753d2d2eSraf  */
142*753d2d2eSraf static int
143*753d2d2eSraf arch(void)
144*753d2d2eSraf {
145*753d2d2eSraf 	int olderrors;
146*753d2d2eSraf 
147*753d2d2eSraf 	errlog(BEGIN, "arch() {");
148*753d2d2eSraf 	if (comment()) {
149*753d2d2eSraf 		errlog(END, "} /* arch */");
150*753d2d2eSraf 		return (TRUE);
151*753d2d2eSraf 	}
152*753d2d2eSraf 	if (arch_name() == FALSE) {
153*753d2d2eSraf 		errlog(END, "} /* arch */");
154*753d2d2eSraf 		return (FALSE);
155*753d2d2eSraf 	}
156*753d2d2eSraf 	if (accept_token("{") == FALSE) {
157*753d2d2eSraf 		errlog(END, "} /* arch */");
158*753d2d2eSraf 		return (FALSE);
159*753d2d2eSraf 	}
160*753d2d2eSraf 
161*753d2d2eSraf 	olderrors = Errors;
162*753d2d2eSraf 	if (set_list() == FALSE) {
163*753d2d2eSraf 		if (olderrors != Errors) {
164*753d2d2eSraf 			errlog(END, "} /* arch */");
165*753d2d2eSraf 			return (FALSE);
166*753d2d2eSraf 		}
167*753d2d2eSraf 	}
168*753d2d2eSraf 
169*753d2d2eSraf 	errlog(END, "} /* arch */");
170*753d2d2eSraf 	return (TRUE);
171*753d2d2eSraf }
172*753d2d2eSraf 
173*753d2d2eSraf static int
174*753d2d2eSraf comment(void)
175*753d2d2eSraf {
176*753d2d2eSraf 	char *token = currtok();
177*753d2d2eSraf 
178*753d2d2eSraf 	if (token == NULL || *token != '#') {
179*753d2d2eSraf 		return (FALSE);
180*753d2d2eSraf 	} else {
181*753d2d2eSraf 		/* Swallow token. */
182*753d2d2eSraf 		token =  nexttok();
183*753d2d2eSraf 		return (TRUE);
184*753d2d2eSraf 	}
185*753d2d2eSraf }
186*753d2d2eSraf 
187*753d2d2eSraf static int
188*753d2d2eSraf arch_name(void)
189*753d2d2eSraf {
190*753d2d2eSraf 	char *token = currtok();
191*753d2d2eSraf 
192*753d2d2eSraf 	errlog(BEGIN, "arch_name() {");
193*753d2d2eSraf 	errlog(VERBOSE, "token = '%s';",
194*753d2d2eSraf 		token ? token : "<NULL>");
195*753d2d2eSraf 
196*753d2d2eSraf 	if (token == NULL) {
197*753d2d2eSraf 		errlog(END, "} /* arch_name */");
198*753d2d2eSraf 		return (FALSE);
199*753d2d2eSraf 
200*753d2d2eSraf 	} else if (in_specials(*token)) {
201*753d2d2eSraf 		/* It's not an architecture */
202*753d2d2eSraf 		Selected = FALSE;
203*753d2d2eSraf 
204*753d2d2eSraf 		/* Report a syntax error: TBD */
205*753d2d2eSraf 		errlog(INPUT | ERROR, "found special char. %c "
206*753d2d2eSraf 		    "while looking for an architecture name",
207*753d2d2eSraf 		    *token);
208*753d2d2eSraf 
209*753d2d2eSraf 		skip_to("}");	/* The follower set for arch_name. */
210*753d2d2eSraf 		errlog(END, "} /* arch name */");
211*753d2d2eSraf 
212*753d2d2eSraf 		Errors++;
213*753d2d2eSraf 		return (FALSE);
214*753d2d2eSraf 
215*753d2d2eSraf 	} else if (!eq(token, TargetArchStr)) {
216*753d2d2eSraf 		/* It's an architecture ... */
217*753d2d2eSraf 		errlog(VERBOSE, "Begin unselected architecture: %s", token);
218*753d2d2eSraf 		add_valid_arch(token);
219*753d2d2eSraf 		(void) nexttok();
220*753d2d2eSraf 
221*753d2d2eSraf 		/* ... but the the wrong one. */
222*753d2d2eSraf 		Selected = FALSE;
223*753d2d2eSraf 		errlog(END, "} /* arch name */");
224*753d2d2eSraf 		return (TRUE);
225*753d2d2eSraf 	} else {
226*753d2d2eSraf 		/* Found the right architecture. */
227*753d2d2eSraf 		errlog(VERBOSE, "Begin selected architecture: %s", token);
228*753d2d2eSraf 		add_valid_arch(token);
229*753d2d2eSraf 		(void) nexttok();
230*753d2d2eSraf 		Selected = TRUE;
231*753d2d2eSraf 		errlog(END, "} /* arch name */");
232*753d2d2eSraf 		return (TRUE);
233*753d2d2eSraf 	}
234*753d2d2eSraf }
235*753d2d2eSraf 
236*753d2d2eSraf 
237*753d2d2eSraf static int
238*753d2d2eSraf set_list(void)
239*753d2d2eSraf {
240*753d2d2eSraf 	int olderrors;
241*753d2d2eSraf 	char *token = currtok();
242*753d2d2eSraf 
243*753d2d2eSraf 	errlog(BEGIN, "set_list() {");
244*753d2d2eSraf 	errlog(VERBOSE, "token = '%s'",
245*753d2d2eSraf 	    (token) ? token : "<NULL>");
246*753d2d2eSraf 	if (set() == FALSE) {
247*753d2d2eSraf 		errlog(END, "} /* set_list */");
248*753d2d2eSraf 		return (FALSE);
249*753d2d2eSraf 	}
250*753d2d2eSraf 
251*753d2d2eSraf 	olderrors = Errors;
252*753d2d2eSraf 	while (set()) {
253*753d2d2eSraf 		continue;
254*753d2d2eSraf 	}
255*753d2d2eSraf 	if (olderrors != Errors) {
256*753d2d2eSraf 		errlog(END, "} /* set_list */");
257*753d2d2eSraf 		return (FALSE);
258*753d2d2eSraf 	}
259*753d2d2eSraf 
260*753d2d2eSraf 	errlog(END, "} /* set_list */");
261*753d2d2eSraf 	return (TRUE);
262*753d2d2eSraf }
263*753d2d2eSraf 
264*753d2d2eSraf 
265*753d2d2eSraf static int
266*753d2d2eSraf set(void)
267*753d2d2eSraf {
268*753d2d2eSraf 	char *token = currtok();
269*753d2d2eSraf 	int has_parent = 0;
270*753d2d2eSraf 
271*753d2d2eSraf 	errlog(BEGIN, "set() {");
272*753d2d2eSraf 	errlog(VERBOSE, "token = '%s'",
273*753d2d2eSraf 	    (token) ? token : "<NULL>");
274*753d2d2eSraf 
275*753d2d2eSraf 	if (in_specials(*token)) {
276*753d2d2eSraf 		errlog(INPUT|ERROR, "unexpected token \"%s\" found. "
277*753d2d2eSraf 		    "Version name expected", token);
278*753d2d2eSraf 		Errors++;
279*753d2d2eSraf 		errlog(END, "} /* set */");
280*753d2d2eSraf 		return (FALSE);
281*753d2d2eSraf 	}
282*753d2d2eSraf 
283*753d2d2eSraf 	errlog(VERBOSE, "Begin Version: %s", token);
284*753d2d2eSraf 	*Previous = '\0';
285*753d2d2eSraf 	if (Selected) {
286*753d2d2eSraf 		if (add_parent(token, Previous, 0) == FALSE) {
287*753d2d2eSraf 			errlog(INPUT | ERROR, "unable to add a parent version "
288*753d2d2eSraf 			    "from the set file");
289*753d2d2eSraf 			Errors++;
290*753d2d2eSraf 			errlog(END, "} /* set */");
291*753d2d2eSraf 			return (FALSE);
292*753d2d2eSraf 		}
293*753d2d2eSraf 	}
294*753d2d2eSraf 
295*753d2d2eSraf 	add_valid_version(token);
296*753d2d2eSraf 	(void) strncpy(LeftMostChild, token, MAXLINE);
297*753d2d2eSraf 	LeftMostChild[MAXLINE-1] = '\0';
298*753d2d2eSraf 	(void) strncpy(Previous, token, MAXLINE);
299*753d2d2eSraf 	Previous[MAXLINE-1] = '\0';
300*753d2d2eSraf 
301*753d2d2eSraf 	token = nexttok();
302*753d2d2eSraf 
303*753d2d2eSraf 	switch (*token) {
304*753d2d2eSraf 		case ':':
305*753d2d2eSraf 			errlog(VERBOSE, "token ':' found");
306*753d2d2eSraf 			(void) accept_token(":");
307*753d2d2eSraf 			if (set_parents() == FALSE) {
308*753d2d2eSraf 				errlog(END, "} /* set */");
309*753d2d2eSraf 				return (FALSE);
310*753d2d2eSraf 			}
311*753d2d2eSraf 			if (accept_token(";") == FALSE) {
312*753d2d2eSraf 				errlog(END, "} /* set */");
313*753d2d2eSraf 				return (FALSE);
314*753d2d2eSraf 			}
315*753d2d2eSraf 			errlog(VERBOSE, "End Version");
316*753d2d2eSraf 			break;
317*753d2d2eSraf 
318*753d2d2eSraf 		case ';':
319*753d2d2eSraf 			errlog(VERBOSE, "token ';' found");
320*753d2d2eSraf 			(void) accept_token(";");
321*753d2d2eSraf 			errlog(VERBOSE, "End version ':'");
322*753d2d2eSraf 			break;
323*753d2d2eSraf 
324*753d2d2eSraf 		case '[':
325*753d2d2eSraf 			(void) accept_token("[");
326*753d2d2eSraf 			if (accept_token("WEAK") == FALSE) {
327*753d2d2eSraf 				errlog(END, "} /* set */");
328*753d2d2eSraf 				return (FALSE);
329*753d2d2eSraf 			}
330*753d2d2eSraf 			if (accept_token("]") == FALSE) {
331*753d2d2eSraf 				errlog(END, "} /* set */");
332*753d2d2eSraf 				return (FALSE);
333*753d2d2eSraf 			}
334*753d2d2eSraf 			token = currtok();
335*753d2d2eSraf 			if (eq(token, ":")) {
336*753d2d2eSraf 				(void) accept_token(":");
337*753d2d2eSraf 				has_parent = 1;
338*753d2d2eSraf 			} else if (eq(token, ";")) {
339*753d2d2eSraf 				(void) accept_token(";");
340*753d2d2eSraf 			} else {
341*753d2d2eSraf 				errlog(ERROR|INPUT,
342*753d2d2eSraf 				    "Unexpected token \"%s\" found. ':'"
343*753d2d2eSraf 				    "or ';' expected.", token);
344*753d2d2eSraf 				Errors++;
345*753d2d2eSraf 				errlog(END, "} /* set */");
346*753d2d2eSraf 				return (FALSE);
347*753d2d2eSraf 			}
348*753d2d2eSraf 			errlog(VERBOSE, "WEAK version detected\n");
349*753d2d2eSraf 			if (Selected)
350*753d2d2eSraf 				set_weak(LeftMostChild, TRUE);
351*753d2d2eSraf 
352*753d2d2eSraf 			if (has_parent) {
353*753d2d2eSraf 				if (set_parents() == FALSE) {
354*753d2d2eSraf 					errlog(END, "} /* set */");
355*753d2d2eSraf 					return (FALSE);
356*753d2d2eSraf 				}
357*753d2d2eSraf 				if (accept_token(";") == FALSE) {
358*753d2d2eSraf 					errlog(END, "} /* set */");
359*753d2d2eSraf 					return (FALSE);
360*753d2d2eSraf 				}
361*753d2d2eSraf 			}
362*753d2d2eSraf 			errlog(VERBOSE, "End Version");
363*753d2d2eSraf 			break;
364*753d2d2eSraf 		default:
365*753d2d2eSraf 			/* CSTYLED */
366*753d2d2eSraf 			errlog(ERROR|INPUT,
367*753d2d2eSraf 			    "Unexpected token \"%s\" found. ';' expected.",
368*753d2d2eSraf 			    token);
369*753d2d2eSraf 			Errors++;
370*753d2d2eSraf 			errlog(END, "} /* set */");
371*753d2d2eSraf 			return (FALSE);
372*753d2d2eSraf 	}
373*753d2d2eSraf 
374*753d2d2eSraf 	token = currtok();
375*753d2d2eSraf 	if (eq(token, "}")) {
376*753d2d2eSraf 		(void) accept_token("}");
377*753d2d2eSraf 		errlog(VERBOSE, "End architecture");
378*753d2d2eSraf 		errlog(END, "} /* set */");
379*753d2d2eSraf 		return (FALSE);
380*753d2d2eSraf 	}
381*753d2d2eSraf 
382*753d2d2eSraf 	errlog(END, "} /* set */");
383*753d2d2eSraf 	return (TRUE);
384*753d2d2eSraf }
385*753d2d2eSraf 
386*753d2d2eSraf static int
387*753d2d2eSraf set_parents(void)
388*753d2d2eSraf {
389*753d2d2eSraf 	char *token = currtok();
390*753d2d2eSraf 	int uncle;
391*753d2d2eSraf 
392*753d2d2eSraf 	errlog(BEGIN, "set_parents() {");
393*753d2d2eSraf 	errlog(VERBOSE, "token = '%s'",
394*753d2d2eSraf 	    (token) ? token : "<NULL>");
395*753d2d2eSraf 
396*753d2d2eSraf 	if (accept_token("{") == FALSE) {
397*753d2d2eSraf 		errlog(INPUT|ERROR, "set_parents(): Unexpected token: %s\n",
398*753d2d2eSraf 		    token);
399*753d2d2eSraf 		Errors++;
400*753d2d2eSraf 		errlog(END, "} /* set_parents */");
401*753d2d2eSraf 		return (FALSE);
402*753d2d2eSraf 	}
403*753d2d2eSraf 
404*753d2d2eSraf 	token = currtok();
405*753d2d2eSraf 
406*753d2d2eSraf 	if (in_specials(*token)) {
407*753d2d2eSraf 		errlog(INPUT|ERROR, "set_parents(): Unexpected token: %c "
408*753d2d2eSraf 		    "found. Version token expected", *token);
409*753d2d2eSraf 		Errors++;
410*753d2d2eSraf 		errlog(END, "} /* set_parents */");
411*753d2d2eSraf 		return (FALSE);
412*753d2d2eSraf 	}
413*753d2d2eSraf 
414*753d2d2eSraf 	uncle = 0;
415*753d2d2eSraf 	while (token && *token != '}') {
416*753d2d2eSraf 		errlog(VERBOSE, "Begin parent list: %s\n", token);
417*753d2d2eSraf 		if (Selected) {
418*753d2d2eSraf 			if (uncle)
419*753d2d2eSraf 				(void) add_uncle(token, LeftMostChild, 0);
420*753d2d2eSraf 			else
421*753d2d2eSraf 				(void) add_parent(token, Previous, 0);
422*753d2d2eSraf 		}
423*753d2d2eSraf 		(void) strncpy(Previous, token, MAXLINE);
424*753d2d2eSraf 		add_valid_version(token);
425*753d2d2eSraf 		Previous[MAXLINE-1] = '\0';
426*753d2d2eSraf 
427*753d2d2eSraf 		token = nexttok();
428*753d2d2eSraf 
429*753d2d2eSraf 		if (*token == ',') {
430*753d2d2eSraf 			token = nexttok();
431*753d2d2eSraf 			/* following identifiers are all uncles */
432*753d2d2eSraf 			uncle = 1;
433*753d2d2eSraf 			continue;
434*753d2d2eSraf 		}
435*753d2d2eSraf 
436*753d2d2eSraf 		if (*token == '}') {
437*753d2d2eSraf 			if (accept_token("}") == FALSE) {
438*753d2d2eSraf 				errlog(END, "} /* set_parents */");
439*753d2d2eSraf 				return (FALSE);
440*753d2d2eSraf 			}
441*753d2d2eSraf 			errlog(VERBOSE, "set_parent: End of parent list");
442*753d2d2eSraf 			errlog(END, "} /* set_parents */");
443*753d2d2eSraf 			return (TRUE);
444*753d2d2eSraf 		}
445*753d2d2eSraf 
446*753d2d2eSraf 		errlog(INPUT|ERROR,
447*753d2d2eSraf 		    "set_parents(): Unexpected token \"%s\" "
448*753d2d2eSraf 		    "found. ',' or '}' were expected", token);
449*753d2d2eSraf 		Errors++;
450*753d2d2eSraf 		errlog(END, "} /* set_parents */");
451*753d2d2eSraf 		return (FALSE);
452*753d2d2eSraf 	}
453*753d2d2eSraf 	errlog(END, "} /* set_parents */");
454*753d2d2eSraf 	return (TRUE);
455*753d2d2eSraf }
456*753d2d2eSraf 
457*753d2d2eSraf 
458*753d2d2eSraf /*
459*753d2d2eSraf  * parser support routines
460*753d2d2eSraf  */
461*753d2d2eSraf 
462*753d2d2eSraf 
463*753d2d2eSraf /*
464*753d2d2eSraf  * accept_token -- get a specified token or complain loudly.
465*753d2d2eSraf  */
466*753d2d2eSraf static int
467*753d2d2eSraf accept_token(char *expected)
468*753d2d2eSraf {
469*753d2d2eSraf 	char *token = currtok();
470*753d2d2eSraf 
471*753d2d2eSraf 	assert(expected != NULL, "null token passed to accept_token");
472*753d2d2eSraf 	errlog(OTHER | TRACING, "accept_token, at %s expecting %s",
473*753d2d2eSraf 		(token) ? token : "<NULL>", expected);
474*753d2d2eSraf 
475*753d2d2eSraf 	if (token == NULL) {
476*753d2d2eSraf 		/* We're at EOF */
477*753d2d2eSraf 		return (TRUE);
478*753d2d2eSraf 	}
479*753d2d2eSraf 	if (eq(token, expected)) {
480*753d2d2eSraf 		(void) nexttok();
481*753d2d2eSraf 		return (TRUE);
482*753d2d2eSraf 	} else {
483*753d2d2eSraf 		errlog(INPUT | ERROR,
484*753d2d2eSraf 			"accept_token, found %s while looking for %s",
485*753d2d2eSraf 			(token) ? token : "<NULL>", expected);
486*753d2d2eSraf 		++Errors;
487*753d2d2eSraf 		return (FALSE);
488*753d2d2eSraf 	}
489*753d2d2eSraf }
490*753d2d2eSraf 
491*753d2d2eSraf static void
492*753d2d2eSraf skip_to(char *target)
493*753d2d2eSraf {
494*753d2d2eSraf 	char *token = currtok();
495*753d2d2eSraf 
496*753d2d2eSraf 	assert(target != NULL, "null target passed to skip_to");
497*753d2d2eSraf 	while (token && !eq(token, target)) {
498*753d2d2eSraf 		errlog(VERBOSE, "skipping over %s",
499*753d2d2eSraf 			(token) ? token : "<NULL>");
500*753d2d2eSraf 		token = nexttok();
501*753d2d2eSraf 	}
502*753d2d2eSraf }
503*753d2d2eSraf 
504*753d2d2eSraf 
505*753d2d2eSraf /*
506*753d2d2eSraf  * tokenizer -- below the grammar lives this, like a troll
507*753d2d2eSraf  *	under a bridge.
508*753d2d2eSraf  */
509*753d2d2eSraf 
510*753d2d2eSraf 
511*753d2d2eSraf /*
512*753d2d2eSraf  * skipb -- skip over blanks (whitespace, actually), stopping
513*753d2d2eSraf  *      on first non-blank.
514*753d2d2eSraf  */
515*753d2d2eSraf static char *
516*753d2d2eSraf skipb(char *p)
517*753d2d2eSraf {
518*753d2d2eSraf 
519*753d2d2eSraf 	while (*p && isspace(*p))
520*753d2d2eSraf 		++p;
521*753d2d2eSraf 	return (p);
522*753d2d2eSraf }
523*753d2d2eSraf 
524*753d2d2eSraf /*
525*753d2d2eSraf  * skipover -- skip over non-separators (alnum, . and _, actually),
526*753d2d2eSraf  *      stopping on first separator.
527*753d2d2eSraf  */
528*753d2d2eSraf static char *
529*753d2d2eSraf skipover(char *p)
530*753d2d2eSraf {
531*753d2d2eSraf 
532*753d2d2eSraf 	while (*p && (isalnum(*p) || (*p == '_' || *p == '.')))
533*753d2d2eSraf 		++p;
534*753d2d2eSraf 	return (p);
535*753d2d2eSraf }
536*753d2d2eSraf 
537*753d2d2eSraf 
538*753d2d2eSraf /*
539*753d2d2eSraf  * currtok/nexttok -- get the current/next token
540*753d2d2eSraf  */
541*753d2d2eSraf static char *
542*753d2d2eSraf currtok(void)
543*753d2d2eSraf {
544*753d2d2eSraf 
545*753d2d2eSraf 	if (CurrTok == NULL) {
546*753d2d2eSraf 		(void) nexttok();
547*753d2d2eSraf 	}
548*753d2d2eSraf 	return (CurrTok);
549*753d2d2eSraf }
550*753d2d2eSraf 
551*753d2d2eSraf static char *
552*753d2d2eSraf nexttok(void)
553*753d2d2eSraf {
554*753d2d2eSraf 	static char line[MAXLINE];
555*753d2d2eSraf 	char *p;
556*753d2d2eSraf 
557*753d2d2eSraf 	if ((p = tokenize(NULL)) == NULL) {
558*753d2d2eSraf 		/* We're at an end of line. */
559*753d2d2eSraf 		do {
560*753d2d2eSraf 			if (fgets(line, sizeof (line), Fp) == NULL) {
561*753d2d2eSraf 				/* Which is also end of file. */
562*753d2d2eSraf 				CurrTok = NULL;
563*753d2d2eSraf 				return (NULL);
564*753d2d2eSraf 			}
565*753d2d2eSraf 			++Line;
566*753d2d2eSraf 			seterrline(Line, Filename, "", line);
567*753d2d2eSraf 		} while ((p = tokenize(line)) == NULL);
568*753d2d2eSraf 	}
569*753d2d2eSraf 	CurrTok = p;
570*753d2d2eSraf 	return (p);
571*753d2d2eSraf }
572*753d2d2eSraf 
573*753d2d2eSraf 
574*753d2d2eSraf 
575*753d2d2eSraf /*
576*753d2d2eSraf  * tokenize -- a version of the standard strtok with specific behavior.
577*753d2d2eSraf  */
578*753d2d2eSraf static char *
579*753d2d2eSraf tokenize(char *line)
580*753d2d2eSraf {
581*753d2d2eSraf 	static char *p = NULL;
582*753d2d2eSraf 	static char saved = 0;
583*753d2d2eSraf 	char *q;
584*753d2d2eSraf 
585*753d2d2eSraf 	if (line == NULL && p == NULL) {
586*753d2d2eSraf 		/* It's the very first time */
587*753d2d2eSraf 		return (NULL);
588*753d2d2eSraf 	} else if (line != NULL) {
589*753d2d2eSraf 		/* Initialize with a new line */
590*753d2d2eSraf 		q = skipb(line);
591*753d2d2eSraf 	} else {
592*753d2d2eSraf 		/* Restore previous line. */
593*753d2d2eSraf 		*p = saved;
594*753d2d2eSraf 		q = skipb(p);
595*753d2d2eSraf 	}
596*753d2d2eSraf 	/* q is at the beginning of a token or at EOL, p is irrelevant. */
597*753d2d2eSraf 
598*753d2d2eSraf 	if (*q == '\0') {
599*753d2d2eSraf 		/* It's at EOL. */
600*753d2d2eSraf 		p = q;
601*753d2d2eSraf 	} else if (in_specials(*q)) {
602*753d2d2eSraf 		/* We have a special-character token. */
603*753d2d2eSraf 		p = q + 1;
604*753d2d2eSraf 	} else if (*q == '#') {
605*753d2d2eSraf 		/* The whole rest of the line is a comment token. */
606*753d2d2eSraf 		return (NULL);
607*753d2d2eSraf 	} else {
608*753d2d2eSraf 		/* We have a word token. */
609*753d2d2eSraf 		p = skipover(q);
610*753d2d2eSraf 	}
611*753d2d2eSraf 	saved = *p;
612*753d2d2eSraf 	*p = '\0';
613*753d2d2eSraf 
614*753d2d2eSraf 	if (p == q) {
615*753d2d2eSraf 		/* End of line */
616*753d2d2eSraf 		return (NULL);
617*753d2d2eSraf 	} else {
618*753d2d2eSraf 		return (q);
619*753d2d2eSraf 	}
620*753d2d2eSraf }
621*753d2d2eSraf 
622*753d2d2eSraf 
623*753d2d2eSraf /*
624*753d2d2eSraf  * valid_version -- see if a version string was mentioned in the set file.
625*753d2d2eSraf  */
626*753d2d2eSraf int
627*753d2d2eSraf valid_version(const char *vers_name)
628*753d2d2eSraf {
629*753d2d2eSraf 
630*753d2d2eSraf 	if (Vers == NULL) {
631*753d2d2eSraf 		init_tables();
632*753d2d2eSraf 	}
633*753d2d2eSraf 	return (in_stringtable(Vers, vers_name));
634*753d2d2eSraf }
635*753d2d2eSraf 
636*753d2d2eSraf /*
637*753d2d2eSraf  * valid_arch -- see if the arch was mentioned in the set file.
638*753d2d2eSraf  */
639*753d2d2eSraf int
640*753d2d2eSraf valid_arch(const char *arch_name)
641*753d2d2eSraf {
642*753d2d2eSraf 
643*753d2d2eSraf 	if (Vers == NULL) {
644*753d2d2eSraf 		init_tables();
645*753d2d2eSraf 	}
646*753d2d2eSraf 	return (in_stringtable(Varch, arch_name));
647*753d2d2eSraf }
648*753d2d2eSraf 
649*753d2d2eSraf /*
650*753d2d2eSraf  * add_valid_version and _arch -- add a name to the table.
651*753d2d2eSraf  */
652*753d2d2eSraf static void
653*753d2d2eSraf add_valid_version(char *vers_name)
654*753d2d2eSraf {
655*753d2d2eSraf 	errlog(BEGIN, "add_valid_version(\"%s\") {", vers_name);
656*753d2d2eSraf 	if (Vers == NULL) {
657*753d2d2eSraf 		init_tables();
658*753d2d2eSraf 	}
659*753d2d2eSraf 	Vers = add_to_stringtable(Vers, vers_name);
660*753d2d2eSraf 	errlog(END, "}");
661*753d2d2eSraf }
662*753d2d2eSraf 
663*753d2d2eSraf static void
664*753d2d2eSraf add_valid_arch(char *arch_name)
665*753d2d2eSraf {
666*753d2d2eSraf 
667*753d2d2eSraf 	errlog(BEGIN, "add_valid_arch(\"%s\") {", arch_name);
668*753d2d2eSraf 	if (Vers == NULL) {
669*753d2d2eSraf 		init_tables();
670*753d2d2eSraf 	}
671*753d2d2eSraf 	Varch = add_to_stringtable(Varch, arch_name);
672*753d2d2eSraf 	errlog(END, "}");
673*753d2d2eSraf }
674*753d2d2eSraf 
675*753d2d2eSraf /*
676*753d2d2eSraf  * init_tables -- creat them when first used.
677*753d2d2eSraf  */
678*753d2d2eSraf static void
679*753d2d2eSraf init_tables(void)
680*753d2d2eSraf {
681*753d2d2eSraf 	Vers = create_stringtable(TABLE_INITIAL);
682*753d2d2eSraf 	Varch = create_stringtable(TABLE_INITIAL);
683*753d2d2eSraf }
684