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