scan.l revision 1.12 1 1.1 thorpej %{
2 1.12 lukem /* $NetBSD: scan.l,v 1.12 2009/04/11 12:41:10 lukem Exp $ */
3 1.1 thorpej
4 1.1 thorpej /*
5 1.1 thorpej * Copyright (c) 1992, 1993
6 1.1 thorpej * The Regents of the University of California. All rights reserved.
7 1.1 thorpej *
8 1.1 thorpej * This software was developed by the Computer Systems Engineering group
9 1.1 thorpej * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10 1.1 thorpej * contributed to Berkeley.
11 1.1 thorpej *
12 1.1 thorpej * All advertising materials mentioning features or use of this software
13 1.1 thorpej * must display the following acknowledgement:
14 1.1 thorpej * This product includes software developed by the University of
15 1.1 thorpej * California, Lawrence Berkeley Laboratories.
16 1.1 thorpej *
17 1.1 thorpej * Redistribution and use in source and binary forms, with or without
18 1.1 thorpej * modification, are permitted provided that the following conditions
19 1.1 thorpej * are met:
20 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
21 1.1 thorpej * notice, this list of conditions and the following disclaimer.
22 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
23 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
24 1.1 thorpej * documentation and/or other materials provided with the distribution.
25 1.1 thorpej * 3. Neither the name of the University nor the names of its contributors
26 1.1 thorpej * may be used to endorse or promote products derived from this software
27 1.1 thorpej * without specific prior written permission.
28 1.1 thorpej *
29 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 1.1 thorpej * SUCH DAMAGE.
40 1.1 thorpej *
41 1.1 thorpej * from: @(#)scan.l 8.1 (Berkeley) 6/6/93
42 1.1 thorpej */
43 1.1 thorpej
44 1.1 thorpej #include <sys/param.h>
45 1.1 thorpej #include <errno.h>
46 1.1 thorpej #include <libgen.h>
47 1.1 thorpej #include <stdio.h>
48 1.1 thorpej #include <stdlib.h>
49 1.1 thorpej #include <string.h>
50 1.1 thorpej #include <unistd.h>
51 1.2 martin #include <stddef.h>
52 1.2 martin #include <ctype.h>
53 1.5 christos #include <util.h>
54 1.5 christos #undef ECHO
55 1.1 thorpej #include "defs.h"
56 1.1 thorpej #include "gram.h"
57 1.1 thorpej
58 1.1 thorpej int yyline;
59 1.1 thorpej const char *yyfile;
60 1.1 thorpej const char *lastfile;
61 1.2 martin char curinclpath[PATH_MAX];
62 1.9 cube int ifdefstate = -1;
63 1.9 cube int st;
64 1.9 cube #define IDS_PARENT_DISABLED \
65 1.9 cube ((ifdefstate > 6) && ((((ifdefstate/6)-1) & 1) == 1))
66 1.9 cube #define IDS_MAX_DEPTH 362797056 /* 6^11 */
67 1.9 cube /* States for ifdefstate:
68 1.9 cube
69 1.9 cube 0 -> matched ifdef
70 1.9 cube 1 -> unmatched ifdef
71 1.9 cube 2 -> matched elifdef
72 1.9 cube 3 -> unmatched elifdef
73 1.9 cube 4 -> matched else
74 1.9 cube 5 -> unmatched else
75 1.9 cube
76 1.9 cube Upon "ifdef", add one and multiply by 6.
77 1.9 cube Upon "endif", divide by 6, remove 1.
78 1.9 cube
79 1.9 cube ifdef -> MATCH => continue
80 1.9 cube MISMATCH => set to 1
81 1.9 cube elifdef -> if (!1) -> MISMATCH
82 1.9 cube MATCH => set to 2
83 1.9 cube MISMATCH => if (2 || 3) set to 3, else set to 1
84 1.9 cube else -> if (1) -> MATCH
85 1.9 cube MATCH => set to 4
86 1.9 cube MISMATCH => set to 5
87 1.9 cube
88 1.9 cube in each case, if parent & 1 == 1, MISMATCH
89 1.9 cube */
90 1.9 cube
91 1.1 thorpej /*
92 1.1 thorpej * Data for returning to previous files from include files.
93 1.1 thorpej */
94 1.1 thorpej struct incl {
95 1.1 thorpej struct incl *in_prev; /* previous includes in effect, if any */
96 1.1 thorpej YY_BUFFER_STATE in_buf; /* previous lex state */
97 1.1 thorpej const char *in_fname; /* previous file name */
98 1.1 thorpej int in_lineno; /* previous line number */
99 1.1 thorpej int in_ateof; /* token to insert at EOF */
100 1.1 thorpej int in_interesting; /* previous value for "interesting" */
101 1.9 cube int in_ifdefstate; /* conditional level */
102 1.1 thorpej };
103 1.1 thorpej static struct incl *incl;
104 1.1 thorpej static int endinclude(void);
105 1.2 martin static int getincludepath(void);
106 1.9 cube static int getcurifdef(void);
107 1.1 thorpej
108 1.1 thorpej #define yywrap() 1
109 1.1 thorpej
110 1.1 thorpej %}
111 1.1 thorpej
112 1.1 thorpej PATH [A-Za-z_0-9]*[./][-A-Za-z_0-9./]*
113 1.2 martin QCHARS ([^"\n]|\\\")+
114 1.1 thorpej WORD [A-Za-z_][-A-Za-z_0-9]*
115 1.2 martin FILENAME ({PATH}|\"{QCHARS}\")
116 1.8 cube RESTOFLINE [ \t]*(#[^\n]*)?\n
117 1.1 thorpej
118 1.9 cube %x IGNORED
119 1.9 cube
120 1.1 thorpej %%
121 1.1 thorpej /* Local variables for yylex() */
122 1.1 thorpej int tok;
123 1.1 thorpej
124 1.1 thorpej and return AND;
125 1.1 thorpej at return AT;
126 1.1 thorpej attach return ATTACH;
127 1.1 thorpej block return BLOCK;
128 1.1 thorpej build return BUILD;
129 1.1 thorpej char return CHAR;
130 1.1 thorpej compile-with return COMPILE_WITH;
131 1.1 thorpej config return CONFIG;
132 1.1 thorpej deffs return DEFFS;
133 1.1 thorpej define return DEFINE;
134 1.1 thorpej defflag return DEFFLAG;
135 1.1 thorpej defopt return DEFOPT;
136 1.1 thorpej defparam return DEFPARAM;
137 1.1 thorpej defpseudo return DEFPSEUDO;
138 1.10 drochner defpseudodev return DEFPSEUDODEV;
139 1.1 thorpej devclass return DEVCLASS;
140 1.1 thorpej device return DEVICE;
141 1.1 thorpej device-major return DEVICE_MAJOR;
142 1.1 thorpej dumps return DUMPS;
143 1.1 thorpej file return XFILE;
144 1.1 thorpej file-system return FILE_SYSTEM;
145 1.1 thorpej flags return FLAGS;
146 1.1 thorpej ident return IDENT;
147 1.1 thorpej machine return XMACHINE;
148 1.1 thorpej major return MAJOR;
149 1.1 thorpej makeoptions return MAKEOPTIONS;
150 1.1 thorpej maxpartitions return MAXPARTITIONS;
151 1.1 thorpej maxusers return MAXUSERS;
152 1.1 thorpej minor return MINOR;
153 1.1 thorpej needs-count return NEEDS_COUNT;
154 1.1 thorpej needs-flag return NEEDS_FLAG;
155 1.1 thorpej no return NO;
156 1.1 thorpej object return XOBJECT;
157 1.4 cube obsolete return OBSOLETE;
158 1.1 thorpej on return ON;
159 1.1 thorpej options return OPTIONS;
160 1.1 thorpej prefix return PREFIX;
161 1.1 thorpej pseudo-device return PSEUDO_DEVICE;
162 1.1 thorpej root return ROOT;
163 1.1 thorpej source return SOURCE;
164 1.1 thorpej type return TYPE;
165 1.3 cube version return VERSION;
166 1.1 thorpej with return WITH;
167 1.1 thorpej
168 1.1 thorpej \+= return PLUSEQ;
169 1.6 cube := return COLONEQ;
170 1.1 thorpej
171 1.9 cube <*>ifdef[ \t]+{WORD}{RESTOFLINE} {
172 1.9 cube ifdefstate = (ifdefstate + 1) * 6;
173 1.9 cube if (ifdefstate >= IDS_MAX_DEPTH) {
174 1.9 cube yyerror("too many levels of conditional");
175 1.9 cube }
176 1.9 cube if (!IDS_PARENT_DISABLED && getcurifdef()) {
177 1.9 cube BEGIN(INITIAL);
178 1.9 cube } else {
179 1.9 cube ifdefstate++;
180 1.9 cube BEGIN(IGNORED);
181 1.9 cube }
182 1.9 cube yyline++;
183 1.9 cube }
184 1.9 cube
185 1.9 cube <*>ifndef[ \t]+{WORD}{RESTOFLINE} {
186 1.9 cube ifdefstate = (ifdefstate + 1) * 6;
187 1.9 cube if (ifdefstate >= IDS_MAX_DEPTH) {
188 1.9 cube yyerror("too many levels of conditional");
189 1.9 cube }
190 1.9 cube if (!IDS_PARENT_DISABLED && !getcurifdef()) {
191 1.9 cube BEGIN(INITIAL);
192 1.9 cube } else {
193 1.9 cube ifdefstate++;
194 1.9 cube BEGIN(IGNORED);
195 1.9 cube }
196 1.9 cube yyline++;
197 1.9 cube }
198 1.9 cube
199 1.9 cube
200 1.9 cube <*>elifdef[ \t]+{WORD}{RESTOFLINE} {
201 1.9 cube st = ifdefstate % 6;
202 1.9 cube if (ifdefstate < 0 || st > 3) {
203 1.9 cube yyerror("mismatched elifdef");
204 1.9 cube }
205 1.9 cube if (IDS_PARENT_DISABLED ||
206 1.9 cube st != 1 || !getcurifdef()) {
207 1.9 cube if (st == 2 || st == 3) {
208 1.9 cube ifdefstate += 3 - st;
209 1.9 cube } else {
210 1.9 cube ifdefstate += 1 - st;
211 1.9 cube }
212 1.9 cube BEGIN(IGNORED);
213 1.9 cube } else {
214 1.9 cube ifdefstate++;
215 1.9 cube BEGIN(INITIAL);
216 1.9 cube }
217 1.9 cube yyline++;
218 1.9 cube }
219 1.9 cube
220 1.9 cube <*>elifndef[ \t]+{WORD}{RESTOFLINE} {
221 1.9 cube st = ifdefstate % 6;
222 1.9 cube if (ifdefstate < 0 || st > 3) {
223 1.9 cube yyerror("mismatched elifndef");
224 1.9 cube }
225 1.9 cube if (IDS_PARENT_DISABLED ||
226 1.9 cube st != 1 || getcurifdef()) {
227 1.9 cube if (st == 2 || st == 3) {
228 1.9 cube ifdefstate += 3 - st;
229 1.9 cube } else {
230 1.9 cube ifdefstate += 1 - st;
231 1.9 cube }
232 1.9 cube BEGIN(IGNORED);
233 1.9 cube } else {
234 1.9 cube ifdefstate++;
235 1.9 cube BEGIN(INITIAL);
236 1.9 cube }
237 1.9 cube yyline++;
238 1.9 cube }
239 1.9 cube
240 1.9 cube <*>else{RESTOFLINE} {
241 1.9 cube st = ifdefstate % 6;
242 1.9 cube if (ifdefstate < 0 || st > 3) {
243 1.9 cube yyerror("mismatched else");
244 1.9 cube }
245 1.9 cube if (!IDS_PARENT_DISABLED && (st == 1)) {
246 1.9 cube ifdefstate += 3;
247 1.9 cube BEGIN(INITIAL);
248 1.9 cube } else {
249 1.9 cube ifdefstate += 5 - st;
250 1.9 cube BEGIN(IGNORED);
251 1.9 cube }
252 1.9 cube yyline++;
253 1.9 cube }
254 1.9 cube
255 1.9 cube <*>endif{RESTOFLINE} {
256 1.9 cube if (ifdefstate < 0) {
257 1.9 cube yyerror("mismatched endif");
258 1.9 cube }
259 1.9 cube if (!IDS_PARENT_DISABLED) {
260 1.9 cube BEGIN(INITIAL);
261 1.9 cube }
262 1.9 cube ifdefstate = (ifdefstate/6) - 1;
263 1.9 cube yyline++;
264 1.9 cube }
265 1.9 cube
266 1.9 cube <IGNORED>\n {
267 1.9 cube yyline++;
268 1.9 cube }
269 1.9 cube
270 1.9 cube <IGNORED>. /* ignore */
271 1.9 cube
272 1.8 cube include[ \t]+{FILENAME}{RESTOFLINE} {
273 1.8 cube yyline++;
274 1.2 martin if (getincludepath()) {
275 1.2 martin include(curinclpath, 0, 0, 1);
276 1.2 martin } else {
277 1.2 martin yyerror("bad include path-name");
278 1.2 martin }
279 1.2 martin }
280 1.2 martin
281 1.8 cube cinclude[ \t]+{FILENAME}{RESTOFLINE} {
282 1.8 cube yyline++;
283 1.2 martin if (getincludepath()) {
284 1.2 martin include(curinclpath, 0, 1, 1);
285 1.2 martin } else {
286 1.2 martin yyerror("bad cinclude path-name");
287 1.2 martin }
288 1.2 martin }
289 1.2 martin
290 1.8 cube package[ \t]+{FILENAME}{RESTOFLINE} {
291 1.8 cube yyline++;
292 1.2 martin if (!oktopackage) {
293 1.2 martin yyerror("package not allowed here");
294 1.2 martin } else if (getincludepath()) {
295 1.2 martin package(curinclpath);
296 1.2 martin } else {
297 1.2 martin yyerror("bad package path-name");
298 1.2 martin }
299 1.2 martin }
300 1.2 martin
301 1.1 thorpej {PATH} {
302 1.1 thorpej yylval.str = intern(yytext);
303 1.1 thorpej return PATHNAME;
304 1.1 thorpej }
305 1.1 thorpej
306 1.1 thorpej {WORD} {
307 1.1 thorpej yylval.str = intern(yytext);
308 1.1 thorpej return WORD;
309 1.1 thorpej }
310 1.1 thorpej
311 1.1 thorpej \"\" {
312 1.1 thorpej yylval.str = intern("");
313 1.5 christos return EMPTYSTRING;
314 1.1 thorpej }
315 1.2 martin
316 1.2 martin \"{QCHARS} {
317 1.1 thorpej tok = input(); /* eat closing quote */
318 1.1 thorpej if (tok != '"') {
319 1.7 christos cfgerror("closing quote missing\n");
320 1.1 thorpej unput(tok);
321 1.1 thorpej }
322 1.1 thorpej yylval.str = intern(yytext + 1);
323 1.1 thorpej return QSTRING;
324 1.1 thorpej }
325 1.1 thorpej 0[0-7]* {
326 1.1 thorpej yylval.num.fmt = 8;
327 1.1 thorpej yylval.num.val = strtoll(yytext, NULL, 8);
328 1.1 thorpej return NUMBER;
329 1.1 thorpej }
330 1.1 thorpej 0[xX][0-9a-fA-F]+ {
331 1.1 thorpej yylval.num.fmt = 16;
332 1.1 thorpej yylval.num.val = strtoull(yytext + 2, NULL, 16);
333 1.1 thorpej return NUMBER;
334 1.1 thorpej }
335 1.1 thorpej [1-9][0-9]* {
336 1.1 thorpej yylval.num.fmt = 10;
337 1.1 thorpej yylval.num.val = strtoll(yytext, NULL, 10);
338 1.1 thorpej return NUMBER;
339 1.1 thorpej }
340 1.1 thorpej \n[ \t] {
341 1.1 thorpej /*
342 1.1 thorpej * Note: newline followed by whitespace is always a
343 1.1 thorpej * continuation of the previous line, so do NOT
344 1.1 thorpej * return a token in this case.
345 1.1 thorpej */
346 1.1 thorpej yyline++;
347 1.1 thorpej }
348 1.1 thorpej \n {
349 1.1 thorpej yyline++;
350 1.1 thorpej return '\n';
351 1.1 thorpej }
352 1.1 thorpej \00 {
353 1.1 thorpej /* Detect NUL characters in the config file and
354 1.1 thorpej * error out.
355 1.1 thorpej */
356 1.7 christos cfgerror("NUL character detected at line %i\n", yyline);
357 1.1 thorpej }
358 1.1 thorpej #.* { /* ignored (comment) */; }
359 1.1 thorpej [ \t]+ { /* ignored (white space) */; }
360 1.1 thorpej . { return yytext[0]; }
361 1.9 cube <*><<EOF>> {
362 1.9 cube if (ifdefstate > (incl == NULL ? -1 : incl->in_ifdefstate)) {
363 1.9 cube yyerror("reached EOF while looking for endif");
364 1.9 cube }
365 1.1 thorpej if (incl == NULL)
366 1.1 thorpej return YY_NULL;
367 1.1 thorpej tok = endinclude();
368 1.1 thorpej if (tok)
369 1.1 thorpej return tok;
370 1.1 thorpej /* otherwise continue scanning */
371 1.1 thorpej }
372 1.1 thorpej
373 1.1 thorpej %%
374 1.1 thorpej
375 1.1 thorpej int interesting = 1;
376 1.1 thorpej
377 1.1 thorpej static int
378 1.1 thorpej curdir_push(const char *fname)
379 1.1 thorpej {
380 1.1 thorpej struct prefix *pf;
381 1.1 thorpej char *p, *d, *f;
382 1.1 thorpej
383 1.1 thorpej /* Set up the initial "current directory" for include directives. */
384 1.1 thorpej d = dirname(f = estrdup(fname));
385 1.1 thorpej if (*d == '/')
386 1.1 thorpej p = estrdup(d);
387 1.1 thorpej else {
388 1.1 thorpej char *cwd, buf[PATH_MAX];
389 1.1 thorpej
390 1.11 dholland if ((cwd = getcwd(buf, sizeof(buf))) == NULL) {
391 1.11 dholland free(f);
392 1.1 thorpej return (-1);
393 1.11 dholland }
394 1.1 thorpej p = emalloc(strlen(cwd) + strlen(d) + 2);
395 1.1 thorpej sprintf(p, "%s/%s", cwd, d);
396 1.1 thorpej }
397 1.1 thorpej free(f);
398 1.1 thorpej pf = ecalloc(1, sizeof(*pf));
399 1.1 thorpej pf->pf_prefix = p;
400 1.1 thorpej SLIST_INSERT_HEAD(&curdirs, pf, pf_next);
401 1.1 thorpej
402 1.1 thorpej return (0);
403 1.1 thorpej }
404 1.1 thorpej
405 1.1 thorpej static void
406 1.1 thorpej curdir_pop(void)
407 1.1 thorpej {
408 1.1 thorpej struct prefix *pf;
409 1.1 thorpej
410 1.1 thorpej pf = SLIST_FIRST(&curdirs);
411 1.1 thorpej SLIST_REMOVE_HEAD(&curdirs, pf_next);
412 1.1 thorpej if (SLIST_EMPTY(&curdirs))
413 1.1 thorpej panic("curdirs is empty");
414 1.1 thorpej /* LINTED cast away const (pf_prefix is malloc'd for curdirs) */
415 1.12 lukem free((void *)__UNCONST(pf->pf_prefix));
416 1.1 thorpej free(pf);
417 1.1 thorpej }
418 1.1 thorpej
419 1.1 thorpej /*
420 1.1 thorpej * Open the "main" file (conffile).
421 1.1 thorpej */
422 1.1 thorpej int
423 1.1 thorpej firstfile(const char *fname)
424 1.1 thorpej {
425 1.1 thorpej
426 1.1 thorpej #if defined(__NetBSD__)
427 1.1 thorpej if ((yyin = fopen(fname, "rf")) == NULL)
428 1.1 thorpej #else
429 1.1 thorpej if ((yyin = fopen(fname, "r")) == NULL)
430 1.1 thorpej #endif
431 1.1 thorpej return (-1);
432 1.1 thorpej
433 1.1 thorpej if (curdir_push(fname) == -1)
434 1.1 thorpej return (-1);
435 1.1 thorpej
436 1.1 thorpej yyfile = conffile = fname;
437 1.1 thorpej yyline = 1;
438 1.1 thorpej return (0);
439 1.1 thorpej }
440 1.1 thorpej
441 1.1 thorpej /*
442 1.1 thorpej * Add a "package" to the configuration. This is essentially
443 1.1 thorpej * syntactic sugar around the sequence:
444 1.1 thorpej *
445 1.1 thorpej * prefix ../some/directory
446 1.1 thorpej * include "files.package"
447 1.1 thorpej * prefix
448 1.1 thorpej */
449 1.1 thorpej void
450 1.1 thorpej package(const char *fname)
451 1.1 thorpej {
452 1.1 thorpej char *fname1 = estrdup(fname);
453 1.1 thorpej char *fname2 = estrdup(fname);
454 1.1 thorpej char *dir = dirname(fname1);
455 1.1 thorpej char *file = basename(fname2);
456 1.1 thorpej
457 1.1 thorpej /*
458 1.1 thorpej * Push the prefix on to the prefix stack and process the include
459 1.1 thorpej * file. When we reach the end of the include file, inserting
460 1.1 thorpej * the PREFIX token into the input stream will pop the prefix off
461 1.1 thorpej * of the prefix stack.
462 1.1 thorpej */
463 1.1 thorpej prefix_push(dir);
464 1.1 thorpej (void) include(file, PREFIX, 0, 1);
465 1.1 thorpej
466 1.1 thorpej free(fname1);
467 1.1 thorpej free(fname2);
468 1.1 thorpej }
469 1.1 thorpej
470 1.1 thorpej /*
471 1.1 thorpej * Open the named file for inclusion at the current point. Returns 0 on
472 1.1 thorpej * success (file opened and previous state pushed), nonzero on failure
473 1.1 thorpej * (fopen failed, complaint made). The `ateof' parameter controls the
474 1.1 thorpej * token to be inserted at the end of the include file (i.e. ENDFILE).
475 1.1 thorpej * If ateof == 0 then nothing is inserted.
476 1.1 thorpej */
477 1.1 thorpej int
478 1.1 thorpej include(const char *fname, int ateof, int conditional, int direct)
479 1.1 thorpej {
480 1.1 thorpej FILE *fp;
481 1.1 thorpej struct incl *in;
482 1.1 thorpej char *s;
483 1.1 thorpej static int havedirs;
484 1.1 thorpej extern int vflag;
485 1.1 thorpej
486 1.1 thorpej if (havedirs == 0) {
487 1.1 thorpej havedirs = 1;
488 1.1 thorpej setupdirs();
489 1.1 thorpej }
490 1.1 thorpej
491 1.1 thorpej if (fname[0] == '/')
492 1.1 thorpej s = estrdup(fname);
493 1.1 thorpej else if (fname[0] == '.' && fname[1] == '/') {
494 1.1 thorpej struct prefix *pf = SLIST_FIRST(&curdirs);
495 1.1 thorpej s = emalloc(strlen(pf->pf_prefix) + strlen(fname));
496 1.1 thorpej sprintf(s, "%s/%s", pf->pf_prefix, fname + 2);
497 1.1 thorpej } else
498 1.1 thorpej s = sourcepath(fname);
499 1.1 thorpej if ((fp = fopen(s, "r")) == NULL) {
500 1.1 thorpej if (conditional == 0)
501 1.7 christos cfgerror("cannot open %s for reading: %s\n", s,
502 1.1 thorpej strerror(errno));
503 1.1 thorpej else if (vflag)
504 1.7 christos cfgwarn("cannot open conditional include file %s: %s",
505 1.1 thorpej s, strerror(errno));
506 1.1 thorpej free(s);
507 1.1 thorpej return (-1);
508 1.1 thorpej }
509 1.1 thorpej if (curdir_push(s) == -1) {
510 1.7 christos cfgerror("cannot record current working directory for %s\n", s);
511 1.1 thorpej fclose(fp);
512 1.1 thorpej free(s);
513 1.1 thorpej return (-1);
514 1.1 thorpej }
515 1.1 thorpej in = ecalloc(1, sizeof *in);
516 1.1 thorpej in->in_prev = incl;
517 1.1 thorpej in->in_buf = YY_CURRENT_BUFFER;
518 1.1 thorpej in->in_fname = yyfile;
519 1.1 thorpej in->in_lineno = yyline;
520 1.1 thorpej in->in_ateof = ateof;
521 1.1 thorpej in->in_interesting = interesting;
522 1.9 cube in->in_ifdefstate = ifdefstate;
523 1.1 thorpej interesting = direct & interesting;
524 1.1 thorpej if (interesting)
525 1.1 thorpej logconfig_include(fp, fname);
526 1.1 thorpej incl = in;
527 1.1 thorpej yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
528 1.1 thorpej yyfile = intern(s);
529 1.1 thorpej yyline = 1;
530 1.1 thorpej free(s);
531 1.1 thorpej return (0);
532 1.1 thorpej }
533 1.1 thorpej
534 1.1 thorpej /*
535 1.2 martin * Extract the pathname from a include/cinclude/package into curinclpath
536 1.2 martin */
537 1.2 martin static int
538 1.2 martin getincludepath()
539 1.2 martin {
540 1.2 martin const char *p = yytext;
541 1.8 cube ptrdiff_t len;
542 1.8 cube const char *e;
543 1.2 martin
544 1.8 cube while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p))
545 1.2 martin p++;
546 1.8 cube while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p))
547 1.2 martin p++;
548 1.2 martin if (!*p)
549 1.2 martin return 0;
550 1.2 martin if (*p == '"') {
551 1.8 cube p++;
552 1.8 cube e = strchr(p, '"');
553 1.2 martin if (!e) return 0;
554 1.2 martin } else {
555 1.8 cube e = p;
556 1.8 cube while (*e && isascii((unsigned int)*e)
557 1.8 cube && !isspace((unsigned int)*e))
558 1.8 cube e++;
559 1.2 martin }
560 1.2 martin
561 1.8 cube len = e-p;
562 1.12 lukem if (len > (ptrdiff_t)sizeof(curinclpath)-1)
563 1.8 cube len = sizeof(curinclpath)-1;
564 1.8 cube strncpy(curinclpath, p, sizeof(curinclpath));
565 1.8 cube curinclpath[len] = '\0';
566 1.8 cube
567 1.2 martin return 1;
568 1.2 martin }
569 1.2 martin
570 1.2 martin /*
571 1.1 thorpej * Terminate the most recent inclusion.
572 1.1 thorpej */
573 1.1 thorpej static int
574 1.1 thorpej endinclude(void)
575 1.1 thorpej {
576 1.1 thorpej struct incl *in;
577 1.1 thorpej int ateof;
578 1.1 thorpej
579 1.1 thorpej curdir_pop();
580 1.1 thorpej if ((in = incl) == NULL)
581 1.1 thorpej panic("endinclude");
582 1.1 thorpej incl = in->in_prev;
583 1.1 thorpej lastfile = yyfile;
584 1.1 thorpej yy_delete_buffer(YY_CURRENT_BUFFER);
585 1.1 thorpej (void)fclose(yyin);
586 1.1 thorpej yy_switch_to_buffer(in->in_buf);
587 1.1 thorpej yyfile = in->in_fname;
588 1.1 thorpej yyline = in->in_lineno;
589 1.1 thorpej ateof = in->in_ateof;
590 1.1 thorpej interesting = in->in_interesting;
591 1.1 thorpej free(in);
592 1.1 thorpej
593 1.1 thorpej return (ateof);
594 1.1 thorpej }
595 1.1 thorpej
596 1.1 thorpej /*
597 1.1 thorpej * Return the current line number. If yacc has looked ahead and caused
598 1.1 thorpej * us to consume a newline, we have to subtract one. yychar is yacc's
599 1.1 thorpej * token lookahead, so we can tell.
600 1.1 thorpej */
601 1.1 thorpej int
602 1.1 thorpej currentline(void)
603 1.1 thorpej {
604 1.1 thorpej extern int yychar;
605 1.1 thorpej
606 1.1 thorpej return (yyline - (yychar == '\n'));
607 1.1 thorpej }
608 1.9 cube
609 1.9 cube static int
610 1.9 cube getcurifdef(void)
611 1.9 cube {
612 1.9 cube char *p = yytext, *q;
613 1.9 cube
614 1.9 cube while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p))
615 1.9 cube p++;
616 1.9 cube while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p))
617 1.9 cube p++;
618 1.9 cube q = p;
619 1.9 cube while (*q && isascii((unsigned int)*q) && !isspace((unsigned int)*q))
620 1.9 cube q++;
621 1.9 cube *q = '\0';
622 1.9 cube
623 1.9 cube return ht_lookup(attrtab, intern(p)) != NULL;
624 1.9 cube }
625