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