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