lang.l revision 250227
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 250227 2013-05-03 23:51:32Z jkim $ 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 961553Srgrimes%} 97250227Sjkim 98250227Sjkim%option nounput 99250227Sjkim%option noinput 100250227Sjkim 10146104SluoqiID [A-Za-z_][-A-Za-z_0-9]* 102180922SobrienPATH [./][-/.%^A-Za-z_0-9]+ 103134542Speter%START TOEOL 1041553Srgrimes%% 105134542Speter{ID} { 1061553Srgrimes int i; 1071553Srgrimes 10846104Sluoqi BEGIN 0; 1091553Srgrimes if ((i = kw_lookup(yytext)) == -1) 1101553Srgrimes { 1116494Sbde yylval.str = strdup(yytext); 1121553Srgrimes return ID; 1131553Srgrimes } 1141553Srgrimes return i; 1151553Srgrimes } 11612772Speter\\\"[^"]+\\\" { 11746104Sluoqi BEGIN 0; 11846104Sluoqi yytext[yyleng-2] = '"'; 11946104Sluoqi yytext[yyleng-1] = '\0'; 12012772Speter yylval.str = strdup(yytext + 1); 12112772Speter return ID; 12212772Speter } 1231553Srgrimes\"[^"]+\" { 12446104Sluoqi BEGIN 0; 12546104Sluoqi yytext[yyleng-1] = '\0'; 1266494Sbde yylval.str = strdup(yytext + 1); 1271553Srgrimes return ID; 1281553Srgrimes } 12948402Speter<TOEOL>[^# \t\n]* { 13046104Sluoqi BEGIN 0; 13146104Sluoqi yylval.str = strdup(yytext); 13246104Sluoqi return ID; 13346104Sluoqi } 1341553Srgrimes0[0-7]* { 1351553Srgrimes yylval.val = octal(yytext); 1361553Srgrimes return NUMBER; 1371553Srgrimes } 1381553Srgrimes0x[0-9a-fA-F]+ { 1391553Srgrimes yylval.val = hex(yytext); 1401553Srgrimes return NUMBER; 1411553Srgrimes } 14246104Sluoqi-?[1-9][0-9]* { 14346021Speter yylval.val = atoi(yytext); 14446021Speter return NUMBER; 14546021Speter } 1461553Srgrimes"?" { 1471553Srgrimes yylval.val = -1; 1481553Srgrimes return NUMBER; 1491553Srgrimes } 1501553Srgrimes\n/[ \t] { 1511553Srgrimes yyline++; 1521553Srgrimes } 1531553Srgrimes\n { 1541553Srgrimes yyline++; 1551553Srgrimes return SEMICOLON; 1561553Srgrimes } 1571553Srgrimes#.* { /* Ignored (comment) */; } 1584242Swollman[ \t\f]* { /* Ignored (white space) */; } 1591553Srgrimes";" { return SEMICOLON; } 1601553Srgrimes"," { return COMMA; } 16146104Sluoqi"=" { BEGIN TOEOL; return EQUALS; } 162185186Sthompsa"+=" { BEGIN TOEOL; return PLUSEQUALS; } 16379607Sdd<<EOF>> { 16479607Sdd int tok; 16579607Sdd 16679607Sdd if (inclp == NULL) 16779607Sdd return YY_NULL; 16879607Sdd tok = endinclude(); 16979607Sdd if (tok != 0) 17079607Sdd return tok; 17179607Sdd /* otherwise continue scanning */ 17279607Sdd } 173180922Sobrien{PATH} { 174180922Sobrien BEGIN 0; 175180922Sobrien yylval.str = strdup(yytext); 176180922Sobrien return PATH; 177180922Sobrien } 1781553Srgrimes. { return yytext[0]; } 1791553Srgrimes 1801553Srgrimes%% 1811553Srgrimes/* 1821553Srgrimes * kw_lookup 1831553Srgrimes * Look up a string in the keyword table. Returns a -1 if the 1841553Srgrimes * string is not a keyword otherwise it returns the keyword number 1851553Srgrimes */ 1861553Srgrimes 18729451Scharnierint 18861640Speterkw_lookup(char *word) 1891553Srgrimes{ 19061640Speter struct kt *kp; 1911553Srgrimes 1921553Srgrimes for (kp = key_words; kp->kt_name != 0; kp++) 1931553Srgrimes if (eq(word, kp->kt_name)) 1941553Srgrimes return kp->kt_val; 1951553Srgrimes return -1; 1961553Srgrimes} 1971553Srgrimes 1981553Srgrimes/* 1991553Srgrimes * Number conversion routines 2001553Srgrimes */ 2011553Srgrimes 20298555Sjmallettunsigned int 20398555Sjmallettoctal(const char *str) 2041553Srgrimes{ 20598555Sjmallett unsigned int num; 2061553Srgrimes 2071553Srgrimes (void) sscanf(str, "%o", &num); 2081553Srgrimes return num; 2091553Srgrimes} 2101553Srgrimes 21198555Sjmallettunsigned int 21298555Sjmalletthex(const char *str) 2131553Srgrimes{ 21498555Sjmallett unsigned int num; 2151553Srgrimes 2161553Srgrimes (void) sscanf(str+2, "%x", &num); 2171553Srgrimes return num; 2181553Srgrimes} 21979607Sdd 220169507Swkoszekvoid 221169507Swkoszekcfgfile_add(const char *fname) 222169507Swkoszek{ 223169507Swkoszek struct cfgfile *cf; 22479607Sdd 225169507Swkoszek cf = calloc(1, sizeof(*cf)); 226205880Sru if (cf == NULL) 227205880Sru err(EXIT_FAILURE, "calloc"); 228169507Swkoszek assert(cf != NULL); 229169507Swkoszek asprintf(&cf->cfg_path, "%s", fname); 230169507Swkoszek STAILQ_INSERT_TAIL(&cfgfiles, cf, cfg_next); 231169507Swkoszek} 232169507Swkoszek 233169507Swkoszekvoid 234169507Swkoszekcfgfile_removeall(void) 235169507Swkoszek{ 236169507Swkoszek struct cfgfile *cf; 237169507Swkoszek 238169507Swkoszek while (!STAILQ_EMPTY(&cfgfiles)) { 239169507Swkoszek cf = STAILQ_FIRST(&cfgfiles); 240169507Swkoszek STAILQ_REMOVE_HEAD(&cfgfiles, cfg_next); 241169507Swkoszek if (cf->cfg_path != NULL) 242169507Swkoszek free(cf->cfg_path); 243169507Swkoszek free(cf); 244169507Swkoszek } 245169507Swkoszek} 246169507Swkoszek 24779607Sdd/* 24879607Sdd * Open the named file for inclusion at the current point. Returns 0 on 24979607Sdd * success (file opened and previous state pushed), nonzero on failure 25079607Sdd * (fopen failed, complaint made). The `ateof' parameter controls the 25179607Sdd * token to be inserted at the end of the include file. If ateof == 0, 25279607Sdd * then nothing is inserted. 25379607Sdd */ 25479607Sddint 25579607Sddinclude(const char *fname, int ateof) 25679607Sdd{ 25779607Sdd FILE *fp; 25879607Sdd struct incl *in; 259136872Sdes char *fnamebuf; 26079607Sdd 261169507Swkoszek fnamebuf = NULL; 26279607Sdd fp = fopen(fname, "r"); 263136872Sdes if (fp == NULL && fname[0] != '.' && fname[0] != '/') { 264136872Sdes asprintf(&fnamebuf, "../../conf/%s", fname); 265136872Sdes if (fnamebuf != NULL) { 266136872Sdes fp = fopen(fnamebuf, "r"); 267136872Sdes free(fnamebuf); 268136872Sdes } 269136872Sdes } 27079607Sdd if (fp == NULL) { 271136872Sdes yyerror("cannot open included file"); 27279607Sdd return (-1); 27379607Sdd } 274169507Swkoszek cfgfile_add(fnamebuf == NULL ? fname : fnamebuf); 27579607Sdd in = malloc(sizeof(*in)); 27679607Sdd assert(in != NULL); 27779607Sdd in->in_prev = inclp; 27879607Sdd in->in_buf = YY_CURRENT_BUFFER; 27979607Sdd in->in_fname = yyfile; 28079607Sdd in->in_lineno = yyline; 28179607Sdd in->in_ateof = ateof; 28279607Sdd inclp = in; 28379607Sdd yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); 28479607Sdd yyfile = fname; 28579607Sdd yyline = 0; 28679607Sdd return (0); 28779607Sdd} 28879607Sdd 28979607Sdd/* 29079607Sdd * Terminate the most recent inclusion. 29179607Sdd */ 29279607Sddstatic int 293201227Sedendinclude(void) 29479607Sdd{ 29579607Sdd struct incl *in; 29679607Sdd int ateof; 29779607Sdd 29879607Sdd in = inclp; 29979607Sdd assert(in != NULL); 30079607Sdd inclp = in->in_prev; 30179607Sdd lastfile = yyfile; 30279607Sdd yy_delete_buffer(YY_CURRENT_BUFFER); 30379607Sdd (void)fclose(yyin); 30479607Sdd yy_switch_to_buffer(in->in_buf); 30579607Sdd yyfile = in->in_fname; 30679607Sdd yyline = in->in_lineno; 30779607Sdd ateof = in->in_ateof; 30879607Sdd free(in); 30979607Sdd 31079607Sdd return (ateof); 31179607Sdd} 312