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