11553Srgrimes%{ 21553Srgrimes/*- 31553Srgrimes * Copyright (c) 1980, 1993 41553Srgrimes * The Regents of the University of California. All rights reserved. 51553Srgrimes * 61553Srgrimes * Redistribution and use in source and binary forms, with or without 71553Srgrimes * modification, are permitted provided that the following conditions 81553Srgrimes * are met: 91553Srgrimes * 1. Redistributions of source code must retain the above copyright 101553Srgrimes * notice, this list of conditions and the following disclaimer. 111553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121553Srgrimes * notice, this list of conditions and the following disclaimer in the 131553Srgrimes * documentation and/or other materials provided with the distribution. 141553Srgrimes * 4. Neither the name of the University nor the names of its contributors 151553Srgrimes * may be used to endorse or promote products derived from this software 161553Srgrimes * without specific prior written permission. 171553Srgrimes * 181553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 191553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 201553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 211553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 221553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 231553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 241553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 251553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 261553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 271553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 281553Srgrimes * SUCH DAMAGE. 291553Srgrimes * 301553Srgrimes * @(#)lang.l 8.1 (Berkeley) 6/6/93 3152007Speter * $FreeBSD$ 321553Srgrimes */ 331553Srgrimes 3479607Sdd#include <assert.h> 351553Srgrimes#include <ctype.h> 36205880Sru#include <err.h> 376494Sbde#include <string.h> 3816073Sphk#include "y.tab.h" 391553Srgrimes#include "config.h" 401553Srgrimes 411553Srgrimes/* 4279607Sdd * Data for returning to previous files from include files. 4379607Sdd */ 4479607Sddstruct incl { 4579607Sdd struct incl *in_prev; /* previous includes in effect, if any */ 4679607Sdd YY_BUFFER_STATE in_buf; /* previous lex state */ 4779607Sdd const char *in_fname; /* previous file name */ 4879607Sdd int in_lineno; /* previous line number */ 4979607Sdd int in_ateof; /* token to insert at EOF */ 5079607Sdd}; 5179607Sddstatic struct incl *inclp; 5279607Sddstatic const char *lastfile; 5379607Sdd 5479607Sdd/* 551553Srgrimes * Key word table 561553Srgrimes */ 571553Srgrimes 581553Srgrimesstruct kt { 5972684Speter const char *kt_name; 601553Srgrimes int kt_val; 611553Srgrimes} key_words[] = { 6246855Speter { "config", CONFIG }, 631553Srgrimes { "cpu", CPU }, 64152018Sru { "nocpu", NOCPU }, 651553Srgrimes { "device", DEVICE }, 66141615Sdes { "devices", DEVICE }, 67111582Sru { "nodevice", NODEVICE }, 68141615Sdes { "nodevices", NODEVICE }, 6982393Speter { "env", ENV }, 7061640Speter { "hints", HINTS }, 711553Srgrimes { "ident", IDENT }, 7252653Smarcel { "machine", ARCH }, /* MACHINE is defined in /sys/param.h */ 73153063Sru { "makeoption", MAKEOPTIONS }, 741553Srgrimes { "makeoptions", MAKEOPTIONS }, 75111582Sru { "nomakeoption", NOMAKEOPTION }, 76152023Sru { "nomakeoptions", NOMAKEOPTION }, 771553Srgrimes { "maxusers", MAXUSERS }, 7867109Sphk { "profile", PROFILE }, 7948402Speter { "option", OPTIONS }, 801553Srgrimes { "options", OPTIONS }, 81111582Sru { "nooption", NOOPTION }, 82136429Sphk { "nooptions", NOOPTION }, 8379607Sdd { "include", INCLUDE }, 84129073Scognet { "files", FILES }, 851553Srgrimes { 0, 0 }, 861553Srgrimes}; 8729451Scharnier 8829451Scharnier 8979607Sddstatic int endinclude(void); 9079607Sddint include(const char *, int); 9161640Speterint kw_lookup(char *); 9298555Sjmallettunsigned int octal(const char *); 9398555Sjmallettunsigned int hex(const char *); 9479607Sddint yyerror(const char *); 9529451Scharnier 96250926Sjkim#define YY_DECL int yylex(void) 971553Srgrimes%} 98250227Sjkim 99250227Sjkim%option nounput 100250227Sjkim%option noinput 101250227Sjkim 10246104SluoqiID [A-Za-z_][-A-Za-z_0-9]* 103180922SobrienPATH [./][-/.%^A-Za-z_0-9]+ 104134542Speter%START TOEOL 1051553Srgrimes%% 106134542Speter{ID} { 1071553Srgrimes int i; 1081553Srgrimes 10946104Sluoqi BEGIN 0; 1101553Srgrimes if ((i = kw_lookup(yytext)) == -1) 1111553Srgrimes { 1126494Sbde yylval.str = strdup(yytext); 1131553Srgrimes return ID; 1141553Srgrimes } 1151553Srgrimes return i; 1161553Srgrimes } 11712772Speter\\\"[^"]+\\\" { 11846104Sluoqi BEGIN 0; 11946104Sluoqi yytext[yyleng-2] = '"'; 12046104Sluoqi yytext[yyleng-1] = '\0'; 12112772Speter yylval.str = strdup(yytext + 1); 12212772Speter return ID; 12312772Speter } 1241553Srgrimes\"[^"]+\" { 12546104Sluoqi BEGIN 0; 12646104Sluoqi yytext[yyleng-1] = '\0'; 1276494Sbde yylval.str = strdup(yytext + 1); 1281553Srgrimes return ID; 1291553Srgrimes } 13048402Speter<TOEOL>[^# \t\n]* { 13146104Sluoqi BEGIN 0; 13246104Sluoqi yylval.str = strdup(yytext); 13346104Sluoqi return ID; 13446104Sluoqi } 1351553Srgrimes0[0-7]* { 1361553Srgrimes yylval.val = octal(yytext); 1371553Srgrimes return NUMBER; 1381553Srgrimes } 1391553Srgrimes0x[0-9a-fA-F]+ { 1401553Srgrimes yylval.val = hex(yytext); 1411553Srgrimes return NUMBER; 1421553Srgrimes } 14346104Sluoqi-?[1-9][0-9]* { 14446021Speter yylval.val = atoi(yytext); 14546021Speter return NUMBER; 14646021Speter } 1471553Srgrimes"?" { 1481553Srgrimes yylval.val = -1; 1491553Srgrimes return NUMBER; 1501553Srgrimes } 1511553Srgrimes\n/[ \t] { 1521553Srgrimes yyline++; 1531553Srgrimes } 1541553Srgrimes\n { 1551553Srgrimes yyline++; 1561553Srgrimes return SEMICOLON; 1571553Srgrimes } 1581553Srgrimes#.* { /* Ignored (comment) */; } 1594242Swollman[ \t\f]* { /* Ignored (white space) */; } 1601553Srgrimes";" { return SEMICOLON; } 1611553Srgrimes"," { return COMMA; } 16246104Sluoqi"=" { BEGIN TOEOL; return EQUALS; } 163185186Sthompsa"+=" { BEGIN TOEOL; return PLUSEQUALS; } 16479607Sdd<<EOF>> { 16579607Sdd int tok; 16679607Sdd 16779607Sdd if (inclp == NULL) 16879607Sdd return YY_NULL; 16979607Sdd tok = endinclude(); 17079607Sdd if (tok != 0) 17179607Sdd return tok; 17279607Sdd /* otherwise continue scanning */ 17379607Sdd } 174180922Sobrien{PATH} { 175180922Sobrien BEGIN 0; 176180922Sobrien yylval.str = strdup(yytext); 177180922Sobrien return PATH; 178180922Sobrien } 1791553Srgrimes. { return yytext[0]; } 1801553Srgrimes 1811553Srgrimes%% 1821553Srgrimes/* 1831553Srgrimes * kw_lookup 1841553Srgrimes * Look up a string in the keyword table. Returns a -1 if the 1851553Srgrimes * string is not a keyword otherwise it returns the keyword number 1861553Srgrimes */ 1871553Srgrimes 18829451Scharnierint 18961640Speterkw_lookup(char *word) 1901553Srgrimes{ 19161640Speter struct kt *kp; 1921553Srgrimes 1931553Srgrimes for (kp = key_words; kp->kt_name != 0; kp++) 1941553Srgrimes if (eq(word, kp->kt_name)) 1951553Srgrimes return kp->kt_val; 1961553Srgrimes return -1; 1971553Srgrimes} 1981553Srgrimes 1991553Srgrimes/* 2001553Srgrimes * Number conversion routines 2011553Srgrimes */ 2021553Srgrimes 20398555Sjmallettunsigned int 20498555Sjmallettoctal(const char *str) 2051553Srgrimes{ 20698555Sjmallett unsigned int num; 2071553Srgrimes 2081553Srgrimes (void) sscanf(str, "%o", &num); 2091553Srgrimes return num; 2101553Srgrimes} 2111553Srgrimes 21298555Sjmallettunsigned int 21398555Sjmalletthex(const char *str) 2141553Srgrimes{ 21598555Sjmallett unsigned int num; 2161553Srgrimes 2171553Srgrimes (void) sscanf(str+2, "%x", &num); 2181553Srgrimes return num; 2191553Srgrimes} 22079607Sdd 221169507Swkoszekvoid 222169507Swkoszekcfgfile_add(const char *fname) 223169507Swkoszek{ 224169507Swkoszek struct cfgfile *cf; 22579607Sdd 226169507Swkoszek cf = calloc(1, sizeof(*cf)); 227205880Sru if (cf == NULL) 228205880Sru err(EXIT_FAILURE, "calloc"); 229169507Swkoszek assert(cf != NULL); 230169507Swkoszek asprintf(&cf->cfg_path, "%s", fname); 231169507Swkoszek STAILQ_INSERT_TAIL(&cfgfiles, cf, cfg_next); 232169507Swkoszek} 233169507Swkoszek 234169507Swkoszekvoid 235169507Swkoszekcfgfile_removeall(void) 236169507Swkoszek{ 237169507Swkoszek struct cfgfile *cf; 238169507Swkoszek 239169507Swkoszek while (!STAILQ_EMPTY(&cfgfiles)) { 240169507Swkoszek cf = STAILQ_FIRST(&cfgfiles); 241169507Swkoszek STAILQ_REMOVE_HEAD(&cfgfiles, cfg_next); 242169507Swkoszek if (cf->cfg_path != NULL) 243169507Swkoszek free(cf->cfg_path); 244169507Swkoszek free(cf); 245169507Swkoszek } 246169507Swkoszek} 247169507Swkoszek 24879607Sdd/* 24979607Sdd * Open the named file for inclusion at the current point. Returns 0 on 25079607Sdd * success (file opened and previous state pushed), nonzero on failure 25179607Sdd * (fopen failed, complaint made). The `ateof' parameter controls the 25279607Sdd * token to be inserted at the end of the include file. If ateof == 0, 25379607Sdd * then nothing is inserted. 25479607Sdd */ 25579607Sddint 25679607Sddinclude(const char *fname, int ateof) 25779607Sdd{ 25879607Sdd FILE *fp; 25979607Sdd struct incl *in; 260136872Sdes char *fnamebuf; 26179607Sdd 262169507Swkoszek fnamebuf = NULL; 26379607Sdd fp = fopen(fname, "r"); 264136872Sdes if (fp == NULL && fname[0] != '.' && fname[0] != '/') { 265136872Sdes asprintf(&fnamebuf, "../../conf/%s", fname); 266136872Sdes if (fnamebuf != NULL) { 267136872Sdes fp = fopen(fnamebuf, "r"); 268136872Sdes free(fnamebuf); 269136872Sdes } 270136872Sdes } 27179607Sdd if (fp == NULL) { 272136872Sdes yyerror("cannot open included file"); 27379607Sdd return (-1); 27479607Sdd } 275169507Swkoszek cfgfile_add(fnamebuf == NULL ? fname : fnamebuf); 27679607Sdd in = malloc(sizeof(*in)); 27779607Sdd assert(in != NULL); 27879607Sdd in->in_prev = inclp; 27979607Sdd in->in_buf = YY_CURRENT_BUFFER; 28079607Sdd in->in_fname = yyfile; 28179607Sdd in->in_lineno = yyline; 28279607Sdd in->in_ateof = ateof; 28379607Sdd inclp = in; 28479607Sdd yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); 28579607Sdd yyfile = fname; 28679607Sdd yyline = 0; 28779607Sdd return (0); 28879607Sdd} 28979607Sdd 29079607Sdd/* 29179607Sdd * Terminate the most recent inclusion. 29279607Sdd */ 29379607Sddstatic int 294201227Sedendinclude(void) 29579607Sdd{ 29679607Sdd struct incl *in; 29779607Sdd int ateof; 29879607Sdd 29979607Sdd in = inclp; 30079607Sdd assert(in != NULL); 30179607Sdd inclp = in->in_prev; 30279607Sdd lastfile = yyfile; 30379607Sdd yy_delete_buffer(YY_CURRENT_BUFFER); 30479607Sdd (void)fclose(yyin); 30579607Sdd yy_switch_to_buffer(in->in_buf); 30679607Sdd yyfile = in->in_fname; 30779607Sdd yyline = in->in_lineno; 30879607Sdd ateof = in->in_ateof; 30979607Sdd free(in); 31079607Sdd 31179607Sdd return (ateof); 31279607Sdd} 313