lang.l revision 134542
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 134542 2004-08-30 23:03:58Z peter $
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	{ "include",	INCLUDE },
79	{ "files", 	FILES },
80	{ 0, 0 },
81};
82
83
84static int endinclude(void);
85int include(const char *, int);
86int kw_lookup(char *);
87unsigned int octal(const char *);
88unsigned int hex(const char *);
89int yyerror(const char *);
90
91%}
92ID	[A-Za-z_][-A-Za-z_0-9]*
93%START TOEOL
94%%
95{ID}		{
96			int i;
97
98			BEGIN 0;
99			if ((i = kw_lookup(yytext)) == -1)
100			{
101				yylval.str = strdup(yytext);
102				return ID;
103			}
104			return i;
105		}
106\\\"[^"]+\\\"	{
107			BEGIN 0;
108			yytext[yyleng-2] = '"';
109			yytext[yyleng-1] = '\0';
110			yylval.str = strdup(yytext + 1);
111			return ID;
112		}
113\"[^"]+\"	{
114			BEGIN 0;
115			yytext[yyleng-1] = '\0';
116			yylval.str = strdup(yytext + 1);
117			return ID;
118		}
119<TOEOL>[^# \t\n]*	{
120			BEGIN 0;
121			yylval.str = strdup(yytext);
122			return ID;
123		}
1240[0-7]*		{
125			yylval.val = octal(yytext);
126			return NUMBER;
127		}
1280x[0-9a-fA-F]+	{
129			yylval.val = hex(yytext);
130			return NUMBER;
131		}
132-?[1-9][0-9]*	{
133			yylval.val = atoi(yytext);
134			return NUMBER;
135		}
136"?"		{
137			yylval.val = -1;
138			return NUMBER;
139		}
140\n/[ \t]	{
141			yyline++;
142		}
143\n		{
144			yyline++;
145			return SEMICOLON;
146		}
147#.*		{	/* Ignored (comment) */;	}
148[ \t\f]*	{	/* Ignored (white space) */;	}
149";"		{	return SEMICOLON;		}
150","		{	return COMMA;			}
151"="		{	BEGIN TOEOL; return EQUALS;	}
152<<EOF>>		{
153			int tok;
154
155			if (inclp == NULL)
156				return YY_NULL;
157			tok = endinclude();
158			if (tok != 0)
159				return tok;
160			/* otherwise continue scanning */
161		}
162.		{	return yytext[0];		}
163
164%%
165/*
166 * kw_lookup
167 *	Look up a string in the keyword table.  Returns a -1 if the
168 *	string is not a keyword otherwise it returns the keyword number
169 */
170
171int
172kw_lookup(char *word)
173{
174	struct kt *kp;
175
176	for (kp = key_words; kp->kt_name != 0; kp++)
177		if (eq(word, kp->kt_name))
178			return kp->kt_val;
179	return -1;
180}
181
182/*
183 * Number conversion routines
184 */
185
186unsigned int
187octal(const char *str)
188{
189	unsigned int num;
190
191	(void) sscanf(str, "%o", &num);
192	return num;
193}
194
195unsigned int
196hex(const char *str)
197{
198	unsigned int num;
199
200	(void) sscanf(str+2, "%x", &num);
201	return num;
202}
203
204
205/*
206 * Open the named file for inclusion at the current point.  Returns 0 on
207 * success (file opened and previous state pushed), nonzero on failure
208 * (fopen failed, complaint made).  The `ateof' parameter controls the
209 * token to be inserted at the end of the include file. If ateof == 0,
210 * then nothing is inserted.
211 */
212int
213include(const char *fname, int ateof)
214{
215	FILE *fp;
216	struct incl *in;
217
218	fp = fopen(fname, "r");
219	if (fp == NULL) {
220		yyerror("cannot open file");
221		return (-1);
222	}
223	in = malloc(sizeof(*in));
224	assert(in != NULL);
225	in->in_prev = inclp;
226	in->in_buf = YY_CURRENT_BUFFER;
227	in->in_fname = yyfile;
228	in->in_lineno = yyline;
229	in->in_ateof = ateof;
230	inclp = in;
231	yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE));
232	yyfile = fname;
233	yyline = 0;
234	return (0);
235}
236
237/*
238 * Terminate the most recent inclusion.
239 */
240static int
241endinclude()
242{
243	struct incl *in;
244	int ateof;
245
246	in = inclp;
247	assert(in != NULL);
248	inclp = in->in_prev;
249	lastfile = yyfile;
250	yy_delete_buffer(YY_CURRENT_BUFFER);
251	(void)fclose(yyin);
252	yy_switch_to_buffer(in->in_buf);
253	yyfile = in->in_fname;
254	yyline = in->in_lineno;
255	ateof  = in->in_ateof;
256	free(in);
257
258	return (ateof);
259}
260