1 %option nostdinit noyywrap never-interactive full ecs
2 %option 8bit perf-report perf-report
3 %option noinput
4 %x COMMAND HELP STRING PARAM
5 %{
6 /*
7 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
8 * Released under the terms of the GNU GPL v2.0.
9 */
10
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16
17 #include "lkc.h"
18 #include "expand_env.h"
19
20 #define START_STRSIZE 16
21
22 static struct {
23 struct file *file;
24 int lineno;
25 } current_pos;
26
27 static char *text;
28 static int text_size, text_asize;
29
30 struct buffer {
31 struct buffer *parent;
32 YY_BUFFER_STATE state;
33 };
34
35 struct buffer *current_buf;
36
37 static int last_ts, first_ts;
38
39 static void zconf_endhelp(void);
40 static void zconf_endfile(void);
41
new_string(void)42 static void new_string(void)
43 {
44 text = xmalloc(START_STRSIZE);
45 text_asize = START_STRSIZE;
46 text_size = 0;
47 *text = 0;
48 }
49
append_string(const char * str,int size)50 static void append_string(const char *str, int size)
51 {
52 int new_size = text_size + size + 1;
53 if (new_size > text_asize) {
54 new_size += START_STRSIZE - 1;
55 new_size &= -START_STRSIZE;
56 text = realloc(text, new_size);
57 text_asize = new_size;
58 }
59 memcpy(text + text_size, str, size);
60 text_size += size;
61 text[text_size] = 0;
62 }
63
alloc_string(const char * str,int size)64 static void alloc_string(const char *str, int size)
65 {
66 text = xmalloc(size + 1);
67 memcpy(text, str, size);
68 text[size] = 0;
69 }
70
warn_ignored_character(char chr)71 static void warn_ignored_character(char chr)
72 {
73 fprintf(stderr,
74 "%s:%d:warning: ignoring unsupported character '%c'\n",
75 zconf_curname(), zconf_lineno(), chr);
76 }
77 %}
78
79 n [A-Za-z0-9_-]
80
81 %%
82 int str = 0;
83 int ts, i;
84
85 [ \t]*#.*\n |
86 [ \t]*\n {
87 current_file->lineno++;
88 return T_EOL;
89 }
90 [ \t]*#.*
91
92
93 [ \t]+ {
94 BEGIN(COMMAND);
95 }
96
97 . {
98 unput(yytext[0]);
99 BEGIN(COMMAND);
100 }
101
102
103 <COMMAND>{
104 {n}+ {
105 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
106 BEGIN(PARAM);
107 current_pos.file = current_file;
108 current_pos.lineno = current_file->lineno;
109 if (id && id->flags & TF_COMMAND) {
110 zconflval.id = id;
111 return id->token;
112 }
113 alloc_string(yytext, yyleng);
114 zconflval.string = text;
115 return T_WORD;
116 }
117 [^\r\n] warn_ignored_character(*yytext);
118 \r?\n {
119 BEGIN(INITIAL);
120 current_file->lineno++;
121 return T_EOL;
122 }
123 }
124
125 <PARAM>{
126 "&&" return T_AND;
127 "||" return T_OR;
128 "(" return T_OPEN_PAREN;
129 ")" return T_CLOSE_PAREN;
130 "!" return T_NOT;
131 "=" return T_EQUAL;
132 "!=" return T_UNEQUAL;
133 "<=" return T_LESS_EQUAL;
134 ">=" return T_GREATER_EQUAL;
135 "<" return T_LESS;
136 ">" return T_GREATER;
137 \"|\' {
138 str = yytext[0];
139 new_string();
140 BEGIN(STRING);
141 }
142 \r?\n BEGIN(INITIAL); current_file->lineno++; return T_EOL;
143 ({n}|[/.])+ {
144 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
145 if (id && id->flags & TF_PARAM) {
146 zconflval.id = id;
147 return id->token;
148 }
149 alloc_string(yytext, yyleng);
150 zconflval.string = text;
151 return T_WORD;
152 }
153 #.* /* comment */
154 \\\r?\n current_file->lineno++;
155 [[:blank:]]+
156 . warn_ignored_character(*yytext);
157 <<EOF>> {
158 BEGIN(INITIAL);
159 }
160 }
161
162 <STRING>{
163 [^'"\\\n]+/\n {
164 append_string(yytext, yyleng);
165 zconflval.string = text;
166 return T_WORD_QUOTE;
167 }
168 [^'"\\\n]+ {
169 append_string(yytext, yyleng);
170 }
171 \\.?/\n {
172 append_string(yytext + 1, yyleng - 1);
173 zconflval.string = text;
174 return T_WORD_QUOTE;
175 }
176 \\.? {
177 append_string(yytext + 1, yyleng - 1);
178 }
179 \'|\" {
180 if (str == yytext[0]) {
181 BEGIN(PARAM);
182 zconflval.string = text;
183 return T_WORD_QUOTE;
184 } else
185 append_string(yytext, 1);
186 }
187 \r?\n {
188 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
189 current_file->lineno++;
190 BEGIN(INITIAL);
191 return T_EOL;
192 }
193 <<EOF>> {
194 BEGIN(INITIAL);
195 }
196 }
197
198 <HELP>{
199 [ \t]+ {
200 ts = 0;
201 for (i = 0; i < yyleng; i++) {
202 if (yytext[i] == '\t')
203 ts = (ts & ~7) + 8;
204 else
205 ts++;
206 }
207 last_ts = ts;
208 if (first_ts) {
209 if (ts < first_ts) {
210 zconf_endhelp();
211 return T_HELPTEXT;
212 }
213 ts -= first_ts;
214 while (ts > 8) {
215 append_string(" ", 8);
216 ts -= 8;
217 }
218 append_string(" ", ts);
219 }
220 }
221 [ \t]*\r?\n/[^ \t\r\n] {
222 current_file->lineno++;
223 zconf_endhelp();
224 return T_HELPTEXT;
225 }
226 [ \t]*\r?\n {
227 current_file->lineno++;
228 append_string("\n", 1);
229 }
230 [^ \t\r?\n].* {
231 while (yyleng) {
232 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
233 break;
234 yyleng--;
235 }
236 append_string(yytext, yyleng);
237 if (!first_ts)
238 first_ts = last_ts;
239 }
240 <<EOF>> {
241 zconf_endhelp();
242 return T_HELPTEXT;
243 }
244 }
245
246 <<EOF>> {
247 if (current_file) {
248 zconf_endfile();
249 return T_EOL;
250 }
251 fclose(yyin);
252 yyterminate();
253 }
254
255 %%
256 void zconf_starthelp(void)
257 {
258 new_string();
259 last_ts = first_ts = 0;
260 BEGIN(HELP);
261 }
262
263 static void zconf_endhelp(void)
264 {
265 zconflval.string = text;
266 BEGIN(INITIAL);
267 }
268
269
270 /*
271 * Try to open specified file with following names:
272 * ./name
273 * $(srctree)/name
274 * The latter is used when srctree is separate from objtree
275 * when compiling the kernel.
276 * Return NULL if file is not found.
277 */
278 FILE *zconf_fopen(const char *name)
279 {
280 char *env, fullname[PATH_MAX+1];
281 FILE *f;
282
283 f = fopen(name, "r");
284
285 if (!f && name != NULL && name[0] != '/') {
286 env = getenv(SRCTREE);
287 if (env) {
288 sprintf(fullname, "%s/%s", env, name);
289 f = fopen(fullname, "r");
290 }
291 }
292 return f;
293 }
294
295 void zconf_initscan(const char *name)
296 {
297 yyin = zconf_fopen(name);
298 if (!yyin) {
299 printf("can't find file %s\n", name);
300 exit(1);
301 }
302
303 current_buf = xmalloc(sizeof(*current_buf));
304 memset(current_buf, 0, sizeof(*current_buf));
305
306 current_file = file_lookup(name, false);
307 current_file->lineno = 1;
308 }
309
310 void zconf_nextfile(const char *name, bool relative)
311 {
312 struct file *iter;
313 struct file *file = file_lookup(name, relative);
314 struct buffer *buf = xmalloc(sizeof(*buf));
315 memset(buf, 0, sizeof(*buf));
316
317 current_buf->state = YY_CURRENT_BUFFER;
318 yyin = zconf_fopen(file->name);
319 if (!yyin) {
320 printf("%s:%d: can't open file \"%s\"\n",
321 zconf_curname(), zconf_lineno(), file->name);
322 exit(1);
323 }
324 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
325 buf->parent = current_buf;
326 current_buf = buf;
327
328 for (iter = current_file->parent; iter; iter = iter->parent ) {
329 if (!strcmp(current_file->name,iter->name) ) {
330 printf("%s:%d: recursive inclusion detected. "
331 "Inclusion path:\n current file : '%s'\n",
332 zconf_curname(), zconf_lineno(),
333 zconf_curname());
334 iter = current_file->parent;
335 while (iter && \
336 strcmp(iter->name,current_file->name)) {
337 printf(" included from: '%s:%d'\n",
338 iter->name, iter->lineno-1);
339 iter = iter->parent;
340 }
341 if (iter)
342 printf(" included from: '%s:%d'\n",
343 iter->name, iter->lineno+1);
344 exit(1);
345 }
346 }
347 file->lineno = 1;
348 file->parent = current_file;
349 current_file = file;
350 }
351
352 void zconf_nextfiles(const char *expression, bool relative)
353 {
354 /* Expand environment variables in 'expression' */
355 char* str = expand_environment(expression, zconf_curname(), zconf_lineno());
356
357 /* zconf_nextfile() processes files in LIFO order, so to keep the
358 files in the order provided we need to process the list backwards
359 */
360 if (str != NULL && strlen(str)) {
361 char* pos = str + strlen(str); // start at null terminator
362
363 while (pos != str) {
364 pos--;
365 if(*pos == ' ') {
366 *pos = '\0'; // split buffer into multiple c-strings
367 if (strlen(pos + 1)) {
368 zconf_nextfile(pos + 1, relative);
369 }
370 }
371 }
372
373 if (strlen(str)) { // re-check as first character may have been a space
374 zconf_nextfile(str, relative);
375 }
376 }
377
378 free_expanded(str);
379 }
380
381 static void zconf_endfile(void)
382 {
383 struct buffer *parent;
384
385 current_file = current_file->parent;
386
387 parent = current_buf->parent;
388 if (parent) {
389 fclose(yyin);
390 yy_delete_buffer(YY_CURRENT_BUFFER);
391 yy_switch_to_buffer(parent->state);
392 }
393 free(current_buf);
394 current_buf = parent;
395 }
396
397 int zconf_lineno(void)
398 {
399 return current_pos.lineno;
400 }
401
402 const char *zconf_curname(void)
403 {
404 return current_pos.file ? current_pos.file->name : "<none>";
405 }
406