lang.l revision 180922
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: head/usr.sbin/config/lang.l 180922 2008-07-28 17:11:57Z obrien $ 321553Srgrimes */ 331553Srgrimes 3479607Sdd#include <assert.h> 351553Srgrimes#include <ctype.h> 366494Sbde#include <string.h> 3716073Sphk#include "y.tab.h" 381553Srgrimes#include "config.h" 391553Srgrimes 4045775Speter#define YY_NO_UNPUT 4145775Speter 421553Srgrimes/* 4379607Sdd * Data for returning to previous files from include files. 4479607Sdd */ 4579607Sddstruct incl { 4679607Sdd struct incl *in_prev; /* previous includes in effect, if any */ 4779607Sdd YY_BUFFER_STATE in_buf; /* previous lex state */ 4879607Sdd const char *in_fname; /* previous file name */ 4979607Sdd int in_lineno; /* previous line number */ 5079607Sdd int in_ateof; /* token to insert at EOF */ 5179607Sdd}; 5279607Sddstatic struct incl *inclp; 5379607Sddstatic const char *lastfile; 5479607Sdd 5579607Sdd/* 561553Srgrimes * Key word table 571553Srgrimes */ 581553Srgrimes 591553Srgrimesstruct kt { 6072684Speter const char *kt_name; 611553Srgrimes int kt_val; 621553Srgrimes} key_words[] = { 6346855Speter { "config", CONFIG }, 641553Srgrimes { "cpu", CPU }, 65152018Sru { "nocpu", NOCPU }, 661553Srgrimes { "device", DEVICE }, 67141615Sdes { "devices", DEVICE }, 68111582Sru { "nodevice", NODEVICE }, 69141615Sdes { "nodevices", NODEVICE }, 7082393Speter { "env", ENV }, 7161640Speter { "hints", HINTS }, 721553Srgrimes { "ident", IDENT }, 7352653Smarcel { "machine", ARCH }, /* MACHINE is defined in /sys/param.h */ 74153063Sru { "makeoption", MAKEOPTIONS }, 751553Srgrimes { "makeoptions", MAKEOPTIONS }, 76111582Sru { "nomakeoption", NOMAKEOPTION }, 77152023Sru { "nomakeoptions", NOMAKEOPTION }, 781553Srgrimes { "maxusers", MAXUSERS }, 7967109Sphk { "profile", PROFILE }, 8048402Speter { "option", OPTIONS }, 811553Srgrimes { "options", OPTIONS }, 82111582Sru { "nooption", NOOPTION }, 83136429Sphk { "nooptions", NOOPTION }, 8479607Sdd { "include", INCLUDE }, 85129073Scognet { "files", FILES }, 861553Srgrimes { 0, 0 }, 871553Srgrimes}; 8829451Scharnier 8929451Scharnier 9079607Sddstatic int endinclude(void); 9179607Sddint include(const char *, int); 9261640Speterint kw_lookup(char *); 9398555Sjmallettunsigned int octal(const char *); 9498555Sjmallettunsigned int hex(const char *); 9579607Sddint yyerror(const char *); 9629451Scharnier 971553Srgrimes%} 9846104SluoqiID [A-Za-z_][-A-Za-z_0-9]* 99180922SobrienPATH [./][-/.%^A-Za-z_0-9]+ 100134542Speter%START TOEOL 1011553Srgrimes%% 102134542Speter{ID} { 1031553Srgrimes int i; 1041553Srgrimes 10546104Sluoqi BEGIN 0; 1061553Srgrimes if ((i = kw_lookup(yytext)) == -1) 1071553Srgrimes { 1086494Sbde yylval.str = strdup(yytext); 1091553Srgrimes return ID; 1101553Srgrimes } 1111553Srgrimes return i; 1121553Srgrimes } 11312772Speter\\\"[^"]+\\\" { 11446104Sluoqi BEGIN 0; 11546104Sluoqi yytext[yyleng-2] = '"'; 11646104Sluoqi yytext[yyleng-1] = '\0'; 11712772Speter yylval.str = strdup(yytext + 1); 11812772Speter return ID; 11912772Speter } 1201553Srgrimes\"[^"]+\" { 12146104Sluoqi BEGIN 0; 12246104Sluoqi yytext[yyleng-1] = '\0'; 1236494Sbde yylval.str = strdup(yytext + 1); 1241553Srgrimes return ID; 1251553Srgrimes } 12648402Speter<TOEOL>[^# \t\n]* { 12746104Sluoqi BEGIN 0; 12846104Sluoqi yylval.str = strdup(yytext); 12946104Sluoqi return ID; 13046104Sluoqi } 1311553Srgrimes0[0-7]* { 1321553Srgrimes yylval.val = octal(yytext); 1331553Srgrimes return NUMBER; 1341553Srgrimes } 1351553Srgrimes0x[0-9a-fA-F]+ { 1361553Srgrimes yylval.val = hex(yytext); 1371553Srgrimes return NUMBER; 1381553Srgrimes } 13946104Sluoqi-?[1-9][0-9]* { 14046021Speter yylval.val = atoi(yytext); 14146021Speter return NUMBER; 14246021Speter } 1431553Srgrimes"?" { 1441553Srgrimes yylval.val = -1; 1451553Srgrimes return NUMBER; 1461553Srgrimes } 1471553Srgrimes\n/[ \t] { 1481553Srgrimes yyline++; 1491553Srgrimes } 1501553Srgrimes\n { 1511553Srgrimes yyline++; 1521553Srgrimes return SEMICOLON; 1531553Srgrimes } 1541553Srgrimes#.* { /* Ignored (comment) */; } 1554242Swollman[ \t\f]* { /* Ignored (white space) */; } 1561553Srgrimes";" { return SEMICOLON; } 1571553Srgrimes"," { return COMMA; } 15846104Sluoqi"=" { BEGIN TOEOL; return EQUALS; } 15979607Sdd<<EOF>> { 16079607Sdd int tok; 16179607Sdd 16279607Sdd if (inclp == NULL) 16379607Sdd return YY_NULL; 16479607Sdd tok = endinclude(); 16579607Sdd if (tok != 0) 16679607Sdd return tok; 16779607Sdd /* otherwise continue scanning */ 16879607Sdd } 169180922Sobrien{PATH} { 170180922Sobrien BEGIN 0; 171180922Sobrien yylval.str = strdup(yytext); 172180922Sobrien return PATH; 173180922Sobrien } 1741553Srgrimes. { return yytext[0]; } 1751553Srgrimes 1761553Srgrimes%% 1771553Srgrimes/* 1781553Srgrimes * kw_lookup 1791553Srgrimes * Look up a string in the keyword table. Returns a -1 if the 1801553Srgrimes * string is not a keyword otherwise it returns the keyword number 1811553Srgrimes */ 1821553Srgrimes 18329451Scharnierint 18461640Speterkw_lookup(char *word) 1851553Srgrimes{ 18661640Speter struct kt *kp; 1871553Srgrimes 1881553Srgrimes for (kp = key_words; kp->kt_name != 0; kp++) 1891553Srgrimes if (eq(word, kp->kt_name)) 1901553Srgrimes return kp->kt_val; 1911553Srgrimes return -1; 1921553Srgrimes} 1931553Srgrimes 1941553Srgrimes/* 1951553Srgrimes * Number conversion routines 1961553Srgrimes */ 1971553Srgrimes 19898555Sjmallettunsigned int 19998555Sjmallettoctal(const char *str) 2001553Srgrimes{ 20198555Sjmallett unsigned int num; 2021553Srgrimes 2031553Srgrimes (void) sscanf(str, "%o", &num); 2041553Srgrimes return num; 2051553Srgrimes} 2061553Srgrimes 20798555Sjmallettunsigned int 20898555Sjmalletthex(const char *str) 2091553Srgrimes{ 21098555Sjmallett unsigned int num; 2111553Srgrimes 2121553Srgrimes (void) sscanf(str+2, "%x", &num); 2131553Srgrimes return num; 2141553Srgrimes} 21579607Sdd 216169507Swkoszekvoid 217169507Swkoszekcfgfile_add(const char *fname) 218169507Swkoszek{ 219169507Swkoszek struct cfgfile *cf; 22079607Sdd 221169507Swkoszek cf = calloc(1, sizeof(*cf)); 222169507Swkoszek assert(cf != NULL); 223169507Swkoszek asprintf(&cf->cfg_path, "%s", fname); 224169507Swkoszek STAILQ_INSERT_TAIL(&cfgfiles, cf, cfg_next); 225169507Swkoszek} 226169507Swkoszek 227169507Swkoszekvoid 228169507Swkoszekcfgfile_removeall(void) 229169507Swkoszek{ 230169507Swkoszek struct cfgfile *cf; 231169507Swkoszek 232169507Swkoszek while (!STAILQ_EMPTY(&cfgfiles)) { 233169507Swkoszek cf = STAILQ_FIRST(&cfgfiles); 234169507Swkoszek STAILQ_REMOVE_HEAD(&cfgfiles, cfg_next); 235169507Swkoszek if (cf->cfg_path != NULL) 236169507Swkoszek free(cf->cfg_path); 237169507Swkoszek free(cf); 238169507Swkoszek } 239169507Swkoszek} 240169507Swkoszek 24179607Sdd/* 24279607Sdd * Open the named file for inclusion at the current point. Returns 0 on 24379607Sdd * success (file opened and previous state pushed), nonzero on failure 24479607Sdd * (fopen failed, complaint made). The `ateof' parameter controls the 24579607Sdd * token to be inserted at the end of the include file. If ateof == 0, 24679607Sdd * then nothing is inserted. 24779607Sdd */ 24879607Sddint 24979607Sddinclude(const char *fname, int ateof) 25079607Sdd{ 25179607Sdd FILE *fp; 25279607Sdd struct incl *in; 253136872Sdes char *fnamebuf; 25479607Sdd 255169507Swkoszek fnamebuf = NULL; 25679607Sdd fp = fopen(fname, "r"); 257136872Sdes if (fp == NULL && fname[0] != '.' && fname[0] != '/') { 258136872Sdes asprintf(&fnamebuf, "../../conf/%s", fname); 259136872Sdes if (fnamebuf != NULL) { 260136872Sdes fp = fopen(fnamebuf, "r"); 261136872Sdes free(fnamebuf); 262136872Sdes } 263136872Sdes } 26479607Sdd if (fp == NULL) { 265136872Sdes yyerror("cannot open included file"); 26679607Sdd return (-1); 26779607Sdd } 268169507Swkoszek cfgfile_add(fnamebuf == NULL ? fname : fnamebuf); 26979607Sdd in = malloc(sizeof(*in)); 27079607Sdd assert(in != NULL); 27179607Sdd in->in_prev = inclp; 27279607Sdd in->in_buf = YY_CURRENT_BUFFER; 27379607Sdd in->in_fname = yyfile; 27479607Sdd in->in_lineno = yyline; 27579607Sdd in->in_ateof = ateof; 27679607Sdd inclp = in; 27779607Sdd yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); 27879607Sdd yyfile = fname; 27979607Sdd yyline = 0; 28079607Sdd return (0); 28179607Sdd} 28279607Sdd 28379607Sdd/* 28479607Sdd * Terminate the most recent inclusion. 28579607Sdd */ 28679607Sddstatic int 28779607Sddendinclude() 28879607Sdd{ 28979607Sdd struct incl *in; 29079607Sdd int ateof; 29179607Sdd 29279607Sdd in = inclp; 29379607Sdd assert(in != NULL); 29479607Sdd inclp = in->in_prev; 29579607Sdd lastfile = yyfile; 29679607Sdd yy_delete_buffer(YY_CURRENT_BUFFER); 29779607Sdd (void)fclose(yyin); 29879607Sdd yy_switch_to_buffer(in->in_buf); 29979607Sdd yyfile = in->in_fname; 30079607Sdd yyline = in->in_lineno; 30179607Sdd ateof = in->in_ateof; 30279607Sdd free(in); 30379607Sdd 30479607Sdd return (ateof); 30579607Sdd} 306