scan.l revision 1.24 1 1.1 thorpej %{
2 1.24 uebayasi /* $NetBSD: scan.l,v 1.24 2015/09/01 13:42:48 uebayasi 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.24 uebayasi __RCSID("$NetBSD: scan.l,v 1.24 2015/09/01 13:42:48 uebayasi 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.24 uebayasi buildprefix return BUILDPREFIX;
168 1.1 thorpej pseudo-device return PSEUDO_DEVICE;
169 1.15 pooka pseudo-root return PSEUDO_ROOT;
170 1.1 thorpej root return ROOT;
171 1.21 uebayasi select return SELECT;
172 1.16 pooka single return SINGLE;
173 1.1 thorpej source return SOURCE;
174 1.1 thorpej type return TYPE;
175 1.16 pooka vector return VECTOR;
176 1.3 cube version return VERSION;
177 1.1 thorpej with return WITH;
178 1.1 thorpej
179 1.1 thorpej \+= return PLUSEQ;
180 1.6 cube := return COLONEQ;
181 1.1 thorpej
182 1.9 cube <*>ifdef[ \t]+{WORD}{RESTOFLINE} {
183 1.9 cube ifdefstate = (ifdefstate + 1) * 6;
184 1.9 cube if (ifdefstate >= IDS_MAX_DEPTH) {
185 1.9 cube yyerror("too many levels of conditional");
186 1.9 cube }
187 1.9 cube if (!IDS_PARENT_DISABLED && getcurifdef()) {
188 1.9 cube BEGIN(INITIAL);
189 1.9 cube } else {
190 1.9 cube ifdefstate++;
191 1.9 cube BEGIN(IGNORED);
192 1.9 cube }
193 1.9 cube yyline++;
194 1.9 cube }
195 1.9 cube
196 1.9 cube <*>ifndef[ \t]+{WORD}{RESTOFLINE} {
197 1.9 cube ifdefstate = (ifdefstate + 1) * 6;
198 1.9 cube if (ifdefstate >= IDS_MAX_DEPTH) {
199 1.9 cube yyerror("too many levels of conditional");
200 1.9 cube }
201 1.9 cube if (!IDS_PARENT_DISABLED && !getcurifdef()) {
202 1.9 cube BEGIN(INITIAL);
203 1.9 cube } else {
204 1.9 cube ifdefstate++;
205 1.9 cube BEGIN(IGNORED);
206 1.9 cube }
207 1.9 cube yyline++;
208 1.9 cube }
209 1.9 cube
210 1.9 cube
211 1.9 cube <*>elifdef[ \t]+{WORD}{RESTOFLINE} {
212 1.9 cube st = ifdefstate % 6;
213 1.9 cube if (ifdefstate < 0 || st > 3) {
214 1.9 cube yyerror("mismatched elifdef");
215 1.9 cube }
216 1.9 cube if (IDS_PARENT_DISABLED ||
217 1.9 cube st != 1 || !getcurifdef()) {
218 1.9 cube if (st == 2 || st == 3) {
219 1.9 cube ifdefstate += 3 - st;
220 1.9 cube } else {
221 1.9 cube ifdefstate += 1 - st;
222 1.9 cube }
223 1.9 cube BEGIN(IGNORED);
224 1.9 cube } else {
225 1.9 cube ifdefstate++;
226 1.9 cube BEGIN(INITIAL);
227 1.9 cube }
228 1.9 cube yyline++;
229 1.9 cube }
230 1.9 cube
231 1.9 cube <*>elifndef[ \t]+{WORD}{RESTOFLINE} {
232 1.9 cube st = ifdefstate % 6;
233 1.9 cube if (ifdefstate < 0 || st > 3) {
234 1.9 cube yyerror("mismatched elifndef");
235 1.9 cube }
236 1.9 cube if (IDS_PARENT_DISABLED ||
237 1.9 cube st != 1 || getcurifdef()) {
238 1.9 cube if (st == 2 || st == 3) {
239 1.9 cube ifdefstate += 3 - st;
240 1.9 cube } else {
241 1.9 cube ifdefstate += 1 - st;
242 1.9 cube }
243 1.9 cube BEGIN(IGNORED);
244 1.9 cube } else {
245 1.9 cube ifdefstate++;
246 1.9 cube BEGIN(INITIAL);
247 1.9 cube }
248 1.9 cube yyline++;
249 1.9 cube }
250 1.9 cube
251 1.9 cube <*>else{RESTOFLINE} {
252 1.9 cube st = ifdefstate % 6;
253 1.9 cube if (ifdefstate < 0 || st > 3) {
254 1.9 cube yyerror("mismatched else");
255 1.9 cube }
256 1.9 cube if (!IDS_PARENT_DISABLED && (st == 1)) {
257 1.9 cube ifdefstate += 3;
258 1.9 cube BEGIN(INITIAL);
259 1.9 cube } else {
260 1.9 cube ifdefstate += 5 - st;
261 1.9 cube BEGIN(IGNORED);
262 1.9 cube }
263 1.9 cube yyline++;
264 1.9 cube }
265 1.9 cube
266 1.9 cube <*>endif{RESTOFLINE} {
267 1.9 cube if (ifdefstate < 0) {
268 1.9 cube yyerror("mismatched endif");
269 1.9 cube }
270 1.9 cube if (!IDS_PARENT_DISABLED) {
271 1.9 cube BEGIN(INITIAL);
272 1.9 cube }
273 1.9 cube ifdefstate = (ifdefstate/6) - 1;
274 1.9 cube yyline++;
275 1.9 cube }
276 1.9 cube
277 1.9 cube <IGNORED>\n {
278 1.9 cube yyline++;
279 1.9 cube }
280 1.9 cube
281 1.9 cube <IGNORED>. /* ignore */
282 1.9 cube
283 1.8 cube include[ \t]+{FILENAME}{RESTOFLINE} {
284 1.8 cube yyline++;
285 1.2 martin if (getincludepath()) {
286 1.2 martin include(curinclpath, 0, 0, 1);
287 1.2 martin } else {
288 1.2 martin yyerror("bad include path-name");
289 1.2 martin }
290 1.2 martin }
291 1.2 martin
292 1.8 cube cinclude[ \t]+{FILENAME}{RESTOFLINE} {
293 1.8 cube yyline++;
294 1.2 martin if (getincludepath()) {
295 1.2 martin include(curinclpath, 0, 1, 1);
296 1.2 martin } else {
297 1.2 martin yyerror("bad cinclude path-name");
298 1.2 martin }
299 1.2 martin }
300 1.2 martin
301 1.8 cube package[ \t]+{FILENAME}{RESTOFLINE} {
302 1.8 cube yyline++;
303 1.2 martin if (!oktopackage) {
304 1.2 martin yyerror("package not allowed here");
305 1.2 martin } else if (getincludepath()) {
306 1.2 martin package(curinclpath);
307 1.2 martin } else {
308 1.2 martin yyerror("bad package path-name");
309 1.2 martin }
310 1.2 martin }
311 1.2 martin
312 1.1 thorpej {PATH} {
313 1.1 thorpej yylval.str = intern(yytext);
314 1.1 thorpej return PATHNAME;
315 1.1 thorpej }
316 1.1 thorpej
317 1.1 thorpej {WORD} {
318 1.1 thorpej yylval.str = intern(yytext);
319 1.1 thorpej return WORD;
320 1.1 thorpej }
321 1.1 thorpej
322 1.1 thorpej \"\" {
323 1.1 thorpej yylval.str = intern("");
324 1.5 christos return EMPTYSTRING;
325 1.1 thorpej }
326 1.2 martin
327 1.22 christos {QCHARS} {
328 1.22 christos size_t l = strlen(yytext);
329 1.22 christos if (l > 1 && yytext[l - 1] == '"')
330 1.22 christos yytext[l - 1] = '\0';
331 1.22 christos
332 1.1 thorpej yylval.str = intern(yytext + 1);
333 1.1 thorpej return QSTRING;
334 1.1 thorpej }
335 1.1 thorpej 0[0-7]* {
336 1.1 thorpej yylval.num.fmt = 8;
337 1.1 thorpej yylval.num.val = strtoll(yytext, NULL, 8);
338 1.1 thorpej return NUMBER;
339 1.1 thorpej }
340 1.1 thorpej 0[xX][0-9a-fA-F]+ {
341 1.1 thorpej yylval.num.fmt = 16;
342 1.20 christos yylval.num.val = (long long)strtoull(yytext + 2, NULL, 16);
343 1.1 thorpej return NUMBER;
344 1.1 thorpej }
345 1.1 thorpej [1-9][0-9]* {
346 1.1 thorpej yylval.num.fmt = 10;
347 1.1 thorpej yylval.num.val = strtoll(yytext, NULL, 10);
348 1.1 thorpej return NUMBER;
349 1.1 thorpej }
350 1.1 thorpej \n[ \t] {
351 1.1 thorpej /*
352 1.1 thorpej * Note: newline followed by whitespace is always a
353 1.1 thorpej * continuation of the previous line, so do NOT
354 1.1 thorpej * return a token in this case.
355 1.1 thorpej */
356 1.1 thorpej yyline++;
357 1.1 thorpej }
358 1.1 thorpej \n {
359 1.1 thorpej yyline++;
360 1.1 thorpej return '\n';
361 1.1 thorpej }
362 1.1 thorpej \00 {
363 1.1 thorpej /* Detect NUL characters in the config file and
364 1.1 thorpej * error out.
365 1.1 thorpej */
366 1.23 christos cfgerror("NUL character detected at line %i", yyline);
367 1.1 thorpej }
368 1.1 thorpej #.* { /* ignored (comment) */; }
369 1.1 thorpej [ \t]+ { /* ignored (white space) */; }
370 1.1 thorpej . { return yytext[0]; }
371 1.9 cube <*><<EOF>> {
372 1.9 cube if (ifdefstate > (incl == NULL ? -1 : incl->in_ifdefstate)) {
373 1.9 cube yyerror("reached EOF while looking for endif");
374 1.9 cube }
375 1.1 thorpej if (incl == NULL)
376 1.1 thorpej return YY_NULL;
377 1.1 thorpej tok = endinclude();
378 1.1 thorpej if (tok)
379 1.1 thorpej return tok;
380 1.1 thorpej /* otherwise continue scanning */
381 1.1 thorpej }
382 1.1 thorpej
383 1.1 thorpej %%
384 1.1 thorpej
385 1.1 thorpej int interesting = 1;
386 1.1 thorpej
387 1.1 thorpej static int
388 1.1 thorpej curdir_push(const char *fname)
389 1.1 thorpej {
390 1.1 thorpej struct prefix *pf;
391 1.1 thorpej char *p, *d, *f;
392 1.1 thorpej
393 1.1 thorpej /* Set up the initial "current directory" for include directives. */
394 1.1 thorpej d = dirname(f = estrdup(fname));
395 1.1 thorpej if (*d == '/')
396 1.1 thorpej p = estrdup(d);
397 1.1 thorpej else {
398 1.1 thorpej char *cwd, buf[PATH_MAX];
399 1.1 thorpej
400 1.11 dholland if ((cwd = getcwd(buf, sizeof(buf))) == NULL) {
401 1.11 dholland free(f);
402 1.1 thorpej return (-1);
403 1.11 dholland }
404 1.22 christos easprintf(&p, "%s/%s", cwd, d);
405 1.1 thorpej }
406 1.1 thorpej free(f);
407 1.1 thorpej pf = ecalloc(1, sizeof(*pf));
408 1.1 thorpej pf->pf_prefix = p;
409 1.1 thorpej SLIST_INSERT_HEAD(&curdirs, pf, pf_next);
410 1.1 thorpej
411 1.1 thorpej return (0);
412 1.1 thorpej }
413 1.1 thorpej
414 1.1 thorpej static void
415 1.1 thorpej curdir_pop(void)
416 1.1 thorpej {
417 1.1 thorpej struct prefix *pf;
418 1.1 thorpej
419 1.1 thorpej pf = SLIST_FIRST(&curdirs);
420 1.1 thorpej SLIST_REMOVE_HEAD(&curdirs, pf_next);
421 1.1 thorpej if (SLIST_EMPTY(&curdirs))
422 1.1 thorpej panic("curdirs is empty");
423 1.1 thorpej /* LINTED cast away const (pf_prefix is malloc'd for curdirs) */
424 1.12 lukem free((void *)__UNCONST(pf->pf_prefix));
425 1.1 thorpej free(pf);
426 1.1 thorpej }
427 1.1 thorpej
428 1.1 thorpej /*
429 1.1 thorpej * Open the "main" file (conffile).
430 1.1 thorpej */
431 1.1 thorpej int
432 1.1 thorpej firstfile(const char *fname)
433 1.1 thorpej {
434 1.1 thorpej
435 1.1 thorpej #if defined(__NetBSD__)
436 1.1 thorpej if ((yyin = fopen(fname, "rf")) == NULL)
437 1.1 thorpej #else
438 1.1 thorpej if ((yyin = fopen(fname, "r")) == NULL)
439 1.1 thorpej #endif
440 1.1 thorpej return (-1);
441 1.1 thorpej
442 1.1 thorpej if (curdir_push(fname) == -1)
443 1.1 thorpej return (-1);
444 1.1 thorpej
445 1.1 thorpej yyfile = conffile = fname;
446 1.1 thorpej yyline = 1;
447 1.1 thorpej return (0);
448 1.1 thorpej }
449 1.1 thorpej
450 1.1 thorpej /*
451 1.1 thorpej * Add a "package" to the configuration. This is essentially
452 1.1 thorpej * syntactic sugar around the sequence:
453 1.1 thorpej *
454 1.1 thorpej * prefix ../some/directory
455 1.1 thorpej * include "files.package"
456 1.1 thorpej * prefix
457 1.1 thorpej */
458 1.1 thorpej void
459 1.1 thorpej package(const char *fname)
460 1.1 thorpej {
461 1.1 thorpej char *fname1 = estrdup(fname);
462 1.1 thorpej char *fname2 = estrdup(fname);
463 1.1 thorpej char *dir = dirname(fname1);
464 1.1 thorpej char *file = basename(fname2);
465 1.1 thorpej
466 1.1 thorpej /*
467 1.1 thorpej * Push the prefix on to the prefix stack and process the include
468 1.1 thorpej * file. When we reach the end of the include file, inserting
469 1.1 thorpej * the PREFIX token into the input stream will pop the prefix off
470 1.1 thorpej * of the prefix stack.
471 1.1 thorpej */
472 1.1 thorpej prefix_push(dir);
473 1.1 thorpej (void) include(file, PREFIX, 0, 1);
474 1.1 thorpej
475 1.1 thorpej free(fname1);
476 1.1 thorpej free(fname2);
477 1.1 thorpej }
478 1.1 thorpej
479 1.1 thorpej /*
480 1.1 thorpej * Open the named file for inclusion at the current point. Returns 0 on
481 1.1 thorpej * success (file opened and previous state pushed), nonzero on failure
482 1.1 thorpej * (fopen failed, complaint made). The `ateof' parameter controls the
483 1.1 thorpej * token to be inserted at the end of the include file (i.e. ENDFILE).
484 1.1 thorpej * If ateof == 0 then nothing is inserted.
485 1.1 thorpej */
486 1.1 thorpej int
487 1.1 thorpej include(const char *fname, int ateof, int conditional, int direct)
488 1.1 thorpej {
489 1.1 thorpej FILE *fp;
490 1.1 thorpej struct incl *in;
491 1.1 thorpej char *s;
492 1.1 thorpej static int havedirs;
493 1.1 thorpej extern int vflag;
494 1.1 thorpej
495 1.1 thorpej if (havedirs == 0) {
496 1.1 thorpej havedirs = 1;
497 1.1 thorpej setupdirs();
498 1.1 thorpej }
499 1.1 thorpej
500 1.1 thorpej if (fname[0] == '/')
501 1.1 thorpej s = estrdup(fname);
502 1.1 thorpej else if (fname[0] == '.' && fname[1] == '/') {
503 1.1 thorpej struct prefix *pf = SLIST_FIRST(&curdirs);
504 1.22 christos easprintf(&s, "%s/%s", pf->pf_prefix, fname + 2);
505 1.1 thorpej } else
506 1.1 thorpej s = sourcepath(fname);
507 1.1 thorpej if ((fp = fopen(s, "r")) == NULL) {
508 1.1 thorpej if (conditional == 0)
509 1.23 christos cfgerror("cannot open %s for reading: %s", s,
510 1.1 thorpej strerror(errno));
511 1.1 thorpej else if (vflag)
512 1.7 christos cfgwarn("cannot open conditional include file %s: %s",
513 1.1 thorpej s, strerror(errno));
514 1.1 thorpej free(s);
515 1.1 thorpej return (-1);
516 1.1 thorpej }
517 1.1 thorpej if (curdir_push(s) == -1) {
518 1.23 christos cfgerror("cannot record current working directory for %s", s);
519 1.1 thorpej fclose(fp);
520 1.1 thorpej free(s);
521 1.1 thorpej return (-1);
522 1.1 thorpej }
523 1.1 thorpej in = ecalloc(1, sizeof *in);
524 1.1 thorpej in->in_prev = incl;
525 1.1 thorpej in->in_buf = YY_CURRENT_BUFFER;
526 1.1 thorpej in->in_fname = yyfile;
527 1.1 thorpej in->in_lineno = yyline;
528 1.1 thorpej in->in_ateof = ateof;
529 1.1 thorpej in->in_interesting = interesting;
530 1.9 cube in->in_ifdefstate = ifdefstate;
531 1.1 thorpej interesting = direct & interesting;
532 1.1 thorpej if (interesting)
533 1.1 thorpej logconfig_include(fp, fname);
534 1.1 thorpej incl = in;
535 1.18 uebayasi CFGDBG(1, "include `%s' from `%s' line %d", fname, yyfile, yyline);
536 1.1 thorpej yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
537 1.1 thorpej yyfile = intern(s);
538 1.1 thorpej yyline = 1;
539 1.1 thorpej free(s);
540 1.1 thorpej return (0);
541 1.1 thorpej }
542 1.1 thorpej
543 1.1 thorpej /*
544 1.2 martin * Extract the pathname from a include/cinclude/package into curinclpath
545 1.2 martin */
546 1.2 martin static int
547 1.17 matt getincludepath(void)
548 1.2 martin {
549 1.2 martin const char *p = yytext;
550 1.8 cube ptrdiff_t len;
551 1.8 cube const char *e;
552 1.2 martin
553 1.8 cube while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p))
554 1.2 martin p++;
555 1.8 cube while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p))
556 1.2 martin p++;
557 1.2 martin if (!*p)
558 1.2 martin return 0;
559 1.2 martin if (*p == '"') {
560 1.8 cube p++;
561 1.8 cube e = strchr(p, '"');
562 1.2 martin if (!e) return 0;
563 1.2 martin } else {
564 1.8 cube e = p;
565 1.8 cube while (*e && isascii((unsigned int)*e)
566 1.8 cube && !isspace((unsigned int)*e))
567 1.8 cube e++;
568 1.2 martin }
569 1.2 martin
570 1.8 cube len = e-p;
571 1.12 lukem if (len > (ptrdiff_t)sizeof(curinclpath)-1)
572 1.8 cube len = sizeof(curinclpath)-1;
573 1.8 cube strncpy(curinclpath, p, sizeof(curinclpath));
574 1.8 cube curinclpath[len] = '\0';
575 1.8 cube
576 1.2 martin return 1;
577 1.2 martin }
578 1.2 martin
579 1.2 martin /*
580 1.1 thorpej * Terminate the most recent inclusion.
581 1.1 thorpej */
582 1.1 thorpej static int
583 1.1 thorpej endinclude(void)
584 1.1 thorpej {
585 1.1 thorpej struct incl *in;
586 1.1 thorpej int ateof;
587 1.1 thorpej
588 1.1 thorpej curdir_pop();
589 1.1 thorpej if ((in = incl) == NULL)
590 1.1 thorpej panic("endinclude");
591 1.1 thorpej incl = in->in_prev;
592 1.1 thorpej lastfile = yyfile;
593 1.1 thorpej yy_delete_buffer(YY_CURRENT_BUFFER);
594 1.1 thorpej (void)fclose(yyin);
595 1.1 thorpej yy_switch_to_buffer(in->in_buf);
596 1.1 thorpej yyfile = in->in_fname;
597 1.1 thorpej yyline = in->in_lineno;
598 1.1 thorpej ateof = in->in_ateof;
599 1.1 thorpej interesting = in->in_interesting;
600 1.1 thorpej free(in);
601 1.1 thorpej
602 1.1 thorpej return (ateof);
603 1.1 thorpej }
604 1.1 thorpej
605 1.1 thorpej /*
606 1.1 thorpej * Return the current line number. If yacc has looked ahead and caused
607 1.1 thorpej * us to consume a newline, we have to subtract one. yychar is yacc's
608 1.1 thorpej * token lookahead, so we can tell.
609 1.1 thorpej */
610 1.19 christos u_short
611 1.1 thorpej currentline(void)
612 1.1 thorpej {
613 1.1 thorpej extern int yychar;
614 1.1 thorpej
615 1.19 christos return (u_short)(yyline - (yychar == '\n'));
616 1.1 thorpej }
617 1.9 cube
618 1.9 cube static int
619 1.9 cube getcurifdef(void)
620 1.9 cube {
621 1.9 cube char *p = yytext, *q;
622 1.9 cube
623 1.9 cube while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p))
624 1.9 cube p++;
625 1.9 cube while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p))
626 1.9 cube p++;
627 1.9 cube q = p;
628 1.9 cube while (*q && isascii((unsigned int)*q) && !isspace((unsigned int)*q))
629 1.9 cube q++;
630 1.9 cube *q = '\0';
631 1.9 cube
632 1.9 cube return ht_lookup(attrtab, intern(p)) != NULL;
633 1.9 cube }
634