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>
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
96250926Sjkim#define YY_DECL int yylex(void)
971553Srgrimes%}
98250227Sjkim
99250227Sjkim%option nounput
100250227Sjkim%option noinput
101250227Sjkim
10246104SluoqiID	[A-Za-z_][-A-Za-z_0-9]*
103180922SobrienPATH	[./][-/.%^A-Za-z_0-9]+
104134542Speter%START TOEOL
1051553Srgrimes%%
106134542Speter{ID}		{
1071553Srgrimes			int i;
1081553Srgrimes
10946104Sluoqi			BEGIN 0;
1101553Srgrimes			if ((i = kw_lookup(yytext)) == -1)
1111553Srgrimes			{
1126494Sbde				yylval.str = strdup(yytext);
1131553Srgrimes				return ID;
1141553Srgrimes			}
1151553Srgrimes			return i;
1161553Srgrimes		}
11712772Speter\\\"[^"]+\\\"	{
11846104Sluoqi			BEGIN 0;
11946104Sluoqi			yytext[yyleng-2] = '"';
12046104Sluoqi			yytext[yyleng-1] = '\0';
12112772Speter			yylval.str = strdup(yytext + 1);
12212772Speter			return ID;
12312772Speter		}
1241553Srgrimes\"[^"]+\"	{
12546104Sluoqi			BEGIN 0;
12646104Sluoqi			yytext[yyleng-1] = '\0';
1276494Sbde			yylval.str = strdup(yytext + 1);
1281553Srgrimes			return ID;
1291553Srgrimes		}
13048402Speter<TOEOL>[^# \t\n]*	{
13146104Sluoqi			BEGIN 0;
13246104Sluoqi			yylval.str = strdup(yytext);
13346104Sluoqi			return ID;
13446104Sluoqi		}
1351553Srgrimes0[0-7]*		{
1361553Srgrimes			yylval.val = octal(yytext);
1371553Srgrimes			return NUMBER;
1381553Srgrimes		}
1391553Srgrimes0x[0-9a-fA-F]+	{
1401553Srgrimes			yylval.val = hex(yytext);
1411553Srgrimes			return NUMBER;
1421553Srgrimes		}
14346104Sluoqi-?[1-9][0-9]*	{
14446021Speter			yylval.val = atoi(yytext);
14546021Speter			return NUMBER;
14646021Speter		}
1471553Srgrimes"?"		{
1481553Srgrimes			yylval.val = -1;
1491553Srgrimes			return NUMBER;
1501553Srgrimes		}
1511553Srgrimes\n/[ \t]	{
1521553Srgrimes			yyline++;
1531553Srgrimes		}
1541553Srgrimes\n		{
1551553Srgrimes			yyline++;
1561553Srgrimes			return SEMICOLON;
1571553Srgrimes		}
1581553Srgrimes#.*		{	/* Ignored (comment) */;	}
1594242Swollman[ \t\f]*	{	/* Ignored (white space) */;	}
1601553Srgrimes";"		{	return SEMICOLON;		}
1611553Srgrimes","		{	return COMMA;			}
16246104Sluoqi"="		{	BEGIN TOEOL; return EQUALS;	}
163185186Sthompsa"+="		{	BEGIN TOEOL; return PLUSEQUALS;	}
16479607Sdd<<EOF>>		{
16579607Sdd			int tok;
16679607Sdd
16779607Sdd			if (inclp == NULL)
16879607Sdd				return YY_NULL;
16979607Sdd			tok = endinclude();
17079607Sdd			if (tok != 0)
17179607Sdd				return tok;
17279607Sdd			/* otherwise continue scanning */
17379607Sdd		}
174180922Sobrien{PATH}		{
175180922Sobrien			BEGIN 0;
176180922Sobrien			yylval.str = strdup(yytext);
177180922Sobrien			return PATH;
178180922Sobrien		}
1791553Srgrimes.		{	return yytext[0];		}
1801553Srgrimes
1811553Srgrimes%%
1821553Srgrimes/*
1831553Srgrimes * kw_lookup
1841553Srgrimes *	Look up a string in the keyword table.  Returns a -1 if the
1851553Srgrimes *	string is not a keyword otherwise it returns the keyword number
1861553Srgrimes */
1871553Srgrimes
18829451Scharnierint
18961640Speterkw_lookup(char *word)
1901553Srgrimes{
19161640Speter	struct kt *kp;
1921553Srgrimes
1931553Srgrimes	for (kp = key_words; kp->kt_name != 0; kp++)
1941553Srgrimes		if (eq(word, kp->kt_name))
1951553Srgrimes			return kp->kt_val;
1961553Srgrimes	return -1;
1971553Srgrimes}
1981553Srgrimes
1991553Srgrimes/*
2001553Srgrimes * Number conversion routines
2011553Srgrimes */
2021553Srgrimes
20398555Sjmallettunsigned int
20498555Sjmallettoctal(const char *str)
2051553Srgrimes{
20698555Sjmallett	unsigned int num;
2071553Srgrimes
2081553Srgrimes	(void) sscanf(str, "%o", &num);
2091553Srgrimes	return num;
2101553Srgrimes}
2111553Srgrimes
21298555Sjmallettunsigned int
21398555Sjmalletthex(const char *str)
2141553Srgrimes{
21598555Sjmallett	unsigned int num;
2161553Srgrimes
2171553Srgrimes	(void) sscanf(str+2, "%x", &num);
2181553Srgrimes	return num;
2191553Srgrimes}
22079607Sdd
221169507Swkoszekvoid
222169507Swkoszekcfgfile_add(const char *fname)
223169507Swkoszek{
224169507Swkoszek	struct cfgfile *cf;
22579607Sdd
226169507Swkoszek	cf = calloc(1, sizeof(*cf));
227205880Sru	if (cf == NULL)
228205880Sru		err(EXIT_FAILURE, "calloc");
229169507Swkoszek	assert(cf != NULL);
230169507Swkoszek	asprintf(&cf->cfg_path, "%s", fname);
231169507Swkoszek	STAILQ_INSERT_TAIL(&cfgfiles, cf, cfg_next);
232169507Swkoszek}
233169507Swkoszek
234169507Swkoszekvoid
235169507Swkoszekcfgfile_removeall(void)
236169507Swkoszek{
237169507Swkoszek	struct cfgfile *cf;
238169507Swkoszek
239169507Swkoszek	while (!STAILQ_EMPTY(&cfgfiles)) {
240169507Swkoszek		cf = STAILQ_FIRST(&cfgfiles);
241169507Swkoszek		STAILQ_REMOVE_HEAD(&cfgfiles, cfg_next);
242169507Swkoszek		if (cf->cfg_path != NULL)
243169507Swkoszek			free(cf->cfg_path);
244169507Swkoszek		free(cf);
245169507Swkoszek	}
246169507Swkoszek}
247169507Swkoszek
24879607Sdd/*
24979607Sdd * Open the named file for inclusion at the current point.  Returns 0 on
25079607Sdd * success (file opened and previous state pushed), nonzero on failure
25179607Sdd * (fopen failed, complaint made).  The `ateof' parameter controls the
25279607Sdd * token to be inserted at the end of the include file. If ateof == 0,
25379607Sdd * then nothing is inserted.
25479607Sdd */
25579607Sddint
25679607Sddinclude(const char *fname, int ateof)
25779607Sdd{
25879607Sdd	FILE *fp;
25979607Sdd	struct incl *in;
260136872Sdes	char *fnamebuf;
26179607Sdd
262169507Swkoszek	fnamebuf = NULL;
26379607Sdd	fp = fopen(fname, "r");
264136872Sdes	if (fp == NULL && fname[0] != '.' && fname[0] != '/') {
265136872Sdes		asprintf(&fnamebuf, "../../conf/%s", fname);
266136872Sdes		if (fnamebuf != NULL) {
267136872Sdes			fp = fopen(fnamebuf, "r");
268136872Sdes			free(fnamebuf);
269136872Sdes		}
270136872Sdes	}
27179607Sdd	if (fp == NULL) {
272136872Sdes		yyerror("cannot open included file");
27379607Sdd		return (-1);
27479607Sdd	}
275169507Swkoszek	cfgfile_add(fnamebuf == NULL ? fname : fnamebuf);
27679607Sdd	in = malloc(sizeof(*in));
27779607Sdd	assert(in != NULL);
27879607Sdd	in->in_prev = inclp;
27979607Sdd	in->in_buf = YY_CURRENT_BUFFER;
28079607Sdd	in->in_fname = yyfile;
28179607Sdd	in->in_lineno = yyline;
28279607Sdd	in->in_ateof = ateof;
28379607Sdd	inclp = in;
28479607Sdd	yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
28579607Sdd	yyfile = fname;
28679607Sdd	yyline = 0;
28779607Sdd	return (0);
28879607Sdd}
28979607Sdd
29079607Sdd/*
29179607Sdd * Terminate the most recent inclusion.
29279607Sdd */
29379607Sddstatic int
294201227Sedendinclude(void)
29579607Sdd{
29679607Sdd	struct incl *in;
29779607Sdd	int ateof;
29879607Sdd
29979607Sdd	in = inclp;
30079607Sdd	assert(in != NULL);
30179607Sdd	inclp = in->in_prev;
30279607Sdd	lastfile = yyfile;
30379607Sdd	yy_delete_buffer(YY_CURRENT_BUFFER);
30479607Sdd	(void)fclose(yyin);
30579607Sdd	yy_switch_to_buffer(in->in_buf);
30679607Sdd	yyfile = in->in_fname;
30779607Sdd	yyline = in->in_lineno;
30879607Sdd	ateof  = in->in_ateof;
30979607Sdd	free(in);
31079607Sdd
31179607Sdd	return (ateof);
31279607Sdd}
313