1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include "tkparse.h"
25
26struct kconfig * config = NULL;
27struct kconfig * clast = NULL;
28struct kconfig * koption = NULL;
29static int lineno = 0;
30static int menus_seen = 0;
31static char * current_file = NULL;
32static int do_source(char * filename);
33static char * get_string(char *pnt, char ** labl);
34static int choose_number = 0;
35
36
37
38
39
40static char * skip_whitespace(char * pnt)
41{
42 while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
43 return pnt;
44}
45
46
47
48
49
50static struct condition * parse_if(char * pnt)
51{
52 char * opnt;
53 struct condition *list;
54 struct condition *last;
55 struct condition *cpnt;
56 char varname[64];
57 char * pnt1;
58
59 opnt = pnt;
60
61
62
63
64 pnt = skip_whitespace(pnt);
65 if( *pnt != '[' ) return NULL;
66 pnt++;
67 pnt = skip_whitespace(pnt);
68
69 list = last = NULL;
70 while(*pnt && *pnt != ']') {
71
72 pnt = skip_whitespace(pnt);
73 if(*pnt== '\0' || *pnt == ']') break;
74
75
76
77
78
79 cpnt = (struct condition *) malloc(sizeof(struct condition));
80 memset(cpnt, 0, sizeof(struct condition));
81 if( last == NULL )
82 {
83 list = last = cpnt;
84 }
85 else
86 {
87 last->next = cpnt;
88 last = cpnt;
89 }
90
91
92
93
94 if( *pnt == '-' && pnt[1] == 'a' )
95 {
96 cpnt->op = op_and;
97 pnt += 2;
98 continue;
99 }
100
101 if( *pnt == '-' && pnt[1] == 'o' )
102 {
103 cpnt->op = op_or;
104 pnt += 2;
105 continue;
106 }
107
108 if( *pnt == '!' && pnt[1] == '=' )
109 {
110 cpnt->op = op_neq;
111 pnt += 2;
112 continue;
113 }
114
115 if( *pnt == '=')
116 {
117 cpnt->op = op_eq;
118 pnt += 1;
119 continue;
120 }
121
122 if( *pnt == '!')
123 {
124 cpnt->op = op_bang;
125 pnt += 1;
126 continue;
127 }
128
129 if( *pnt != '"' ) goto error;
130 pnt++;
131 if( *pnt == '`' )
132 {
133 cpnt->op = op_shellcmd;
134 pnt1 = varname;
135 pnt++;
136 while(*pnt && *pnt != '`') *pnt1++ = *pnt++;
137 *pnt1++ = '\0';
138 cpnt->variable.str = strdup(varname);
139 if( *pnt == '`' ) pnt++;
140 if( *pnt == '"' ) pnt++;
141 continue;
142 }
143 if( *pnt == '$' )
144 {
145 cpnt->op = op_variable;
146 pnt1 = varname;
147 pnt++;
148 while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
149 *pnt1++ = '\0';
150 cpnt->variable.str = strdup(varname);
151 if( *pnt == '"' ) pnt++;
152 continue;
153 }
154
155 cpnt->op = op_constant;
156 pnt1 = varname;
157 while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
158 *pnt1++ = '\0';
159 cpnt->variable.str = strdup(varname);
160 if( *pnt == '"' ) pnt++;
161 continue;
162 }
163
164 return list;
165
166 error:
167 if(current_file != NULL)
168 fprintf(stderr,
169 "Bad if clause at line %d(%s):%s\n", lineno, current_file, opnt);
170 else
171 fprintf(stderr,
172 "Bad if clause at line %d:%s\n", lineno, opnt);
173 return NULL;
174}
175
176
177
178
179
180
181
182
183static char * get_qstring(char *pnt, char ** labl)
184{
185 char quotechar;
186 char newlabel[1024];
187 char * pnt1;
188 char * pnt2;
189
190 while( *pnt && *pnt != '"' && *pnt != '\'') pnt++;
191 if (*pnt == '\0') return pnt;
192
193 quotechar = *pnt++;
194 pnt1 = newlabel;
195 while(*pnt && *pnt != quotechar && pnt[-1] != '\\')
196 {
197
198
199
200 if( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']')
201 *pnt1++ = '\\';
202
203 *pnt1++ = *pnt++;
204 }
205 *pnt1++ = '\0';
206
207 pnt2 = (char *) malloc(strlen(newlabel) + 1);
208 strcpy(pnt2, newlabel);
209 *labl = pnt2;
210
211
212
213
214 pnt++;
215 pnt = skip_whitespace(pnt);
216 return pnt;
217}
218
219static char * parse_choices(struct kconfig * choice_kcfg, char * pnt)
220{
221 struct kconfig * kcfg;
222 int index = 1;
223
224
225
226
227 while(1)
228 {
229 pnt = skip_whitespace(pnt);
230 if(*pnt == '\0') break;
231
232 kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
233 memset(kcfg, 0, sizeof(struct kconfig));
234 kcfg->tok = tok_choice;
235 if( clast != NULL )
236 {
237 clast->next = kcfg;
238 clast = kcfg;
239 }
240 else
241 {
242 clast = config = kcfg;
243 }
244
245 pnt = get_string(pnt, &kcfg->label);
246 pnt = skip_whitespace(pnt);
247 pnt = get_string(pnt, &kcfg->optionname);
248 kcfg->choice_label = choice_kcfg;
249 kcfg->choice_value = index++;
250 if( strcmp(kcfg->label, choice_kcfg->value) == 0 )
251 choice_kcfg->choice_value = kcfg->choice_value;
252 }
253
254 return pnt;
255}
256
257
258
259
260
261
262
263
264static char * get_string(char *pnt, char ** labl)
265{
266 char newlabel[1024];
267 char * pnt1;
268 char * pnt2;
269
270 if (*pnt == '\0') return pnt;
271
272 pnt1 = newlabel;
273 while(*pnt && *pnt != ' ' && *pnt != '\t')
274 {
275 *pnt1++ = *pnt++;
276 }
277 *pnt1++ = '\0';
278
279 pnt2 = (char *) malloc(strlen(newlabel) + 1);
280 strcpy(pnt2, newlabel);
281 *labl = pnt2;
282
283 if( *pnt ) pnt++;
284 return pnt;
285}
286
287
288
289
290
291
292
293void parse(char * pnt) {
294 enum token tok;
295 struct kconfig * kcfg;
296 char tmpbuf[24],fake_if[1024];
297
298
299
300
301
302 pnt = skip_whitespace(pnt);
303 while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
304 if(! *pnt ) return;
305 if( *pnt == '#' ) return;
306
307
308
309
310 tok = tok_unknown;
311 if (strncmp(pnt, "mainmenu_name", 13) == 0)
312 {
313 tok = tok_menuname;
314 pnt += 13;
315 }
316 else if (strncmp(pnt, "source", 6) == 0)
317 {
318 pnt += 7;
319 pnt = skip_whitespace(pnt);
320 do_source(pnt);
321 return;
322 }
323 else if (strncmp(pnt, "mainmenu_option", 15) == 0)
324 {
325 menus_seen++;
326 tok = tok_menuoption;
327 pnt += 15;
328 }
329 else if (strncmp(pnt, "$MAKE ", 6) == 0)
330 {
331 tok = tok_make;
332 }
333 else if (strncmp(pnt, "comment", 7) == 0)
334 {
335 tok = tok_comment;
336 pnt += 7;
337 }
338 else if (strncmp(pnt, "choice", 6) == 0)
339 {
340 tok = tok_choose;
341 pnt += 6;
342 }
343 else if (strncmp(pnt, "define_bool", 11) == 0)
344 {
345 tok = tok_define;
346 pnt += 11;
347 }
348 else if (strncmp(pnt, "bool", 4) == 0)
349 {
350 tok = tok_bool;
351 pnt += 4;
352 }
353 else if (strncmp(pnt, "tristate", 8) == 0)
354 {
355 tok = tok_tristate;
356 pnt += 8;
357 }
358 else if (strncmp(pnt, "dep_tristate", 12) == 0)
359 {
360 tok = tok_dep_tristate;
361 pnt += 12;
362 }
363 else if (strncmp(pnt, "int", 3) == 0)
364 {
365 tok = tok_int;
366 pnt += 3;
367 }
368 else if (strncmp(pnt, "hex", 3) == 0)
369 {
370 tok = tok_hex;
371 pnt += 3;
372 }
373 else if (strncmp(pnt, "string", 6) == 0)
374 {
375 tok = tok_string;
376 pnt += 6;
377 }
378 else if (strncmp(pnt, "if", 2) == 0)
379 {
380 tok = tok_if;
381 pnt += 2;
382 }
383 else if (strncmp(pnt, "else", 4) == 0)
384 {
385 tok = tok_else;
386 pnt += 4;
387 }
388 else if (strncmp(pnt, "fi", 2) == 0)
389 {
390 tok = tok_fi;
391 pnt += 2;
392 }
393 else if (strncmp(pnt, "endmenu", 7) == 0)
394 {
395 tok = tok_endmenu;
396 pnt += 7;
397 }
398
399 if( tok == tok_unknown)
400 {
401 if( clast != NULL && clast->tok == tok_if
402 && strcmp(pnt,"then") == 0) return;
403 if( current_file != NULL )
404 fprintf(stderr, "unknown command=%s(%s %d)\n", pnt,
405 current_file, lineno);
406 else
407 fprintf(stderr, "unknown command=%s(%d)\n", pnt,lineno);
408 return;
409 }
410
411
412
413
414
415 kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
416 memset(kcfg, 0, sizeof(struct kconfig));
417 kcfg->tok = tok;
418 if( clast != NULL )
419 {
420 clast->next = kcfg;
421 clast = kcfg;
422 }
423 else
424 {
425 clast = config = kcfg;
426 }
427
428 pnt = skip_whitespace(pnt);
429
430
431
432
433
434 switch (tok)
435 {
436 case tok_choose:
437 pnt = get_qstring(pnt, &kcfg->label);
438 pnt = get_qstring(pnt, &kcfg->optionname);
439 pnt = get_string(pnt, &kcfg->value);
440
441
442
443
444 parse_choices(kcfg, kcfg->optionname);
445 free(kcfg->optionname);
446 sprintf(tmpbuf, "tmpvar_%d", choose_number++);
447 kcfg->optionname = strdup(tmpbuf);
448 break;
449 case tok_define:
450 pnt = get_string(pnt, &kcfg->optionname);
451 if(*pnt == 'y' || *pnt == 'Y' ) kcfg->value = "1";
452 if(*pnt == 'n' || *pnt == 'N' ) kcfg->value = "0";
453 if(*pnt == 'm' || *pnt == 'M' ) kcfg->value = "2";
454 break;
455 case tok_menuname:
456 pnt = get_qstring(pnt, &kcfg->label);
457 break;
458 case tok_bool:
459 case tok_tristate:
460 pnt = get_qstring(pnt, &kcfg->label);
461 pnt = get_string(pnt, &kcfg->optionname);
462 break;
463 case tok_int:
464 case tok_hex:
465 case tok_string:
466 pnt = get_qstring(pnt, &kcfg->label);
467 pnt = get_string(pnt, &kcfg->optionname);
468 pnt = get_string(pnt, &kcfg->value);
469 break;
470 case tok_dep_tristate:
471 pnt = get_qstring(pnt, &kcfg->label);
472 pnt = get_string(pnt, &kcfg->optionname);
473 pnt = skip_whitespace(pnt);
474 if( *pnt == '$') pnt++;
475 pnt = get_string(pnt, &kcfg->depend.str);
476
477
478
479
480
481
482
483
484
485
486
487
488
489 sprintf(fake_if,"[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then",
490 kcfg->depend.str,kcfg->depend.str);
491 kcfg->cond = parse_if(fake_if);
492 if(kcfg->cond == NULL )
493 {
494 exit(1);
495 }
496 break;
497 case tok_comment:
498 pnt = get_qstring(pnt, &kcfg->label);
499 if( koption != NULL )
500 {
501 pnt = get_qstring(pnt, &kcfg->label);
502 koption->label = kcfg->label;
503 koption = NULL;
504 }
505 break;
506 case tok_menuoption:
507 if( strncmp(pnt, "next_comment", 12) == 0)
508 {
509 koption = kcfg;
510 }
511 else
512 {
513 pnt = get_qstring(pnt, &kcfg->label);
514 }
515 break;
516 case tok_make:
517 kcfg->value=strdup(pnt);
518 break;
519 case tok_else:
520 case tok_fi:
521 case tok_endmenu:
522 break;
523 case tok_if:
524
525
526
527
528 kcfg->cond = parse_if(pnt);
529 if(kcfg->cond == NULL )
530 {
531 exit(1);
532 }
533 break;
534 default:
535 exit(0);
536 }
537
538 return;
539}
540
541
542
543
544void dump_if(struct condition * cond)
545{
546 printf(" ");
547 while(cond != NULL )
548 {
549 switch(cond->op){
550 case op_eq:
551 printf(" = ");
552 break;
553 case op_bang:
554 printf(" ! ");
555 break;
556 case op_neq:
557 printf(" != ");
558 break;
559 case op_and:
560 printf(" -a ");
561 break;
562 case op_lparen:
563 printf("(");
564 break;
565 case op_rparen:
566 printf(")");
567 break;
568 case op_variable:
569 printf("$%s", cond->variable.str);
570 break;
571 case op_constant:
572 printf("'%s'", cond->variable.str);
573 break;
574 default:
575 break;
576 }
577 cond = cond->next;
578 }
579
580 printf("\n");
581}
582
583static int do_source(char * filename)
584{
585 char buffer[1024];
586 int offset;
587 int old_lineno;
588 char * old_file;
589 char * pnt;
590 FILE * infile;
591
592 if( strcmp(filename, "-") == 0 )
593 infile = stdin;
594 else
595 infile = fopen(filename,"r");
596
597
598
599
600
601 if(!infile) {
602 strcpy (buffer, "../");
603 strcat (buffer, filename);
604 infile = fopen(buffer,"r");
605 }
606
607 if(!infile) {
608 fprintf(stderr,"Unable to open file %s\n", filename);
609 return 1;
610 }
611 old_lineno = lineno;
612 lineno = 0;
613 if( infile != stdin ) {
614 old_file = current_file;
615 current_file = filename;
616 }
617 offset = 0;
618 while(1)
619 {
620 fgets(&buffer[offset], sizeof(buffer) - offset, infile);
621 if(feof(infile)) break;
622
623
624
625
626 pnt = buffer + strlen(buffer) - 1;
627 if( *pnt == '\n') *pnt-- = 0;
628 lineno++;
629 if( *pnt == '\\' )
630 {
631 offset = pnt - buffer;
632 }
633 else
634 {
635 parse(buffer);
636 offset = 0;
637 }
638 }
639 fclose(infile);
640 if( infile != stdin ) {
641 current_file = old_file;
642 }
643 lineno = old_lineno;
644 return 0;
645}
646
647int main(int argc, char * argv[])
648{
649#if 0
650 char buffer[1024];
651 char * pnt;
652 struct kconfig * cfg;
653 int i;
654#endif
655
656
657
658
659 do_source("-");
660
661 if( menus_seen == 0 )
662 {
663 fprintf(stderr,"The config.in file for this platform does not support\n");
664 fprintf(stderr,"menus.\n");
665 exit(1);
666 }
667
668
669
670
671
672
673 fix_conditionals(config);
674
675
676
677
678 dump_tk_script(config);
679
680#if 0
681
682
683
684
685 for(cfg = config; cfg; cfg = cfg->next)
686 {
687
688 if(cfg->cond != NULL && cfg->tok != tok_if)
689 dump_if(cfg->cond);
690
691 switch(cfg->tok)
692 {
693 case tok_menuname:
694 printf("main_menuname ");
695 break;
696 case tok_bool:
697 printf("bool ");
698 break;
699 case tok_tristate:
700 printf("tristate ");
701 break;
702 case tok_dep_tristate:
703 printf("dep_tristate ");
704 break;
705 case tok_int:
706 printf("int ");
707 break;
708 case tok_hex:
709 printf("hex ");
710 break;
711 case tok_string:
712 printf("istring ");
713 break;
714 case tok_comment:
715 printf("comment ");
716 break;
717 case tok_menuoption:
718 printf("menuoption ");
719 break;
720 case tok_else:
721 printf("else");
722 break;
723 case tok_fi:
724 printf("fi");
725 break;
726 case tok_if:
727 printf("if");
728 break;
729 default:
730 }
731
732 switch(cfg->tok)
733 {
734 case tok_menuoption:
735 case tok_comment:
736 case tok_menuname:
737 printf("%s\n", cfg->label);
738 break;
739 case tok_bool:
740 case tok_tristate:
741 case tok_dep_tristate:
742 case tok_int:
743 case tok_hex:
744 case tok_string:
745 printf("%s %s\n", cfg->label, cfg->optionname);
746 break;
747 case tok_if:
748 dump_if(cfg->cond);
749 break;
750 case tok_nop:
751 case tok_endmenu:
752 break;
753 default:
754 printf("\n");
755 }
756 }
757#endif
758
759 return 0;
760
761}
762