Home | History | Annotate | Line # | Download | only in config
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