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 <limits.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #define LKC_DIRECT_LINK
17 #include "lkc.h"
18
19 #define START_STRSIZE 16
20
21 static struct {
22 struct file *file;
23 int lineno;
24 } current_pos;
25
26 static char *text;
27 static int text_size, text_asize;
28
29 struct buffer {
30 struct buffer *parent;
31 YY_BUFFER_STATE state;
32 };
33
34 struct buffer *current_buf;
35
36 static int last_ts, first_ts;
37
38 static void zconf_endhelp(void);
39 static void zconf_endfile(void);
40
new_string(void)41 void new_string(void)
42 {
43 text = malloc(START_STRSIZE);
44 text_asize = START_STRSIZE;
45 text_size = 0;
46 *text = 0;
47 }
48
append_string(const char * str,int size)49 void append_string(const char *str, int size)
50 {
51 int new_size = text_size + size + 1;
52 if (size > 70) {
53 fprintf (stderr, "%s:%d error: Overlong line\n",
54 current_file->name, current_file->lineno);
55 }
56 if (new_size > text_asize) {
57 new_size += START_STRSIZE - 1;
58 new_size &= -START_STRSIZE;
59 text = realloc(text, new_size);
60 text_asize = new_size;
61 }
62 memcpy(text + text_size, str, size);
63 text_size += size;
64 text[text_size] = 0;
65 }
66
alloc_string(const char * str,int size)67 void alloc_string(const char *str, int size)
68 {
69 text = malloc(size + 1);
70 memcpy(text, str, size);
71 text[size] = 0;
72 }
73 %}
74
75 ws [ \n\t]
76 n [A-Za-z0-9_]
77
78 %%
79 int str = 0;
80 int ts, i;
81
82 [ \t]*#.*\n |
83 [ \t]*\n {
84 current_file->lineno++;
85 return T_EOL;
86 }
87 [ \t]*#.*
88
89
90 [ \t]+ {
91 BEGIN(COMMAND);
92 }
93
94 . {
95 unput(yytext[0]);
96 BEGIN(COMMAND);
97 }
98
99
100 <COMMAND>{
101 {n}+ {
102 struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
103 BEGIN(PARAM);
104 current_pos.file = current_file;
105 current_pos.lineno = current_file->lineno;
106 if (id && id->flags & TF_COMMAND) {
107 zconflval.id = id;
108 return id->token;
109 }
110 alloc_string(yytext, yyleng);
111 zconflval.string = text;
112 return T_WORD;
113 }
114 .
115 \n {
116 BEGIN(INITIAL);
117 current_file->lineno++;
118 return T_EOL;
119 }
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 \"|\' {
131 str = yytext[0];
132 new_string();
133 BEGIN(STRING);
134 }
135 \n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
136 --- /* ignore */
137 ({n}|[-/.])+ {
138 struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
139 if (id && id->flags & TF_PARAM) {
140 zconflval.id = id;
141 return id->token;
142 }
143 alloc_string(yytext, yyleng);
144 zconflval.string = text;
145 return T_WORD;
146 }
147 #.* /* comment */
148 \\\n current_file->lineno++;
149 .
150 <<EOF>> {
151 BEGIN(INITIAL);
152 }
153 }
154
155 <STRING>{
156 [^'"\\\n]+/\n {
157 append_string(yytext, yyleng);
158 zconflval.string = text;
159 return T_WORD_QUOTE;
160 }
161 [^'"\\\n]+ {
162 append_string(yytext, yyleng);
163 }
164 \\.?/\n {
165 append_string(yytext + 1, yyleng - 1);
166 zconflval.string = text;
167 return T_WORD_QUOTE;
168 }
169 \\.? {
170 append_string(yytext + 1, yyleng - 1);
171 }
172 \'|\" {
173 if (str == yytext[0]) {
174 BEGIN(PARAM);
175 zconflval.string = text;
176 return T_WORD_QUOTE;
177 } else
178 append_string(yytext, 1);
179 }
180 \n {
181 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
182 current_file->lineno++;
183 BEGIN(INITIAL);
184 return T_EOL;
185 }
186 <<EOF>> {
187 BEGIN(INITIAL);
188 }
189 }
190
191 <HELP>{
192 [ \t]+ {
193 ts = 0;
194 for (i = 0; i < yyleng; i++) {
195 if (yytext[i] == '\t')
196 ts = (ts & ~7) + 8;
197 else
198 ts++;
199 }
200 last_ts = ts;
201 if (first_ts) {
202 if (ts < first_ts) {
203 zconf_endhelp();
204 return T_HELPTEXT;
205 }
206 ts -= first_ts;
207 while (ts > 8) {
208 append_string(" ", 8);
209 ts -= 8;
210 }
211 append_string(" ", ts);
212 }
213 }
214 [ \t]*\n/[^ \t\n] {
215 current_file->lineno++;
216 zconf_endhelp();
217 return T_HELPTEXT;
218 }
219 [ \t]*\n {
220 current_file->lineno++;
221 append_string("\n", 1);
222 }
223 [^ \t\n].* {
224 append_string(yytext, yyleng);
225 if (!first_ts)
226 first_ts = last_ts;
227 }
228 <<EOF>> {
229 zconf_endhelp();
230 return T_HELPTEXT;
231 }
232 }
233
234 <<EOF>> {
235 if (current_file) {
236 zconf_endfile();
237 return T_EOL;
238 }
239 fclose(yyin);
240 yyterminate();
241 }
242
243 %%
244 void zconf_starthelp(void)
245 {
246 new_string();
247 last_ts = first_ts = 0;
248 BEGIN(HELP);
249 }
250
251 static void zconf_endhelp(void)
252 {
253 zconflval.string = text;
254 BEGIN(INITIAL);
255 }
256
257
258 /*
259 * Try to open specified file with following names:
260 * ./name
261 * $(srctree)/name
262 * The latter is used when srctree is separate from objtree
263 * when compiling the kernel.
264 * Return NULL if file is not found.
265 */
266 FILE *zconf_fopen(const char *name)
267 {
268 char *env;
269 FILE *f;
270
271 f = fopen(name, "r");
272 if (!f && name[0] != '/') {
273 env = getenv(SRCTREE);
274 if (env) {
275 char *fullname = alloca(strlen(env) + strlen(name) + 2);
276 sprintf(fullname, "%s/%s", env, name);
277 f = fopen(fullname, "r");
278 }
279 }
280 return f;
281 }
282
283 void zconf_initscan(const char *name)
284 {
285 yyin = zconf_fopen(name);
286 if (!yyin) {
287 printf("can't find file %s\n", name);
288 exit(1);
289 }
290
291 current_buf = malloc(sizeof(*current_buf));
292 memset(current_buf, 0, sizeof(*current_buf));
293
294 current_file = file_lookup(name);
295 current_file->lineno = 1;
296 current_file->flags = FILE_BUSY;
297 }
298
299 void zconf_nextfile(const char *name)
300 {
301 struct file *file = file_lookup(name);
302 struct buffer *buf = malloc(sizeof(*buf));
303 memset(buf, 0, sizeof(*buf));
304
305 current_buf->state = YY_CURRENT_BUFFER;
306 yyin = zconf_fopen(name);
307 if (!yyin) {
308 printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
309 exit(1);
310 }
311 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
312 buf->parent = current_buf;
313 current_buf = buf;
314
315 if (file->flags & FILE_BUSY) {
316 printf("recursive scan (%s)?\n", name);
317 exit(1);
318 }
319 if (file->flags & FILE_SCANNED) {
320 printf("file %s already scanned?\n", name);
321 exit(1);
322 }
323 file->flags |= FILE_BUSY;
324 file->lineno = 1;
325 file->parent = current_file;
326 current_file = file;
327 }
328
329 static void zconf_endfile(void)
330 {
331 struct buffer *parent;
332
333 current_file->flags |= FILE_SCANNED;
334 current_file->flags &= ~FILE_BUSY;
335 current_file = current_file->parent;
336
337 parent = current_buf->parent;
338 if (parent) {
339 fclose(yyin);
340 yy_delete_buffer(YY_CURRENT_BUFFER);
341 yy_switch_to_buffer(parent->state);
342 }
343 free(current_buf);
344 current_buf = parent;
345 }
346
347 int zconf_lineno(void)
348 {
349 return current_pos.lineno;
350 }
351
352 char *zconf_curname(void)
353 {
354 return current_pos.file ? current_pos.file->name : "<none>";
355 }
356