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
parse_versions(const char * fileName)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
arch(void)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
comment(void)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
arch_name(void)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
set_list(void)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
set(void)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
set_parents(void)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
accept_token(char * expected)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
skip_to(char * target)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 *
skipb(char * p)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 *
skipover(char * p)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 *
currtok(void)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 *
nexttok(void)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 *
tokenize(char * line)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
valid_version(const char * vers_name)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
valid_arch(const char * arch_name)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
add_valid_version(char * vers_name)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
add_valid_arch(char * arch_name)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
init_tables(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