1%option backup nostdinit noyywrap never-interactive full ecs
2%option 8bit backup nodefault perf-report perf-report
3%x COMMAND HELP STRING PARAM
4%{
5/*
6 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
7 * Released under the terms of the GNU GPL v2.0.
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <unistd.h>
14
15#define LKC_DIRECT_LINK
16#include "lkc.h"
17#include "zconf.tab.h"
18
19#define START_STRSIZE	16
20
21char *text;
22static char *text_ptr;
23static int text_size, text_asize;
24
25struct buffer {
26        struct buffer *parent;
27        YY_BUFFER_STATE state;
28};
29
30struct buffer *current_buf;
31
32static int last_ts, first_ts;
33
34static void zconf_endhelp(void);
35static struct buffer *zconf_endfile(void);
36
37void new_string(void)
38{
39	text = malloc(START_STRSIZE);
40	text_asize = START_STRSIZE;
41	text_ptr = text;
42	text_size = 0;
43	*text_ptr = 0;
44}
45
46void append_string(const char *str, int size)
47{
48	int new_size = text_size + size + 1;
49	if (new_size > text_asize) {
50		text = realloc(text, new_size);
51		text_asize = new_size;
52		text_ptr = text + text_size;
53	}
54	memcpy(text_ptr, str, size);
55	text_ptr += size;
56	text_size += size;
57	*text_ptr = 0;
58}
59
60void alloc_string(const char *str, int size)
61{
62	text = malloc(size + 1);
63	memcpy(text, str, size);
64	text[size] = 0;
65}
66%}
67
68ws	[ \n\t]
69n	[A-Za-z0-9_]
70
71%%
72	int str = 0;
73	int ts, i;
74
75[ \t]*#.*\n	current_file->lineno++;
76[ \t]*#.*
77
78[ \t]*\n	current_file->lineno++; return T_EOL;
79
80[ \t]+	{
81	BEGIN(COMMAND);
82}
83
84.	{
85	unput(yytext[0]);
86	BEGIN(COMMAND);
87}
88
89
90<COMMAND>{
91	"mainmenu"		BEGIN(PARAM); return T_MAINMENU;
92	"menu"			BEGIN(PARAM); return T_MENU;
93	"endmenu"		BEGIN(PARAM); return T_ENDMENU;
94	"source"		BEGIN(PARAM); return T_SOURCE;
95	"choice"		BEGIN(PARAM); return T_CHOICE;
96	"endchoice"		BEGIN(PARAM); return T_ENDCHOICE;
97	"comment"		BEGIN(PARAM); return T_COMMENT;
98	"config"		BEGIN(PARAM); return T_CONFIG;
99	"help"			BEGIN(PARAM); return T_HELP;
100	"if"			BEGIN(PARAM); return T_IF;
101	"endif"			BEGIN(PARAM); return T_ENDIF;
102	"depends"		BEGIN(PARAM); return T_DEPENDS;
103	"requires"		BEGIN(PARAM); return T_REQUIRES;
104	"optional"		BEGIN(PARAM); return T_OPTIONAL;
105	"default"		BEGIN(PARAM); return T_DEFAULT;
106	"prompt"		BEGIN(PARAM); return T_PROMPT;
107	"tristate"		BEGIN(PARAM); return T_TRISTATE;
108	"bool"			BEGIN(PARAM); return T_BOOLEAN;
109	"boolean"		BEGIN(PARAM); return T_BOOLEAN;
110	"int"			BEGIN(PARAM); return T_INT;
111	"hex"			BEGIN(PARAM); return T_HEX;
112	"string"		BEGIN(PARAM); return T_STRING;
113	{n}+	{
114		alloc_string(yytext, yyleng);
115		zconflval.string = text;
116		return T_WORD;
117	}
118	.
119	\n	current_file->lineno++; BEGIN(INITIAL);
120}
121
122<PARAM>{
123	"&&"	return T_AND;
124	"||"	return T_OR;
125	"("	return T_OPEN_PAREN;
126	")"	return T_CLOSE_PAREN;
127	"!"	return T_NOT;
128	"="	return T_EQUAL;
129	"!="	return T_UNEQUAL;
130	"if"	return T_IF;
131	"on"	return T_ON;
132	\"|\'	{
133		str = yytext[0];
134		new_string();
135		BEGIN(STRING);
136	}
137	\n	BEGIN(INITIAL); current_file->lineno++; return T_EOL;
138	---	/* ignore */
139	({n}|[-/.])+	{
140		alloc_string(yytext, yyleng);
141		zconflval.string = text;
142		return T_WORD;
143	}
144	.
145	<<EOF>> {
146		BEGIN(INITIAL);
147	}
148}
149
150<STRING>{
151	[^'"\\\n]+/\n	{
152		append_string(yytext, yyleng);
153		zconflval.string = text;
154		return T_STRING;
155	}
156	[^'"\\\n]+	{
157		append_string(yytext, yyleng);
158	}
159	\\.?/\n	{
160		append_string(yytext+1, yyleng);
161		zconflval.string = text;
162		return T_STRING;
163	}
164	\\.?	{
165		append_string(yytext+1, yyleng);
166	}
167	\'|\"	{
168		if (str == yytext[0]) {
169			BEGIN(PARAM);
170			zconflval.string = text;
171			return T_STRING;
172		} else
173			append_string(yytext, 1);
174	}
175	\n	{
176		printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
177		BEGIN(INITIAL);
178		return T_EOL;
179	}
180	<<EOF>>	{
181		BEGIN(INITIAL);
182	}
183}
184
185<HELP>{
186	[ \t]+	{
187		ts = 0;
188		for (i = 0; i < yyleng; i++) {
189			if (yytext[i] == '\t')
190				ts = (ts & ~7) + 8;
191			else
192				ts++;
193		}
194		last_ts = ts;
195		if (first_ts) {
196			if (ts < first_ts) {
197				zconf_endhelp();
198				return T_HELPTEXT;
199			}
200			ts -= first_ts;
201			while (ts > 8) {
202				append_string("        ", 8);
203				ts -= 8;
204			}
205			append_string("        ", ts);
206		}
207
208	}
209	\n/[^ \t\n] {
210		current_file->lineno++;
211		zconf_endhelp();
212		return T_HELPTEXT;
213	}
214	[ \t]*\n	{
215		current_file->lineno++;
216		append_string("\n", 1);
217	}
218	[^ \t\n].* {
219		append_string(yytext, yyleng);
220		if (!first_ts)
221			first_ts = last_ts;
222	}
223	<<EOF>>	{
224		zconf_endhelp();
225		return T_HELPTEXT;
226	}
227}
228
229<<EOF>>	{
230	if (current_buf) {
231		zconf_endfile();
232		return T_EOF;
233	}
234	fclose(yyin);
235	yyterminate();
236}
237
238%%
239void zconf_starthelp(void)
240{
241	new_string();
242	last_ts = first_ts = 0;
243	BEGIN(HELP);
244}
245
246static void zconf_endhelp(void)
247{
248	zconflval.string = text;
249	BEGIN(INITIAL);
250}
251
252void zconf_initscan(const char *name)
253{
254	yyin = fopen(name, "r");
255	if (!yyin) {
256		printf("can't find file %s\n", name);
257		exit(1);
258	}
259
260	current_buf = malloc(sizeof(*current_buf));
261	memset(current_buf, 0, sizeof(*current_buf));
262
263	current_file = file_lookup(name);
264	current_file->lineno = 1;
265	current_file->flags = FILE_BUSY;
266}
267
268void zconf_nextfile(const char *name)
269{
270	struct file *file = file_lookup(name);
271	struct buffer *buf = malloc(sizeof(*buf));
272	memset(buf, 0, sizeof(*buf));
273
274	current_buf->state = YY_CURRENT_BUFFER;
275	yyin = fopen(name, "r");
276	if (!yyin) {
277		printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
278		exit(1);
279	}
280	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
281	buf->parent = current_buf;
282	current_buf = buf;
283
284	if (file->flags & FILE_BUSY) {
285		printf("recursive scan (%s)?\n", name);
286		exit(1);
287	}
288	if (file->flags & FILE_SCANNED) {
289		printf("file %s already scanned?\n", name);
290		exit(1);
291	}
292	file->flags |= FILE_BUSY;
293	file->lineno = 1;
294	file->parent = current_file;
295	current_file = file;
296}
297
298static struct buffer *zconf_endfile(void)
299{
300	struct buffer *parent;
301
302	current_file->flags |= FILE_SCANNED;
303	current_file->flags &= ~FILE_BUSY;
304	current_file = current_file->parent;
305
306	parent = current_buf->parent;
307	if (parent) {
308		fclose(yyin);
309		yy_delete_buffer(YY_CURRENT_BUFFER);
310		yy_switch_to_buffer(parent->state);
311	}
312	free(current_buf);
313	current_buf = parent;
314
315	return parent;
316}
317
318int zconf_lineno(void)
319{
320	if (current_buf)
321		return current_file->lineno;
322	else
323		return 0;
324}
325
326char *zconf_curname(void)
327{
328	if (current_buf)
329		return current_file->name;
330	else
331		return "<none>";
332}
333