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