15ecc953bSthorpej %{ 2*93b25323Sjoe /* $NetBSD: scan.l,v 1.37 2025/01/07 14:21:11 joe Exp $ */ 35ecc953bSthorpej 45ecc953bSthorpej /* 55ecc953bSthorpej * Copyright (c) 1992, 1993 65ecc953bSthorpej * The Regents of the University of California. All rights reserved. 75ecc953bSthorpej * 85ecc953bSthorpej * This software was developed by the Computer Systems Engineering group 95ecc953bSthorpej * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 105ecc953bSthorpej * contributed to Berkeley. 115ecc953bSthorpej * 125ecc953bSthorpej * All advertising materials mentioning features or use of this software 135ecc953bSthorpej * must display the following acknowledgement: 145ecc953bSthorpej * This product includes software developed by the University of 155ecc953bSthorpej * California, Lawrence Berkeley Laboratories. 165ecc953bSthorpej * 175ecc953bSthorpej * Redistribution and use in source and binary forms, with or without 185ecc953bSthorpej * modification, are permitted provided that the following conditions 195ecc953bSthorpej * are met: 205ecc953bSthorpej * 1. Redistributions of source code must retain the above copyright 215ecc953bSthorpej * notice, this list of conditions and the following disclaimer. 225ecc953bSthorpej * 2. Redistributions in binary form must reproduce the above copyright 235ecc953bSthorpej * notice, this list of conditions and the following disclaimer in the 245ecc953bSthorpej * documentation and/or other materials provided with the distribution. 255ecc953bSthorpej * 3. Neither the name of the University nor the names of its contributors 265ecc953bSthorpej * may be used to endorse or promote products derived from this software 275ecc953bSthorpej * without specific prior written permission. 285ecc953bSthorpej * 295ecc953bSthorpej * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 305ecc953bSthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 315ecc953bSthorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 325ecc953bSthorpej * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 335ecc953bSthorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 345ecc953bSthorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 355ecc953bSthorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 365ecc953bSthorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 375ecc953bSthorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 385ecc953bSthorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 395ecc953bSthorpej * SUCH DAMAGE. 405ecc953bSthorpej * 415ecc953bSthorpej * from: @(#)scan.l 8.1 (Berkeley) 6/6/93 425ecc953bSthorpej */ 435ecc953bSthorpej 44d12b0036Schristos #include <sys/cdefs.h> 45*93b25323Sjoe __RCSID("$NetBSD: scan.l,v 1.37 2025/01/07 14:21:11 joe Exp $"); 46d12b0036Schristos 475ecc953bSthorpej #include <sys/param.h> 485ecc953bSthorpej #include <errno.h> 495ecc953bSthorpej #include <libgen.h> 505ecc953bSthorpej #include <stdio.h> 515ecc953bSthorpej #include <stdlib.h> 525ecc953bSthorpej #include <string.h> 535ecc953bSthorpej #include <unistd.h> 546fd5c015Smartin #include <stddef.h> 556fd5c015Smartin #include <ctype.h> 56d0fb8901Schristos #include <util.h> 57d0fb8901Schristos #undef ECHO 585ecc953bSthorpej #include "defs.h" 595ecc953bSthorpej #include "gram.h" 605ecc953bSthorpej 615ecc953bSthorpej int yyline; 625ecc953bSthorpej const char *yyfile; 635ecc953bSthorpej const char *lastfile; 646fd5c015Smartin char curinclpath[PATH_MAX]; 65c2ac5ba4Schristos uint64_t ifdefstate; 66c2ac5ba4Schristos int ifdefshift = -1; 67656cdcc8Scube 68c2ac5ba4Schristos /* 69c2ac5ba4Schristos * The state is represented by 3 bits. 70656cdcc8Scube */ 71180ab6e0Schristos #define IDS_ENABLED 1ll 72180ab6e0Schristos #define IDS_MATCH 2ll 73180ab6e0Schristos #define IDS_ELIF 4ll 74180ab6e0Schristos #define IDS_ELSE 8ll 75c2ac5ba4Schristos 76180ab6e0Schristos #define IDS_BITS 0xf 77180ab6e0Schristos #define IDS_SHIFT 4 78c2ac5ba4Schristos 79c2ac5ba4Schristos #define IDS_ISMATCH(st) (((st) & IDS_MATCH) != 0) 80180ab6e0Schristos #define IDS_ISENABLED(st) (((st) & IDS_ENABLED) != 0) 81c2ac5ba4Schristos #define IDS_PARENT_DISABLED \ 82180ab6e0Schristos (ifdefshift > 0 && !IDS_ISENABLED(ifdefstate >> IDS_SHIFT)) 83180ab6e0Schristos #define IDS_MAX_DEPTH 16 /* 64 / 4 */ 845ecc953bSthorpej 85eb23c9a2Schristos #ifdef IDS_DEBUG 86eb23c9a2Schristos # define IDS_PRINT(s, st, x) \ 87eb23c9a2Schristos do { \ 88eb23c9a2Schristos for (int i = 0; i < ifdefshift + 1; i++) \ 89eb23c9a2Schristos fprintf(stderr, " "); \ 90eb23c9a2Schristos printf("%s%s [%d,%d,%d] %#" PRIx64 "\n", x, # s, \ 91eb23c9a2Schristos IDS_PARENT_DISABLED, IDS_ISMATCH(st), getcurifdef(), \ 92eb23c9a2Schristos ifdefstate); \ 93133e932aSrillig } while (0) 94eb23c9a2Schristos #else 95180ab6e0Schristos # define IDS_PRINT(s, st, x) ((void)0) 96eb23c9a2Schristos #endif 97eb23c9a2Schristos 98eb23c9a2Schristos #define IDS_ENTER(s, st) \ 99eb23c9a2Schristos IDS_PRINT(s, st, ">") 100eb23c9a2Schristos #define IDS_EXIT(s, st) \ 101eb23c9a2Schristos IDS_PRINT(s, st, "<") 102eb23c9a2Schristos 1035ecc953bSthorpej /* 1045ecc953bSthorpej * Data for returning to previous files from include files. 1055ecc953bSthorpej */ 1065ecc953bSthorpej struct incl { 1075ecc953bSthorpej struct incl *in_prev; /* previous includes in effect, if any */ 1085ecc953bSthorpej YY_BUFFER_STATE in_buf; /* previous lex state */ 10920255392Schristos struct where in_where; 1105ecc953bSthorpej int in_ateof; /* token to insert at EOF */ 1115ecc953bSthorpej int in_interesting; /* previous value for "interesting" */ 112c2ac5ba4Schristos uint64_t in_ifdefstate; /* conditional level */ 113c2ac5ba4Schristos int in_ifdefshift; /* conditional level */ 1145ecc953bSthorpej }; 1155ecc953bSthorpej static struct incl *incl; 1165ecc953bSthorpej static int endinclude(void); 1176fd5c015Smartin static int getincludepath(void); 118656cdcc8Scube static int getcurifdef(void); 1195ecc953bSthorpej 1209d91b80eSjoerg SLIST_HEAD(, prefix) curdirs; /* curdir stack */ 1215ecc953bSthorpej 1225ecc953bSthorpej %} 1235ecc953bSthorpej 124727f2362Schristos %option noyywrap nounput noinput 125c2261f67Schristos 1265ecc953bSthorpej PATH [A-Za-z_0-9]*[./][-A-Za-z_0-9./]* 127727f2362Schristos QCHARS \"(\\.|[^\\"])*\" 1285ecc953bSthorpej WORD [A-Za-z_][-A-Za-z_0-9]* 129727f2362Schristos FILENAME ({PATH}|{QCHARS}) 130f51c36b8Scube RESTOFLINE [ \t]*(#[^\n]*)?\n 131782c9b91Schristos WS ^[ \t]* 1325ecc953bSthorpej 133656cdcc8Scube %x IGNORED 134656cdcc8Scube 1355ecc953bSthorpej %% 1365ecc953bSthorpej /* Local variables for yylex() */ 1375ecc953bSthorpej int tok; 1385ecc953bSthorpej 1395ecc953bSthorpej and return AND; 1405ecc953bSthorpej at return AT; 1415ecc953bSthorpej attach return ATTACH; 1425ecc953bSthorpej block return BLOCK; 1435ecc953bSthorpej build return BUILD; 1445ecc953bSthorpej char return CHAR; 1455ecc953bSthorpej compile-with return COMPILE_WITH; 1465ecc953bSthorpej config return CONFIG; 1475ecc953bSthorpej deffs return DEFFS; 1485ecc953bSthorpej define return DEFINE; 1495ecc953bSthorpej defflag return DEFFLAG; 1505ecc953bSthorpej defopt return DEFOPT; 1515ecc953bSthorpej defparam return DEFPARAM; 1525ecc953bSthorpej defpseudo return DEFPSEUDO; 1538456b350Sdrochner defpseudodev return DEFPSEUDODEV; 1545ecc953bSthorpej devclass return DEVCLASS; 1555ecc953bSthorpej device return DEVICE; 1565ecc953bSthorpej device-major return DEVICE_MAJOR; 1575ecc953bSthorpej dumps return DUMPS; 1585ecc953bSthorpej file return XFILE; 1595ecc953bSthorpej file-system return FILE_SYSTEM; 1605ecc953bSthorpej flags return FLAGS; 1615ecc953bSthorpej ident return IDENT; 162e239742fSpooka ioconf return IOCONF; 1633da3ab25Spooka linkzero return LINKZERO; 1645ecc953bSthorpej machine return XMACHINE; 1655ecc953bSthorpej major return MAJOR; 1665ecc953bSthorpej makeoptions return MAKEOPTIONS; 167e407e527Sthorpej mkflagvar return MKFLAGVAR; 1685ecc953bSthorpej maxpartitions return MAXPARTITIONS; 1695ecc953bSthorpej maxusers return MAXUSERS; 1705ecc953bSthorpej minor return MINOR; 1715ecc953bSthorpej needs-count return NEEDS_COUNT; 1725ecc953bSthorpej needs-flag return NEEDS_FLAG; 1735ecc953bSthorpej no return NO; 174f138f6c5Schristos -no return CNO; 1755ecc953bSthorpej object return XOBJECT; 176ac24e161Scube obsolete return OBSOLETE; 1775ecc953bSthorpej on return ON; 1785ecc953bSthorpej options return OPTIONS; 1795ecc953bSthorpej prefix return PREFIX; 1802cb009cdSuebayasi buildprefix return BUILDPREFIX; 1815ecc953bSthorpej pseudo-device return PSEUDO_DEVICE; 18290ac64deSpooka pseudo-root return PSEUDO_ROOT; 1835ecc953bSthorpej root return ROOT; 184c42523f4Suebayasi select return SELECT; 1853da3ab25Spooka single return SINGLE; 1865ecc953bSthorpej source return SOURCE; 1875ecc953bSthorpej type return TYPE; 1883da3ab25Spooka vector return VECTOR; 189437f8925Scube version return VERSION; 1905ecc953bSthorpej with return WITH; 1915ecc953bSthorpej 1925ecc953bSthorpej \+= return PLUSEQ; 19390426267Scube := return COLONEQ; 1945ecc953bSthorpej 195782c9b91Schristos <*>{WS}ifdef[ \t]+{WORD}{RESTOFLINE} { 196c2ac5ba4Schristos ifdefstate <<= IDS_SHIFT; 197c2ac5ba4Schristos if (++ifdefshift >= IDS_MAX_DEPTH) { 198656cdcc8Scube yyerror("too many levels of conditional"); 199656cdcc8Scube } 200eb23c9a2Schristos IDS_ENTER(ifdef, 0); 201c2ac5ba4Schristos if (IDS_PARENT_DISABLED || !getcurifdef()) { 202180ab6e0Schristos ifdefstate &= (uint64_t)~IDS_ENABLED; 203656cdcc8Scube BEGIN(IGNORED); 204c2ac5ba4Schristos } else { 205180ab6e0Schristos ifdefstate |= IDS_MATCH|IDS_ENABLED; 206c2ac5ba4Schristos BEGIN(INITIAL); 207656cdcc8Scube } 208eb23c9a2Schristos IDS_EXIT(ifdef, 0); 209656cdcc8Scube yyline++; 210656cdcc8Scube } 211656cdcc8Scube 212782c9b91Schristos <*>{WS}ifndef[ \t]+{WORD}{RESTOFLINE} { 213c2ac5ba4Schristos ifdefstate <<= IDS_SHIFT; 214c2ac5ba4Schristos if (++ifdefshift >= IDS_MAX_DEPTH) { 215656cdcc8Scube yyerror("too many levels of conditional"); 216656cdcc8Scube } 217eb23c9a2Schristos IDS_ENTER(ifndef, 0); 218c2ac5ba4Schristos if (IDS_PARENT_DISABLED || getcurifdef()) { 219180ab6e0Schristos ifdefstate &= (uint64_t)~IDS_ENABLED; 220656cdcc8Scube BEGIN(IGNORED); 221c2ac5ba4Schristos } else { 222180ab6e0Schristos ifdefstate |= IDS_MATCH|IDS_ENABLED; 223c2ac5ba4Schristos BEGIN(INITIAL); 224656cdcc8Scube } 225eb23c9a2Schristos IDS_EXIT(ifndef, 0); 226656cdcc8Scube yyline++; 227656cdcc8Scube } 228656cdcc8Scube 229656cdcc8Scube 230782c9b91Schristos <*>{WS}elifdef[ \t]+{WORD}{RESTOFLINE} { 231c2ac5ba4Schristos int st = ifdefstate & IDS_BITS; 232eb23c9a2Schristos IDS_ENTER(elifdef, st); 233c2ac5ba4Schristos if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { 234656cdcc8Scube yyerror("mismatched elifdef"); 235656cdcc8Scube } 236c2ac5ba4Schristos if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || !getcurifdef()) { 237180ab6e0Schristos ifdefstate &= (uint64_t)~IDS_ENABLED; 238656cdcc8Scube BEGIN(IGNORED); 239656cdcc8Scube } else { 240180ab6e0Schristos ifdefstate |= IDS_MATCH|IDS_ENABLED; 241656cdcc8Scube BEGIN(INITIAL); 242656cdcc8Scube } 243c2ac5ba4Schristos ifdefstate |= IDS_ELIF; 244eb23c9a2Schristos IDS_EXIT(elifdef, st); 245656cdcc8Scube yyline++; 246656cdcc8Scube } 247656cdcc8Scube 248782c9b91Schristos <*>{WS}elifndef[ \t]+{WORD}{RESTOFLINE} { 249c2ac5ba4Schristos int st = ifdefstate & IDS_BITS; 250eb23c9a2Schristos IDS_ENTER(elifndef, st); 251c2ac5ba4Schristos if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { 252656cdcc8Scube yyerror("mismatched elifndef"); 253656cdcc8Scube } 254c2ac5ba4Schristos if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || getcurifdef()) { 255180ab6e0Schristos ifdefstate &= (uint64_t)~IDS_ENABLED; 256656cdcc8Scube BEGIN(IGNORED); 257656cdcc8Scube } else { 258180ab6e0Schristos ifdefstate |= IDS_MATCH|IDS_ENABLED; 259656cdcc8Scube BEGIN(INITIAL); 260656cdcc8Scube } 261c2ac5ba4Schristos ifdefstate |= IDS_ELIF; 262eb23c9a2Schristos IDS_EXIT(elifndef, st); 263656cdcc8Scube yyline++; 264656cdcc8Scube } 265656cdcc8Scube 266782c9b91Schristos <*>{WS}else{RESTOFLINE} { 267c2ac5ba4Schristos int st = ifdefstate & IDS_BITS; 268eb23c9a2Schristos IDS_ENTER(else, st); 269c2ac5ba4Schristos if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { 270656cdcc8Scube yyerror("mismatched else"); 271656cdcc8Scube } 272c2ac5ba4Schristos if (IDS_PARENT_DISABLED || IDS_ISMATCH(st)) { 273180ab6e0Schristos ifdefstate &= (uint64_t)~IDS_ENABLED; 274656cdcc8Scube BEGIN(IGNORED); 275c2ac5ba4Schristos } else { 276180ab6e0Schristos ifdefstate |= IDS_MATCH|IDS_ENABLED; 277c2ac5ba4Schristos BEGIN(INITIAL); 278656cdcc8Scube } 279c2ac5ba4Schristos ifdefstate |= IDS_ELSE; 280eb23c9a2Schristos IDS_ENTER(else, st); 281656cdcc8Scube yyline++; 282656cdcc8Scube } 283656cdcc8Scube 284782c9b91Schristos <*>{WS}endif{RESTOFLINE} { 285eb23c9a2Schristos IDS_ENTER(endif, 0); 286c2ac5ba4Schristos if (ifdefshift == -1) { 287656cdcc8Scube yyerror("mismatched endif"); 288656cdcc8Scube } 289656cdcc8Scube if (!IDS_PARENT_DISABLED) { 290656cdcc8Scube BEGIN(INITIAL); 291656cdcc8Scube } 292eb23c9a2Schristos IDS_EXIT(endif, 0); 293c2ac5ba4Schristos ifdefshift--; 294c2ac5ba4Schristos ifdefstate >>= IDS_SHIFT; 295656cdcc8Scube yyline++; 296656cdcc8Scube } 297656cdcc8Scube 298656cdcc8Scube <IGNORED>\n { 299656cdcc8Scube yyline++; 300656cdcc8Scube } 301656cdcc8Scube 302656cdcc8Scube <IGNORED>. /* ignore */ 303656cdcc8Scube 304f51c36b8Scube include[ \t]+{FILENAME}{RESTOFLINE} { 305f51c36b8Scube yyline++; 3066fd5c015Smartin if (getincludepath()) { 3076fd5c015Smartin include(curinclpath, 0, 0, 1); 3086fd5c015Smartin } else { 3096fd5c015Smartin yyerror("bad include path-name"); 3106fd5c015Smartin } 3116fd5c015Smartin } 3126fd5c015Smartin 313f51c36b8Scube cinclude[ \t]+{FILENAME}{RESTOFLINE} { 314f51c36b8Scube yyline++; 3156fd5c015Smartin if (getincludepath()) { 3166fd5c015Smartin include(curinclpath, 0, 1, 1); 3176fd5c015Smartin } else { 3186fd5c015Smartin yyerror("bad cinclude path-name"); 3196fd5c015Smartin } 3206fd5c015Smartin } 3216fd5c015Smartin 322f51c36b8Scube package[ \t]+{FILENAME}{RESTOFLINE} { 323f51c36b8Scube yyline++; 3246fd5c015Smartin if (!oktopackage) { 3256fd5c015Smartin yyerror("package not allowed here"); 3266fd5c015Smartin } else if (getincludepath()) { 3276fd5c015Smartin package(curinclpath); 3286fd5c015Smartin } else { 3296fd5c015Smartin yyerror("bad package path-name"); 3306fd5c015Smartin } 3316fd5c015Smartin } 3326fd5c015Smartin 3335ecc953bSthorpej {PATH} { 3345ecc953bSthorpej yylval.str = intern(yytext); 3355ecc953bSthorpej return PATHNAME; 3365ecc953bSthorpej } 3375ecc953bSthorpej 3385ecc953bSthorpej {WORD} { 3395ecc953bSthorpej yylval.str = intern(yytext); 3405ecc953bSthorpej return WORD; 3415ecc953bSthorpej } 3425ecc953bSthorpej 3435ecc953bSthorpej \"\" { 3445ecc953bSthorpej yylval.str = intern(""); 345d0fb8901Schristos return EMPTYSTRING; 3465ecc953bSthorpej } 3476fd5c015Smartin 348727f2362Schristos {QCHARS} { 349727f2362Schristos size_t l = strlen(yytext); 350727f2362Schristos if (l > 1 && yytext[l - 1] == '"') 351727f2362Schristos yytext[l - 1] = '\0'; 352727f2362Schristos 3535ecc953bSthorpej yylval.str = intern(yytext + 1); 3545ecc953bSthorpej return QSTRING; 3555ecc953bSthorpej } 3565ecc953bSthorpej 0[0-7]* { 3575ecc953bSthorpej yylval.num.fmt = 8; 3585ecc953bSthorpej yylval.num.val = strtoll(yytext, NULL, 8); 3595ecc953bSthorpej return NUMBER; 3605ecc953bSthorpej } 3615ecc953bSthorpej 0[xX][0-9a-fA-F]+ { 3625ecc953bSthorpej yylval.num.fmt = 16; 3631ed33bc5Schristos yylval.num.val = (long long)strtoull(yytext + 2, NULL, 16); 3645ecc953bSthorpej return NUMBER; 3655ecc953bSthorpej } 3665ecc953bSthorpej [1-9][0-9]* { 3675ecc953bSthorpej yylval.num.fmt = 10; 3685ecc953bSthorpej yylval.num.val = strtoll(yytext, NULL, 10); 3695ecc953bSthorpej return NUMBER; 3705ecc953bSthorpej } 3715ecc953bSthorpej \n[ \t] { 3725ecc953bSthorpej /* 3735ecc953bSthorpej * Note: newline followed by whitespace is always a 3745ecc953bSthorpej * continuation of the previous line, so do NOT 3755ecc953bSthorpej * return a token in this case. 3765ecc953bSthorpej */ 3775ecc953bSthorpej yyline++; 3785ecc953bSthorpej } 3795ecc953bSthorpej \n { 3805ecc953bSthorpej yyline++; 3815ecc953bSthorpej return '\n'; 3825ecc953bSthorpej } 3835ecc953bSthorpej \00 { 3845ecc953bSthorpej /* Detect NUL characters in the config file and 3855ecc953bSthorpej * error out. 3865ecc953bSthorpej */ 387b921b702Schristos cfgerror("NUL character detected at line %i", yyline); 3885ecc953bSthorpej } 3895ecc953bSthorpej #.* { /* ignored (comment) */; } 3905ecc953bSthorpej [ \t]+ { /* ignored (white space) */; } 3915ecc953bSthorpej . { return yytext[0]; } 392656cdcc8Scube <*><<EOF>> { 393c2ac5ba4Schristos if (ifdefshift > (incl == NULL ? -1 : incl->in_ifdefshift)) { 394656cdcc8Scube yyerror("reached EOF while looking for endif"); 395656cdcc8Scube } 3965ecc953bSthorpej if (incl == NULL) 3975ecc953bSthorpej return YY_NULL; 3985ecc953bSthorpej tok = endinclude(); 3995ecc953bSthorpej if (tok) 4005ecc953bSthorpej return tok; 4015ecc953bSthorpej /* otherwise continue scanning */ 4025ecc953bSthorpej } 4035ecc953bSthorpej 4045ecc953bSthorpej %% 4055ecc953bSthorpej 4065ecc953bSthorpej int interesting = 1; 4075ecc953bSthorpej 4085ecc953bSthorpej static int 4095ecc953bSthorpej curdir_push(const char *fname) 4105ecc953bSthorpej { 4115ecc953bSthorpej struct prefix *pf; 4125ecc953bSthorpej char *p, *d, *f; 4135ecc953bSthorpej 4145ecc953bSthorpej /* Set up the initial "current directory" for include directives. */ 4155ecc953bSthorpej d = dirname(f = estrdup(fname)); 4165ecc953bSthorpej if (*d == '/') 4175ecc953bSthorpej p = estrdup(d); 4185ecc953bSthorpej else { 4195ecc953bSthorpej char *cwd, buf[PATH_MAX]; 4205ecc953bSthorpej 4213251535cSdholland if ((cwd = getcwd(buf, sizeof(buf))) == NULL) { 4223251535cSdholland free(f); 4235ecc953bSthorpej return (-1); 4243251535cSdholland } 425727f2362Schristos easprintf(&p, "%s/%s", cwd, d); 4265ecc953bSthorpej } 4275ecc953bSthorpej free(f); 4285ecc953bSthorpej pf = ecalloc(1, sizeof(*pf)); 4295ecc953bSthorpej pf->pf_prefix = p; 4305ecc953bSthorpej SLIST_INSERT_HEAD(&curdirs, pf, pf_next); 4315ecc953bSthorpej 4325ecc953bSthorpej return (0); 4335ecc953bSthorpej } 4345ecc953bSthorpej 4355ecc953bSthorpej static void 4365ecc953bSthorpej curdir_pop(void) 4375ecc953bSthorpej { 4385ecc953bSthorpej struct prefix *pf; 4395ecc953bSthorpej 4405ecc953bSthorpej pf = SLIST_FIRST(&curdirs); 4415ecc953bSthorpej SLIST_REMOVE_HEAD(&curdirs, pf_next); 4425ecc953bSthorpej if (SLIST_EMPTY(&curdirs)) 4435ecc953bSthorpej panic("curdirs is empty"); 4445ecc953bSthorpej /* LINTED cast away const (pf_prefix is malloc'd for curdirs) */ 4455cc303e1Slukem free((void *)__UNCONST(pf->pf_prefix)); 4465ecc953bSthorpej free(pf); 4475ecc953bSthorpej } 4485ecc953bSthorpej 4495ecc953bSthorpej /* 4505ecc953bSthorpej * Open the "main" file (conffile). 4515ecc953bSthorpej */ 4525ecc953bSthorpej int 4535ecc953bSthorpej firstfile(const char *fname) 4545ecc953bSthorpej { 4555ecc953bSthorpej 4565ecc953bSthorpej #if defined(__NetBSD__) 4575ecc953bSthorpej if ((yyin = fopen(fname, "rf")) == NULL) 4585ecc953bSthorpej #else 4595ecc953bSthorpej if ((yyin = fopen(fname, "r")) == NULL) 4605ecc953bSthorpej #endif 4615ecc953bSthorpej return (-1); 4625ecc953bSthorpej 4635ecc953bSthorpej if (curdir_push(fname) == -1) 4645ecc953bSthorpej return (-1); 4655ecc953bSthorpej 4665ecc953bSthorpej yyfile = conffile = fname; 4675ecc953bSthorpej yyline = 1; 4685ecc953bSthorpej return (0); 4695ecc953bSthorpej } 4705ecc953bSthorpej 4715ecc953bSthorpej /* 4725ecc953bSthorpej * Add a "package" to the configuration. This is essentially 4735ecc953bSthorpej * syntactic sugar around the sequence: 4745ecc953bSthorpej * 4755ecc953bSthorpej * prefix ../some/directory 4765ecc953bSthorpej * include "files.package" 4775ecc953bSthorpej * prefix 4785ecc953bSthorpej */ 4795ecc953bSthorpej void 4805ecc953bSthorpej package(const char *fname) 4815ecc953bSthorpej { 4825ecc953bSthorpej char *fname1 = estrdup(fname); 4835ecc953bSthorpej char *fname2 = estrdup(fname); 4845ecc953bSthorpej char *dir = dirname(fname1); 4855ecc953bSthorpej char *file = basename(fname2); 4865ecc953bSthorpej 4875ecc953bSthorpej /* 4885ecc953bSthorpej * Push the prefix on to the prefix stack and process the include 4895ecc953bSthorpej * file. When we reach the end of the include file, inserting 4905ecc953bSthorpej * the PREFIX token into the input stream will pop the prefix off 4915ecc953bSthorpej * of the prefix stack. 4925ecc953bSthorpej */ 4935ecc953bSthorpej prefix_push(dir); 4945ecc953bSthorpej (void) include(file, PREFIX, 0, 1); 4955ecc953bSthorpej 4965ecc953bSthorpej free(fname1); 4975ecc953bSthorpej free(fname2); 4985ecc953bSthorpej } 4995ecc953bSthorpej 5009b48d494Suebayasi int includedepth; 5019b48d494Suebayasi 5025ecc953bSthorpej /* 5035ecc953bSthorpej * Open the named file for inclusion at the current point. Returns 0 on 5045ecc953bSthorpej * success (file opened and previous state pushed), nonzero on failure 5055ecc953bSthorpej * (fopen failed, complaint made). The `ateof' parameter controls the 5065ecc953bSthorpej * token to be inserted at the end of the include file (i.e. ENDFILE). 5075ecc953bSthorpej * If ateof == 0 then nothing is inserted. 5085ecc953bSthorpej */ 5095ecc953bSthorpej int 5105ecc953bSthorpej include(const char *fname, int ateof, int conditional, int direct) 5115ecc953bSthorpej { 5125ecc953bSthorpej FILE *fp; 5135ecc953bSthorpej struct incl *in; 5145ecc953bSthorpej char *s; 5155ecc953bSthorpej static int havedirs; 5165ecc953bSthorpej extern int vflag; 5175ecc953bSthorpej 5185ecc953bSthorpej if (havedirs == 0) { 5195ecc953bSthorpej havedirs = 1; 5205ecc953bSthorpej setupdirs(); 5215ecc953bSthorpej } 5225ecc953bSthorpej 5235ecc953bSthorpej if (fname[0] == '/') 5245ecc953bSthorpej s = estrdup(fname); 5255ecc953bSthorpej else if (fname[0] == '.' && fname[1] == '/') { 5265ecc953bSthorpej struct prefix *pf = SLIST_FIRST(&curdirs); 527727f2362Schristos easprintf(&s, "%s/%s", pf->pf_prefix, fname + 2); 5285ecc953bSthorpej } else 5295ecc953bSthorpej s = sourcepath(fname); 5305ecc953bSthorpej if ((fp = fopen(s, "r")) == NULL) { 5315ecc953bSthorpej if (conditional == 0) 532b921b702Schristos cfgerror("cannot open %s for reading: %s", s, 5335ecc953bSthorpej strerror(errno)); 5345ecc953bSthorpej else if (vflag) 535c7295a4cSchristos cfgwarn("cannot open conditional include file %s: %s", 5365ecc953bSthorpej s, strerror(errno)); 5375ecc953bSthorpej free(s); 5385ecc953bSthorpej return (-1); 5395ecc953bSthorpej } 5405ecc953bSthorpej if (curdir_push(s) == -1) { 541b921b702Schristos cfgerror("cannot record current working directory for %s", s); 5425ecc953bSthorpej fclose(fp); 5435ecc953bSthorpej free(s); 5445ecc953bSthorpej return (-1); 5455ecc953bSthorpej } 5465ecc953bSthorpej in = ecalloc(1, sizeof *in); 5475ecc953bSthorpej in->in_prev = incl; 5485ecc953bSthorpej in->in_buf = YY_CURRENT_BUFFER; 54920255392Schristos in->in_where.w_srcfile = yyfile; 55020255392Schristos in->in_where.w_srcline = (u_short)yyline; 5515ecc953bSthorpej in->in_ateof = ateof; 5525ecc953bSthorpej in->in_interesting = interesting; 553656cdcc8Scube in->in_ifdefstate = ifdefstate; 554c2ac5ba4Schristos in->in_ifdefshift = ifdefshift; 5555ecc953bSthorpej interesting = direct & interesting; 5565ecc953bSthorpej if (interesting) 5575ecc953bSthorpej logconfig_include(fp, fname); 5585ecc953bSthorpej incl = in; 55961a3ba02Suwe CFGDBG(1, "include `%s'", fname); 5605ecc953bSthorpej yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); 5615ecc953bSthorpej yyfile = intern(s); 5625ecc953bSthorpej yyline = 1; 5635ecc953bSthorpej free(s); 5649b48d494Suebayasi includedepth++; 5655ecc953bSthorpej return (0); 5665ecc953bSthorpej } 5675ecc953bSthorpej 5685ecc953bSthorpej /* 5696fd5c015Smartin * Extract the pathname from a include/cinclude/package into curinclpath 5706fd5c015Smartin */ 5716fd5c015Smartin static int 572d34c2845Smatt getincludepath(void) 5736fd5c015Smartin { 5746fd5c015Smartin const char *p = yytext; 575f51c36b8Scube ptrdiff_t len; 576f51c36b8Scube const char *e; 5776fd5c015Smartin 578c178875fSuwe while (*p && isascii((unsigned char)*p) && !isspace((unsigned char)*p)) 5796fd5c015Smartin p++; 580c178875fSuwe while (*p && isascii((unsigned char)*p) && isspace((unsigned char)*p)) 5816fd5c015Smartin p++; 5826fd5c015Smartin if (!*p) 5836fd5c015Smartin return 0; 5846fd5c015Smartin if (*p == '"') { 585f51c36b8Scube p++; 586f51c36b8Scube e = strchr(p, '"'); 5876fd5c015Smartin if (!e) return 0; 588f51c36b8Scube } else { 589f51c36b8Scube e = p; 590c178875fSuwe while (*e && isascii((unsigned char)*e) 591c178875fSuwe && !isspace((unsigned char)*e)) 592f51c36b8Scube e++; 593f51c36b8Scube } 594f51c36b8Scube 595f51c36b8Scube len = e-p; 5965cc303e1Slukem if (len > (ptrdiff_t)sizeof(curinclpath)-1) 5976fd5c015Smartin len = sizeof(curinclpath)-1; 5986fd5c015Smartin strncpy(curinclpath, p, sizeof(curinclpath)); 599f51c36b8Scube curinclpath[len] = '\0'; 6006fd5c015Smartin 6016fd5c015Smartin return 1; 6026fd5c015Smartin } 6036fd5c015Smartin 6046fd5c015Smartin /* 6055ecc953bSthorpej * Terminate the most recent inclusion. 6065ecc953bSthorpej */ 6075ecc953bSthorpej static int 6085ecc953bSthorpej endinclude(void) 6095ecc953bSthorpej { 6105ecc953bSthorpej struct incl *in; 6115ecc953bSthorpej int ateof; 6125ecc953bSthorpej 6135ecc953bSthorpej curdir_pop(); 6145ecc953bSthorpej if ((in = incl) == NULL) 6155ecc953bSthorpej panic("endinclude"); 6165ecc953bSthorpej incl = in->in_prev; 6175ecc953bSthorpej lastfile = yyfile; 6185ecc953bSthorpej yy_delete_buffer(YY_CURRENT_BUFFER); 6195ecc953bSthorpej (void)fclose(yyin); 6205ecc953bSthorpej yy_switch_to_buffer(in->in_buf); 62120255392Schristos yyfile = in->in_where.w_srcfile; 62220255392Schristos yyline = in->in_where.w_srcline; 6235ecc953bSthorpej ateof = in->in_ateof; 6245ecc953bSthorpej interesting = in->in_interesting; 625c2ac5ba4Schristos ifdefstate = in->in_ifdefstate; 626c2ac5ba4Schristos ifdefshift = in->in_ifdefshift; 6275ecc953bSthorpej free(in); 6285ecc953bSthorpej 6299b48d494Suebayasi includedepth--; 6309b48d494Suebayasi 6315ecc953bSthorpej return (ateof); 6325ecc953bSthorpej } 6335ecc953bSthorpej 6345ecc953bSthorpej /* 6355ecc953bSthorpej * Return the current line number. If yacc has looked ahead and caused 6365ecc953bSthorpej * us to consume a newline, we have to subtract one. yychar is yacc's 6375ecc953bSthorpej * token lookahead, so we can tell. 6385ecc953bSthorpej */ 639d12b0036Schristos u_short 6405ecc953bSthorpej currentline(void) 6415ecc953bSthorpej { 6425ecc953bSthorpej extern int yychar; 6435ecc953bSthorpej 644d12b0036Schristos return (u_short)(yyline - (yychar == '\n')); 6455ecc953bSthorpej } 646656cdcc8Scube 647656cdcc8Scube static int 648656cdcc8Scube getcurifdef(void) 649656cdcc8Scube { 650656cdcc8Scube char *p = yytext, *q; 651656cdcc8Scube 652c178875fSuwe while (*p && isascii((unsigned char)*p) && !isspace((unsigned char)*p)) 653656cdcc8Scube p++; 654c178875fSuwe while (*p && isascii((unsigned char)*p) && isspace((unsigned char)*p)) 655656cdcc8Scube p++; 656656cdcc8Scube q = p; 657c178875fSuwe while (*q && isascii((unsigned char)*q) && !isspace((unsigned char)*q)) 658656cdcc8Scube q++; 659656cdcc8Scube *q = '\0'; 660656cdcc8Scube 661656cdcc8Scube return ht_lookup(attrtab, intern(p)) != NULL; 662656cdcc8Scube } 663