Standardize on the vi editing directives being on the first line.
[oweals/busybox.git] / scripts / config / symbol.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4  * Released under the terms of the GNU GPL v2.0.
5  */
6
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <regex.h>
11 #include <sys/utsname.h>
12
13 #define LKC_DIRECT_LINK
14 #include "lkc.h"
15
16 struct symbol symbol_yes = {
17         .name = "y",
18         .curr = { "y", yes },
19         .flags = SYMBOL_YES|SYMBOL_VALID,
20 }, symbol_mod = {
21         .name = "m",
22         .curr = { "m", mod },
23         .flags = SYMBOL_MOD|SYMBOL_VALID,
24 }, symbol_no = {
25         .name = "n",
26         .curr = { "n", no },
27         .flags = SYMBOL_NO|SYMBOL_VALID,
28 }, symbol_empty = {
29         .name = "",
30         .curr = { "", no },
31         .flags = SYMBOL_VALID,
32 };
33
34 int sym_change_count;
35 struct symbol *modules_sym;
36 tristate modules_val;
37
38 void sym_add_default(struct symbol *sym, const char *def)
39 {
40         struct property *prop = prop_alloc(P_DEFAULT, sym);
41
42         prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
43 }
44
45 void sym_init(void)
46 {
47         struct symbol *sym;
48         char *p;
49         static bool inited = false;
50
51         if (inited)
52                 return;
53         inited = true;
54
55         sym = sym_lookup("VERSION", 0);
56         sym->type = S_STRING;
57         sym->flags |= SYMBOL_AUTO;
58         p = getenv("VERSION");
59         if (p)
60                 sym_add_default(sym, p);
61
62         sym = sym_lookup("TARGET_ARCH", 0);
63         sym->type = S_STRING;
64         sym->flags |= SYMBOL_AUTO;
65         p = getenv("TARGET_ARCH");
66         if (p)
67                 sym_add_default(sym, p);
68
69 }
70
71 enum symbol_type sym_get_type(struct symbol *sym)
72 {
73         enum symbol_type type = sym->type;
74
75         if (type == S_TRISTATE) {
76                 if (sym_is_choice_value(sym) && sym->visible == yes)
77                         type = S_BOOLEAN;
78                 else if (modules_val == no)
79                         type = S_BOOLEAN;
80         }
81         return type;
82 }
83
84 const char *sym_type_name(enum symbol_type type)
85 {
86         switch (type) {
87         case S_BOOLEAN:
88                 return "boolean";
89         case S_TRISTATE:
90                 return "tristate";
91         case S_INT:
92                 return "integer";
93         case S_HEX:
94                 return "hex";
95         case S_STRING:
96                 return "string";
97         case S_UNKNOWN:
98                 return "unknown";
99         case S_OTHER:
100                 break;
101         }
102         return "???";
103 }
104
105 struct property *sym_get_choice_prop(struct symbol *sym)
106 {
107         struct property *prop;
108
109         for_all_choices(sym, prop)
110                 return prop;
111         return NULL;
112 }
113
114 struct property *sym_get_default_prop(struct symbol *sym)
115 {
116         struct property *prop;
117
118         for_all_defaults(sym, prop) {
119                 prop->visible.tri = expr_calc_value(prop->visible.expr);
120                 if (prop->visible.tri != no)
121                         return prop;
122         }
123         return NULL;
124 }
125
126 struct property *sym_get_range_prop(struct symbol *sym)
127 {
128         struct property *prop;
129
130         for_all_properties(sym, prop, P_RANGE) {
131                 prop->visible.tri = expr_calc_value(prop->visible.expr);
132                 if (prop->visible.tri != no)
133                         return prop;
134         }
135         return NULL;
136 }
137
138 static void sym_calc_visibility(struct symbol *sym)
139 {
140         struct property *prop;
141         tristate tri;
142
143         /* any prompt visible? */
144         tri = no;
145         for_all_prompts(sym, prop) {
146                 prop->visible.tri = expr_calc_value(prop->visible.expr);
147                 tri = E_OR(tri, prop->visible.tri);
148         }
149         if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
150                 tri = yes;
151         if (sym->visible != tri) {
152                 sym->visible = tri;
153                 sym_set_changed(sym);
154         }
155         if (sym_is_choice_value(sym))
156                 return;
157         tri = no;
158         if (sym->rev_dep.expr)
159                 tri = expr_calc_value(sym->rev_dep.expr);
160         if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
161                 tri = yes;
162         if (sym->rev_dep.tri != tri) {
163                 sym->rev_dep.tri = tri;
164                 sym_set_changed(sym);
165         }
166 }
167
168 static struct symbol *sym_calc_choice(struct symbol *sym)
169 {
170         struct symbol *def_sym;
171         struct property *prop;
172         struct expr *e;
173
174         /* is the user choice visible? */
175         def_sym = sym->user.val;
176         if (def_sym) {
177                 sym_calc_visibility(def_sym);
178                 if (def_sym->visible != no)
179                         return def_sym;
180         }
181
182         /* any of the defaults visible? */
183         for_all_defaults(sym, prop) {
184                 prop->visible.tri = expr_calc_value(prop->visible.expr);
185                 if (prop->visible.tri == no)
186                         continue;
187                 def_sym = prop_get_symbol(prop);
188                 sym_calc_visibility(def_sym);
189                 if (def_sym->visible != no)
190                         return def_sym;
191         }
192
193         /* just get the first visible value */
194         prop = sym_get_choice_prop(sym);
195         for (e = prop->expr; e; e = e->left.expr) {
196                 def_sym = e->right.sym;
197                 sym_calc_visibility(def_sym);
198                 if (def_sym->visible != no)
199                         return def_sym;
200         }
201
202         /* no choice? reset tristate value */
203         sym->curr.tri = no;
204         return NULL;
205 }
206
207 void sym_calc_value(struct symbol *sym)
208 {
209         struct symbol_value newval, oldval;
210         struct property *prop;
211         struct expr *e;
212
213         if (!sym)
214                 return;
215
216         if (sym->flags & SYMBOL_VALID)
217                 return;
218         sym->flags |= SYMBOL_VALID;
219
220         oldval = sym->curr;
221
222         switch (sym->type) {
223         case S_INT:
224         case S_HEX:
225         case S_STRING:
226                 newval = symbol_empty.curr;
227                 break;
228         case S_BOOLEAN:
229         case S_TRISTATE:
230                 newval = symbol_no.curr;
231                 break;
232         default:
233                 sym->curr.val = sym->name;
234                 sym->curr.tri = no;
235                 return;
236         }
237         if (!sym_is_choice_value(sym))
238                 sym->flags &= ~SYMBOL_WRITE;
239
240         sym_calc_visibility(sym);
241
242         /* set default if recursively called */
243         sym->curr = newval;
244
245         switch (sym_get_type(sym)) {
246         case S_BOOLEAN:
247         case S_TRISTATE:
248                 if (sym_is_choice_value(sym) && sym->visible == yes) {
249                         prop = sym_get_choice_prop(sym);
250                         newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
251                 } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
252                         sym->flags |= SYMBOL_WRITE;
253                         if (sym_has_value(sym))
254                                 newval.tri = sym->user.tri;
255                         else if (!sym_is_choice(sym)) {
256                                 prop = sym_get_default_prop(sym);
257                                 if (prop)
258                                         newval.tri = expr_calc_value(prop->expr);
259                         }
260                         newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
261                 } else if (!sym_is_choice(sym)) {
262                         prop = sym_get_default_prop(sym);
263                         if (prop) {
264                                 sym->flags |= SYMBOL_WRITE;
265                                 newval.tri = expr_calc_value(prop->expr);
266                         }
267                 }
268                 if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
269                         newval.tri = yes;
270                 break;
271         case S_STRING:
272         case S_HEX:
273         case S_INT:
274                 if (sym->visible != no) {
275                         sym->flags |= SYMBOL_WRITE;
276                         if (sym_has_value(sym)) {
277                                 newval.val = sym->user.val;
278                                 break;
279                         }
280                 }
281                 prop = sym_get_default_prop(sym);
282                 if (prop) {
283                         struct symbol *ds = prop_get_symbol(prop);
284                         if (ds) {
285                                 sym->flags |= SYMBOL_WRITE;
286                                 sym_calc_value(ds);
287                                 newval.val = ds->curr.val;
288                         }
289                 }
290                 break;
291         default:
292                 ;
293         }
294
295         sym->curr = newval;
296         if (sym_is_choice(sym) && newval.tri == yes)
297                 sym->curr.val = sym_calc_choice(sym);
298
299         if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
300                 sym_set_changed(sym);
301         if (modules_sym == sym)
302                 modules_val = modules_sym->curr.tri;
303
304         if (sym_is_choice(sym)) {
305                 int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
306                 prop = sym_get_choice_prop(sym);
307                 for (e = prop->expr; e; e = e->left.expr) {
308                         e->right.sym->flags |= flags;
309                         if (flags & SYMBOL_CHANGED)
310                                 sym_set_changed(e->right.sym);
311                 }
312         }
313 }
314
315 void sym_clear_all_valid(void)
316 {
317         struct symbol *sym;
318         int i;
319
320         for_all_symbols(i, sym)
321                 sym->flags &= ~SYMBOL_VALID;
322         sym_change_count++;
323         if (modules_sym)
324                 sym_calc_value(modules_sym);
325 }
326
327 void sym_set_changed(struct symbol *sym)
328 {
329         struct property *prop;
330
331         sym->flags |= SYMBOL_CHANGED;
332         for (prop = sym->prop; prop; prop = prop->next) {
333                 if (prop->menu)
334                         prop->menu->flags |= MENU_CHANGED;
335         }
336 }
337
338 void sym_set_all_changed(void)
339 {
340         struct symbol *sym;
341         int i;
342
343         for_all_symbols(i, sym)
344                 sym_set_changed(sym);
345 }
346
347 bool sym_tristate_within_range(struct symbol *sym, tristate val)
348 {
349         int type = sym_get_type(sym);
350
351         if (sym->visible == no)
352                 return false;
353
354         if (type != S_BOOLEAN && type != S_TRISTATE)
355                 return false;
356
357         if (type == S_BOOLEAN && val == mod)
358                 return false;
359         if (sym->visible <= sym->rev_dep.tri)
360                 return false;
361         if (sym_is_choice_value(sym) && sym->visible == yes)
362                 return val == yes;
363         return val >= sym->rev_dep.tri && val <= sym->visible;
364 }
365
366 bool sym_set_tristate_value(struct symbol *sym, tristate val)
367 {
368         tristate oldval = sym_get_tristate_value(sym);
369
370         if (oldval != val && !sym_tristate_within_range(sym, val))
371                 return false;
372
373         if (sym->flags & SYMBOL_NEW) {
374                 sym->flags &= ~SYMBOL_NEW;
375                 sym_set_changed(sym);
376         }
377         if (sym_is_choice_value(sym) && val == yes) {
378                 struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
379
380                 cs->user.val = sym;
381                 cs->flags &= ~SYMBOL_NEW;
382         }
383
384         sym->user.tri = val;
385         if (oldval != val) {
386                 sym_clear_all_valid();
387                 if (sym == modules_sym)
388                         sym_set_all_changed();
389         }
390
391         return true;
392 }
393
394 tristate sym_toggle_tristate_value(struct symbol *sym)
395 {
396         tristate oldval, newval;
397
398         oldval = newval = sym_get_tristate_value(sym);
399         do {
400                 switch (newval) {
401                 case no:
402                         newval = mod;
403                         break;
404                 case mod:
405                         newval = yes;
406                         break;
407                 case yes:
408                         newval = no;
409                         break;
410                 }
411                 if (sym_set_tristate_value(sym, newval))
412                         break;
413         } while (oldval != newval);
414         return newval;
415 }
416
417 bool sym_string_valid(struct symbol *sym, const char *str)
418 {
419         signed char ch;
420
421         switch (sym->type) {
422         case S_STRING:
423                 return true;
424         case S_INT:
425                 ch = *str++;
426                 if (ch == '-')
427                         ch = *str++;
428                 if (!isdigit(ch))
429                         return false;
430                 if (ch == '0' && *str != 0)
431                         return false;
432                 while ((ch = *str++)) {
433                         if (!isdigit(ch))
434                                 return false;
435                 }
436                 return true;
437         case S_HEX:
438                 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
439                         str += 2;
440                 ch = *str++;
441                 do {
442                         if (!isxdigit(ch))
443                                 return false;
444                 } while ((ch = *str++));
445                 return true;
446         case S_BOOLEAN:
447         case S_TRISTATE:
448                 switch (str[0]) {
449                 case 'y': case 'Y':
450                 case 'm': case 'M':
451                 case 'n': case 'N':
452                         return true;
453                 }
454                 return false;
455         default:
456                 return false;
457         }
458 }
459
460 bool sym_string_within_range(struct symbol *sym, const char *str)
461 {
462         struct property *prop;
463         int val;
464
465         switch (sym->type) {
466         case S_STRING:
467                 return sym_string_valid(sym, str);
468         case S_INT:
469                 if (!sym_string_valid(sym, str))
470                         return false;
471                 prop = sym_get_range_prop(sym);
472                 if (!prop)
473                         return true;
474                 val = strtol(str, NULL, 10);
475                 return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
476                        val <= strtol(prop->expr->right.sym->name, NULL, 10);
477         case S_HEX:
478                 if (!sym_string_valid(sym, str))
479                         return false;
480                 prop = sym_get_range_prop(sym);
481                 if (!prop)
482                         return true;
483                 val = strtol(str, NULL, 16);
484                 return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
485                        val <= strtol(prop->expr->right.sym->name, NULL, 16);
486         case S_BOOLEAN:
487         case S_TRISTATE:
488                 switch (str[0]) {
489                 case 'y': case 'Y':
490                         return sym_tristate_within_range(sym, yes);
491                 case 'm': case 'M':
492                         return sym_tristate_within_range(sym, mod);
493                 case 'n': case 'N':
494                         return sym_tristate_within_range(sym, no);
495                 }
496                 return false;
497         default:
498                 return false;
499         }
500 }
501
502 bool sym_set_string_value(struct symbol *sym, const char *newval)
503 {
504         const char *oldval;
505         char *val;
506         int size;
507
508         switch (sym->type) {
509         case S_BOOLEAN:
510         case S_TRISTATE:
511                 switch (newval[0]) {
512                 case 'y': case 'Y':
513                         return sym_set_tristate_value(sym, yes);
514                 case 'm': case 'M':
515                         return sym_set_tristate_value(sym, mod);
516                 case 'n': case 'N':
517                         return sym_set_tristate_value(sym, no);
518                 }
519                 return false;
520         default:
521                 ;
522         }
523
524         if (!sym_string_within_range(sym, newval))
525                 return false;
526
527         if (sym->flags & SYMBOL_NEW) {
528                 sym->flags &= ~SYMBOL_NEW;
529                 sym_set_changed(sym);
530         }
531
532         oldval = sym->user.val;
533         size = strlen(newval) + 1;
534         if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
535                 size += 2;
536                 sym->user.val = val = malloc(size);
537                 *val++ = '0';
538                 *val++ = 'x';
539         } else if (!oldval || strcmp(oldval, newval))
540                 sym->user.val = val = malloc(size);
541         else
542                 return true;
543
544         strcpy(val, newval);
545         free((void *)oldval);
546         sym_clear_all_valid();
547
548         return true;
549 }
550
551 const char *sym_get_string_value(struct symbol *sym)
552 {
553         tristate val;
554
555         switch (sym->type) {
556         case S_BOOLEAN:
557         case S_TRISTATE:
558                 val = sym_get_tristate_value(sym);
559                 switch (val) {
560                 case no:
561                         return "n";
562                 case mod:
563                         return "m";
564                 case yes:
565                         return "y";
566                 }
567                 break;
568         default:
569                 ;
570         }
571         return (const char *)sym->curr.val;
572 }
573
574 bool sym_is_changable(struct symbol *sym)
575 {
576         return sym->visible > sym->rev_dep.tri;
577 }
578
579 struct symbol *sym_lookup(const char *name, int isconst)
580 {
581         struct symbol *symbol;
582         const char *ptr;
583         char *new_name;
584         int hash = 0;
585
586         if (name) {
587                 if (name[0] && !name[1]) {
588                         switch (name[0]) {
589                         case 'y': return &symbol_yes;
590                         case 'm': return &symbol_mod;
591                         case 'n': return &symbol_no;
592                         }
593                 }
594                 for (ptr = name; *ptr; ptr++)
595                         hash += *ptr;
596                 hash &= 0xff;
597
598                 for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
599                         if (!strcmp(symbol->name, name)) {
600                                 if ((isconst && symbol->flags & SYMBOL_CONST) ||
601                                     (!isconst && !(symbol->flags & SYMBOL_CONST)))
602                                         return symbol;
603                         }
604                 }
605                 new_name = strdup(name);
606         } else {
607                 new_name = NULL;
608                 hash = 256;
609         }
610
611         symbol = malloc(sizeof(*symbol));
612         memset(symbol, 0, sizeof(*symbol));
613         symbol->name = new_name;
614         symbol->type = S_UNKNOWN;
615         symbol->flags = SYMBOL_NEW;
616         if (isconst)
617                 symbol->flags |= SYMBOL_CONST;
618
619         symbol->next = symbol_hash[hash];
620         symbol_hash[hash] = symbol;
621
622         return symbol;
623 }
624
625 struct symbol *sym_find(const char *name)
626 {
627         struct symbol *symbol = NULL;
628         const char *ptr;
629         int hash = 0;
630
631         if (!name)
632                 return NULL;
633
634         if (name[0] && !name[1]) {
635                 switch (name[0]) {
636                 case 'y': return &symbol_yes;
637                 case 'm': return &symbol_mod;
638                 case 'n': return &symbol_no;
639                 }
640         }
641         for (ptr = name; *ptr; ptr++)
642                 hash += *ptr;
643         hash &= 0xff;
644
645         for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
646                 if (!strcmp(symbol->name, name) &&
647                     !(symbol->flags & SYMBOL_CONST))
648                                 break;
649         }
650
651         return symbol;
652 }
653
654 struct symbol **sym_re_search(const char *pattern)
655 {
656         struct symbol *sym, **sym_arr = NULL;
657         int i, cnt, size;
658         regex_t re;
659
660         cnt = size = 0;
661         /* Skip if empty */
662         if (strlen(pattern) == 0)
663                 return NULL;
664         if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE))
665                 return NULL;
666
667         for_all_symbols(i, sym) {
668                 if (sym->flags & SYMBOL_CONST || !sym->name)
669                         continue;
670                 if (regexec(&re, sym->name, 0, NULL, 0))
671                         continue;
672                 if (cnt + 1 >= size) {
673                         void *tmp = sym_arr;
674                         size += 16;
675                         sym_arr = realloc(sym_arr, size * sizeof(struct symbol *));
676                         if (!sym_arr) {
677                                 free(tmp);
678                                 return NULL;
679                         }
680                 }
681                 sym_arr[cnt++] = sym;
682         }
683         if (sym_arr)
684                 sym_arr[cnt] = NULL;
685         regfree(&re);
686
687         return sym_arr;
688 }
689
690
691 struct symbol *sym_check_deps(struct symbol *sym);
692
693 static struct symbol *sym_check_expr_deps(struct expr *e)
694 {
695         struct symbol *sym;
696
697         if (!e)
698                 return NULL;
699         switch (e->type) {
700         case E_OR:
701         case E_AND:
702                 sym = sym_check_expr_deps(e->left.expr);
703                 if (sym)
704                         return sym;
705                 return sym_check_expr_deps(e->right.expr);
706         case E_NOT:
707                 return sym_check_expr_deps(e->left.expr);
708         case E_EQUAL:
709         case E_UNEQUAL:
710                 sym = sym_check_deps(e->left.sym);
711                 if (sym)
712                         return sym;
713                 return sym_check_deps(e->right.sym);
714         case E_SYMBOL:
715                 return sym_check_deps(e->left.sym);
716         default:
717                 break;
718         }
719         printf("Oops! How to check %d?\n", e->type);
720         return NULL;
721 }
722
723 struct symbol *sym_check_deps(struct symbol *sym)
724 {
725         struct symbol *sym2;
726         struct property *prop;
727
728         if (sym->flags & SYMBOL_CHECK_DONE)
729                 return NULL;
730         if (sym->flags & SYMBOL_CHECK) {
731                 printf("Warning! Found recursive dependency: %s", sym->name);
732                 return sym;
733         }
734
735         sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
736         sym2 = sym_check_expr_deps(sym->rev_dep.expr);
737         if (sym2)
738                 goto out;
739
740         for (prop = sym->prop; prop; prop = prop->next) {
741                 if (prop->type == P_CHOICE || prop->type == P_SELECT)
742                         continue;
743                 sym2 = sym_check_expr_deps(prop->visible.expr);
744                 if (sym2)
745                         goto out;
746                 if (prop->type != P_DEFAULT || sym_is_choice(sym))
747                         continue;
748                 sym2 = sym_check_expr_deps(prop->expr);
749                 if (sym2)
750                         goto out;
751         }
752 out:
753         if (sym2)
754                 printf(" %s", sym->name);
755         sym->flags &= ~SYMBOL_CHECK;
756         return sym2;
757 }
758
759 struct property *prop_alloc(enum prop_type type, struct symbol *sym)
760 {
761         struct property *prop;
762         struct property **propp;
763
764         prop = malloc(sizeof(*prop));
765         memset(prop, 0, sizeof(*prop));
766         prop->type = type;
767         prop->sym = sym;
768         prop->file = current_file;
769         prop->lineno = zconf_lineno();
770
771         /* append property to the prop list of symbol */
772         if (sym) {
773                 for (propp = &sym->prop; *propp; propp = &(*propp)->next)
774                         ;
775                 *propp = prop;
776         }
777
778         return prop;
779 }
780
781 struct symbol *prop_get_symbol(struct property *prop)
782 {
783         if (prop->expr && (prop->expr->type == E_SYMBOL ||
784                            prop->expr->type == E_CHOICE))
785                 return prop->expr->left.sym;
786         return NULL;
787 }
788
789 const char *prop_get_type_name(enum prop_type type)
790 {
791         switch (type) {
792         case P_PROMPT:
793                 return "prompt";
794         case P_COMMENT:
795                 return "comment";
796         case P_MENU:
797                 return "menu";
798         case P_DEFAULT:
799                 return "default";
800         case P_CHOICE:
801                 return "choice";
802         case P_SELECT:
803                 return "select";
804         case P_RANGE:
805                 return "range";
806         case P_UNKNOWN:
807                 break;
808         }
809         return "unknown";
810 }