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