lang.l revision 136429
1%{
2/*-
3 * Copyright (c) 1980, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 *	@(#)lang.l	8.1 (Berkeley) 6/6/93
31 * $FreeBSD: head/usr.sbin/config/lang.l 136429 2004-10-12 13:21:44Z phk $
32 */
33
34#include <assert.h>
35#include <ctype.h>
36#include <string.h>
37#include "y.tab.h"
38#include "config.h"
39
40#define YY_NO_UNPUT
41
42/*
43 * Data for returning to previous files from include files.
44 */
45struct incl {
46	struct	incl *in_prev; 	/* previous includes in effect, if any */
47	YY_BUFFER_STATE in_buf;	/* previous lex state */
48	const	char *in_fname;	/* previous file name */
49	int	in_lineno;	/* previous line number */
50	int	in_ateof;	/* token to insert at EOF */
51};
52static struct	incl *inclp;
53static const	char *lastfile;
54
55/*
56 * Key word table
57 */
58
59struct kt {
60	const char *kt_name;
61	int kt_val;
62} key_words[] = {
63	{ "config",	CONFIG },
64	{ "cpu",	CPU },
65	{ "device",	DEVICE },
66	{ "nodevice",	NODEVICE },
67	{ "env",	ENV },
68	{ "hints",	HINTS },
69	{ "ident",	IDENT },
70	{ "machine",	ARCH }, /* MACHINE is defined in /sys/param.h */
71	{ "makeoptions", MAKEOPTIONS },
72	{ "nomakeoption", NOMAKEOPTION },
73	{ "maxusers",	MAXUSERS },
74	{ "profile",	PROFILE },
75	{ "option",	OPTIONS },
76	{ "options",	OPTIONS },
77	{ "nooption",	NOOPTION },
78	{ "nooptions",	NOOPTION },
79	{ "include",	INCLUDE },
80	{ "files", 	FILES },
81	{ 0, 0 },
82};
83
84
85static int endinclude(void);
86int include(const char *, int);
87int kw_lookup(char *);
88unsigned int octal(const char *);
89unsigned int hex(const char *);
90int yyerror(const char *);
91
92%}
93ID	[A-Za-z_][-A-Za-z_0-9]*
94%START TOEOL
95%%
96{ID}		{
97			int i;
98
99			BEGIN 0;
100			if ((i = kw_lookup(yytext)) == -1)
101			{
102				yylval.str = strdup(yytext);
103				return ID;
104			}
105			return i;
106		}
107\\\"[^"]+\\\"	{
108			BEGIN 0;
109			yytext[yyleng-2] = '"';
110			yytext[yyleng-1] = '\0';
111			yylval.str = strdup(yytext + 1);
112			return ID;
113		}
114\"[^"]+\"	{
115			BEGIN 0;
116			yytext[yyleng-1] = '\0';
117			yylval.str = strdup(yytext + 1);
118			return ID;
119		}
120<TOEOL>[^# \t\n]*	{
121			BEGIN 0;
122			yylval.str = strdup(yytext);
123			return ID;
124		}
1250[0-7]*		{
126			yylval.val = octal(yytext);
127			return NUMBER;
128		}
1290x[0-9a-fA-F]+	{
130			yylval.val = hex(yytext);
131			return NUMBER;
132		}
133-?[1-9][0-9]*	{
134			yylval.val = atoi(yytext);
135			return NUMBER;
136		}
137"?"		{
138			yylval.val = -1;
139			return NUMBER;
140		}
141\n/[ \t]	{
142			yyline++;
143		}
144\n		{
145			yyline++;
146			return SEMICOLON;
147		}
148#.*		{	/* Ignored (comment) */;	}
149[ \t\f]*	{	/* Ignored (white space) */;	}
150";"		{	return SEMICOLON;		}
151","		{	return COMMA;			}
152"="		{	BEGIN TOEOL; return EQUALS;	}
153<<EOF>>		{
154			int tok;
155
156			if (inclp == NULL)
157				return YY_NULL;
158			tok = endinclude();
159			if (tok != 0)
160				return tok;
161			/* otherwise continue scanning */
162		}
163.		{	return yytext[0];		}
164
165%%
166/*
167 * kw_lookup
168 *	Look up a string in the keyword table.  Returns a -1 if the
169 *	string is not a keyword otherwise it returns the keyword number
170 */
171
172int
173kw_lookup(char *word)
174{
175	struct kt *kp;
176
177	for (kp = key_words; kp->kt_name != 0; kp++)
178		if (eq(word, kp->kt_name))
179			return kp->kt_val;
180	return -1;
181}
182
183/*
184 * Number conversion routines
185 */
186
187unsigned int
188octal(const char *str)
189{
190	unsigned int num;
191
192	(void) sscanf(str, "%o", &num);
193	return num;
194}
195
196unsigned int
197hex(const char *str)
198{
199	unsigned int num;
200
201	(void) sscanf(str+2, "%x", &num);
202	return num;
203}
204
205
206/*
207 * Open the named file for inclusion at the current point.  Returns 0 on
208 * success (file opened and previous state pushed), nonzero on failure
209 * (fopen failed, complaint made).  The `ateof' parameter controls the
210 * token to be inserted at the end of the include file. If ateof == 0,
211 * then nothing is inserted.
212 */
213int
214include(const char *fname, int ateof)
215{
216	FILE *fp;
217	struct incl *in;
218
219	fp = fopen(fname, "r");
220	if (fp == NULL) {
221		yyerror("cannot open file");
222		return (-1);
223	}
224	in = malloc(sizeof(*in));
225	assert(in != NULL);
226	in->in_prev = inclp;
227	in->in_buf = YY_CURRENT_BUFFER;
228	in->in_fname = yyfile;
229	in->in_lineno = yyline;
230	in->in_ateof = ateof;
231	inclp = in;
232	yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
233	yyfile = fname;
234	yyline = 0;
235	return (0);
236}
237
238/*
239 * Terminate the most recent inclusion.
240 */
241static int
242endinclude()
243{
244	struct incl *in;
245	int ateof;
246
247	in = inclp;
248	assert(in != NULL);
249	inclp = in->in_prev;
250	lastfile = yyfile;
251	yy_delete_buffer(YY_CURRENT_BUFFER);
252	(void)fclose(yyin);
253	yy_switch_to_buffer(in->in_buf);
254	yyfile = in->in_fname;
255	yyline = in->in_lineno;
256	ateof  = in->in_ateof;
257	free(in);
258
259	return (ateof);
260}
261