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>
37264325Sasomers#include <stdlib.h>
386494Sbde#include <string.h>
3916073Sphk#include "y.tab.h"
401553Srgrimes#include "config.h"
411553Srgrimes
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
97250926Sjkim#define YY_DECL int yylex(void)
981553Srgrimes%}
99250227Sjkim
100250227Sjkim%option nounput
101250227Sjkim%option noinput
102250227Sjkim
10346104SluoqiID	[A-Za-z_][-A-Za-z_0-9]*
104180922SobrienPATH	[./][-/.%^A-Za-z_0-9]+
105134542Speter%START TOEOL
1061553Srgrimes%%
107134542Speter{ID}		{
1081553Srgrimes			int i;
1091553Srgrimes
11046104Sluoqi			BEGIN 0;
1111553Srgrimes			if ((i = kw_lookup(yytext)) == -1)
1121553Srgrimes			{
1136494Sbde				yylval.str = strdup(yytext);
1141553Srgrimes				return ID;
1151553Srgrimes			}
1161553Srgrimes			return i;
1171553Srgrimes		}
11812772Speter\\\"[^"]+\\\"	{
11946104Sluoqi			BEGIN 0;
12046104Sluoqi			yytext[yyleng-2] = '"';
12146104Sluoqi			yytext[yyleng-1] = '\0';
12212772Speter			yylval.str = strdup(yytext + 1);
12312772Speter			return ID;
12412772Speter		}
1251553Srgrimes\"[^"]+\"	{
12646104Sluoqi			BEGIN 0;
12746104Sluoqi			yytext[yyleng-1] = '\0';
1286494Sbde			yylval.str = strdup(yytext + 1);
1291553Srgrimes			return ID;
1301553Srgrimes		}
13148402Speter<TOEOL>[^# \t\n]*	{
13246104Sluoqi			BEGIN 0;
13346104Sluoqi			yylval.str = strdup(yytext);
13446104Sluoqi			return ID;
13546104Sluoqi		}
1361553Srgrimes0[0-7]*		{
1371553Srgrimes			yylval.val = octal(yytext);
1381553Srgrimes			return NUMBER;
1391553Srgrimes		}
1401553Srgrimes0x[0-9a-fA-F]+	{
1411553Srgrimes			yylval.val = hex(yytext);
1421553Srgrimes			return NUMBER;
1431553Srgrimes		}
14446104Sluoqi-?[1-9][0-9]*	{
14546021Speter			yylval.val = atoi(yytext);
14646021Speter			return NUMBER;
14746021Speter		}
1481553Srgrimes"?"		{
1491553Srgrimes			yylval.val = -1;
1501553Srgrimes			return NUMBER;
1511553Srgrimes		}
1521553Srgrimes\n/[ \t]	{
1531553Srgrimes			yyline++;
1541553Srgrimes		}
1551553Srgrimes\n		{
1561553Srgrimes			yyline++;
1571553Srgrimes			return SEMICOLON;
1581553Srgrimes		}
1591553Srgrimes#.*		{	/* Ignored (comment) */;	}
1604242Swollman[ \t\f]*	{	/* Ignored (white space) */;	}
1611553Srgrimes";"		{	return SEMICOLON;		}
1621553Srgrimes","		{	return COMMA;			}
16346104Sluoqi"="		{	BEGIN TOEOL; return EQUALS;	}
164185186Sthompsa"+="		{	BEGIN TOEOL; return PLUSEQUALS;	}
16579607Sdd<<EOF>>		{
16679607Sdd			int tok;
16779607Sdd
16879607Sdd			if (inclp == NULL)
16979607Sdd				return YY_NULL;
17079607Sdd			tok = endinclude();
17179607Sdd			if (tok != 0)
17279607Sdd				return tok;
17379607Sdd			/* otherwise continue scanning */
17479607Sdd		}
175180922Sobrien{PATH}		{
176180922Sobrien			BEGIN 0;
177180922Sobrien			yylval.str = strdup(yytext);
178180922Sobrien			return PATH;
179180922Sobrien		}
1801553Srgrimes.		{	return yytext[0];		}
1811553Srgrimes
1821553Srgrimes%%
1831553Srgrimes/*
1841553Srgrimes * kw_lookup
1851553Srgrimes *	Look up a string in the keyword table.  Returns a -1 if the
1861553Srgrimes *	string is not a keyword otherwise it returns the keyword number
1871553Srgrimes */
1881553Srgrimes
18929451Scharnierint
19061640Speterkw_lookup(char *word)
1911553Srgrimes{
19261640Speter	struct kt *kp;
1931553Srgrimes
1941553Srgrimes	for (kp = key_words; kp->kt_name != 0; kp++)
1951553Srgrimes		if (eq(word, kp->kt_name))
1961553Srgrimes			return kp->kt_val;
1971553Srgrimes	return -1;
1981553Srgrimes}
1991553Srgrimes
2001553Srgrimes/*
2011553Srgrimes * Number conversion routines
2021553Srgrimes */
2031553Srgrimes
20498555Sjmallettunsigned int
20598555Sjmallettoctal(const char *str)
2061553Srgrimes{
20798555Sjmallett	unsigned int num;
2081553Srgrimes
2091553Srgrimes	(void) sscanf(str, "%o", &num);
2101553Srgrimes	return num;
2111553Srgrimes}
2121553Srgrimes
21398555Sjmallettunsigned int
21498555Sjmalletthex(const char *str)
2151553Srgrimes{
21698555Sjmallett	unsigned int num;
2171553Srgrimes
2181553Srgrimes	(void) sscanf(str+2, "%x", &num);
2191553Srgrimes	return num;
2201553Srgrimes}
22179607Sdd
222169507Swkoszekvoid
223169507Swkoszekcfgfile_add(const char *fname)
224169507Swkoszek{
225169507Swkoszek	struct cfgfile *cf;
22679607Sdd
227169507Swkoszek	cf = calloc(1, sizeof(*cf));
228205880Sru	if (cf == NULL)
229205880Sru		err(EXIT_FAILURE, "calloc");
230169507Swkoszek	assert(cf != NULL);
231169507Swkoszek	asprintf(&cf->cfg_path, "%s", fname);
232169507Swkoszek	STAILQ_INSERT_TAIL(&cfgfiles, cf, cfg_next);
233169507Swkoszek}
234169507Swkoszek
235169507Swkoszekvoid
236169507Swkoszekcfgfile_removeall(void)
237169507Swkoszek{
238169507Swkoszek	struct cfgfile *cf;
239169507Swkoszek
240169507Swkoszek	while (!STAILQ_EMPTY(&cfgfiles)) {
241169507Swkoszek		cf = STAILQ_FIRST(&cfgfiles);
242169507Swkoszek		STAILQ_REMOVE_HEAD(&cfgfiles, cfg_next);
243169507Swkoszek		if (cf->cfg_path != NULL)
244169507Swkoszek			free(cf->cfg_path);
245169507Swkoszek		free(cf);
246169507Swkoszek	}
247169507Swkoszek}
248169507Swkoszek
24979607Sdd/*
25079607Sdd * Open the named file for inclusion at the current point.  Returns 0 on
25179607Sdd * success (file opened and previous state pushed), nonzero on failure
25279607Sdd * (fopen failed, complaint made).  The `ateof' parameter controls the
25379607Sdd * token to be inserted at the end of the include file. If ateof == 0,
25479607Sdd * then nothing is inserted.
25579607Sdd */
25679607Sddint
25779607Sddinclude(const char *fname, int ateof)
25879607Sdd{
25979607Sdd	FILE *fp;
26079607Sdd	struct incl *in;
261264325Sasomers	struct includepath* ipath;
262136872Sdes	char *fnamebuf;
26379607Sdd
264169507Swkoszek	fnamebuf = NULL;
26579607Sdd	fp = fopen(fname, "r");
266136872Sdes	if (fp == NULL && fname[0] != '.' && fname[0] != '/') {
267136872Sdes		asprintf(&fnamebuf, "../../conf/%s", fname);
268136872Sdes		if (fnamebuf != NULL) {
269136872Sdes			fp = fopen(fnamebuf, "r");
270136872Sdes			free(fnamebuf);
271136872Sdes		}
272136872Sdes	}
27379607Sdd	if (fp == NULL) {
274264325Sasomers		SLIST_FOREACH(ipath, &includepath, path_next) {
275264325Sasomers			asprintf(&fnamebuf, "%s/%s", ipath->path, fname);
276264325Sasomers			if (fnamebuf != NULL) {
277264325Sasomers				fp = fopen(fnamebuf, "r");
278264325Sasomers				free(fnamebuf);
279264325Sasomers			}
280264325Sasomers			if (fp != NULL)
281264325Sasomers				break;
282264325Sasomers		}
283264325Sasomers	}
284264325Sasomers	if (fp == NULL) {
285136872Sdes		yyerror("cannot open included file");
28679607Sdd		return (-1);
28779607Sdd	}
288169507Swkoszek	cfgfile_add(fnamebuf == NULL ? fname : fnamebuf);
28979607Sdd	in = malloc(sizeof(*in));
29079607Sdd	assert(in != NULL);
29179607Sdd	in->in_prev = inclp;
29279607Sdd	in->in_buf = YY_CURRENT_BUFFER;
29379607Sdd	in->in_fname = yyfile;
29479607Sdd	in->in_lineno = yyline;
29579607Sdd	in->in_ateof = ateof;
29679607Sdd	inclp = in;
29779607Sdd	yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
29879607Sdd	yyfile = fname;
29979607Sdd	yyline = 0;
30079607Sdd	return (0);
30179607Sdd}
30279607Sdd
30379607Sdd/*
30479607Sdd * Terminate the most recent inclusion.
30579607Sdd */
30679607Sddstatic int
307201227Sedendinclude(void)
30879607Sdd{
30979607Sdd	struct incl *in;
31079607Sdd	int ateof;
31179607Sdd
31279607Sdd	in = inclp;
31379607Sdd	assert(in != NULL);
31479607Sdd	inclp = in->in_prev;
31579607Sdd	lastfile = yyfile;
31679607Sdd	yy_delete_buffer(YY_CURRENT_BUFFER);
31779607Sdd	(void)fclose(yyin);
31879607Sdd	yy_switch_to_buffer(in->in_buf);
31979607Sdd	yyfile = in->in_fname;
32079607Sdd	yyline = in->in_lineno;
32179607Sdd	ateof  = in->in_ateof;
32279607Sdd	free(in);
32379607Sdd
32479607Sdd	return (ateof);
32579607Sdd}
326