diff options
author | Arnaud Lacombe <lacombar@gmail.com> | 2011-05-15 23:42:09 -0400 |
---|---|---|
committer | Michal Marek <mmarek@suse.cz> | 2011-07-01 10:23:27 -0400 |
commit | e54e692ba613c2170c66ce36a3791c009680af08 (patch) | |
tree | 481c7b253cc97a38f2b267ff2f7cf068a50304d4 | |
parent | ec6452a5ec68498221a0ced3443cefd65b08be36 (diff) |
kconfig: introduce specialized printer
Make conf_write_symbol() grammar agnostic to be able to use it from different
code path. These path pass a printer callback which will print a symbol's name
and its value in different format.
conf_write_symbol()'s job become mostly only to prepare a string for the
printer. This avoid to have to pass specialized flag to generic
functions
Signed-off-by: Arnaud Lacombe <lacombar@gmail.com>
[mmarek: rebased on top of de12518 (kconfig: autogenerated config_is_xxx
macro)]
Signed-off-by: Michal Marek <mmarek@suse.cz>
-rw-r--r-- | scripts/kconfig/confdata.c | 342 | ||||
-rw-r--r-- | scripts/kconfig/lkc.h | 5 | ||||
-rw-r--r-- | scripts/kconfig/lkc_proto.h | 1 | ||||
-rw-r--r-- | scripts/kconfig/symbol.c | 46 |
4 files changed, 266 insertions, 128 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index a49cf4f7dca5..be6952c7fb29 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
@@ -422,64 +422,228 @@ int conf_read(const char *name) | |||
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | 424 | ||
425 | /* Write a S_STRING */ | 425 | /* |
426 | static void conf_write_string(bool headerfile, const char *name, | 426 | * Kconfig configuration printer |
427 | const char *str, FILE *out) | 427 | * |
428 | * This printer is used when generating the resulting configuration after | ||
429 | * kconfig invocation and `defconfig' files. Unset symbol might be omitted by | ||
430 | * passing a non-NULL argument to the printer. | ||
431 | * | ||
432 | */ | ||
433 | static void | ||
434 | kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) | ||
435 | { | ||
436 | |||
437 | switch (sym->type) { | ||
438 | case S_BOOLEAN: | ||
439 | case S_TRISTATE: | ||
440 | if (*value == 'n') { | ||
441 | bool skip_unset = (arg != NULL); | ||
442 | |||
443 | if (!skip_unset) | ||
444 | fprintf(fp, "# %s%s is not set\n", | ||
445 | CONFIG_, sym->name); | ||
446 | return; | ||
447 | } | ||
448 | break; | ||
449 | default: | ||
450 | break; | ||
451 | } | ||
452 | |||
453 | fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); | ||
454 | } | ||
455 | |||
456 | static void | ||
457 | kconfig_print_comment(FILE *fp, const char *value, void *arg) | ||
428 | { | 458 | { |
429 | int l; | 459 | const char *p = value; |
430 | if (headerfile) | 460 | size_t l; |
431 | fprintf(out, "#define %s%s \"", CONFIG_, name); | 461 | |
432 | else | 462 | for (;;) { |
433 | fprintf(out, "%s%s=\"", CONFIG_, name); | 463 | l = strcspn(p, "\n"); |
434 | 464 | fprintf(fp, "#"); | |
435 | while (1) { | ||
436 | l = strcspn(str, "\"\\"); | ||
437 | if (l) { | 465 | if (l) { |
438 | xfwrite(str, l, 1, out); | 466 | fprintf(fp, " "); |
439 | str += l; | 467 | fwrite(p, l, 1, fp); |
468 | p += l; | ||
440 | } | 469 | } |
441 | if (!*str) | 470 | fprintf(fp, "\n"); |
471 | if (*p++ == '\0') | ||
442 | break; | 472 | break; |
443 | fprintf(out, "\\%c", *str++); | ||
444 | } | 473 | } |
445 | fputs("\"\n", out); | ||
446 | } | 474 | } |
447 | 475 | ||
448 | static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) | 476 | static struct conf_printer kconfig_printer_cb = |
449 | { | 477 | { |
450 | const char *str; | 478 | .print_symbol = kconfig_print_symbol, |
479 | .print_comment = kconfig_print_comment, | ||
480 | }; | ||
481 | |||
482 | /* | ||
483 | * Header printer | ||
484 | * | ||
485 | * This printer is used when generating the `include/generated/autoconf.h' file. | ||
486 | */ | ||
487 | static void | ||
488 | header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) | ||
489 | { | ||
490 | const char *suffix = ""; | ||
451 | 491 | ||
452 | switch (sym->type) { | 492 | switch (sym->type) { |
453 | case S_BOOLEAN: | 493 | case S_BOOLEAN: |
454 | case S_TRISTATE: | 494 | case S_TRISTATE: |
455 | switch (sym_get_tristate_value(sym)) { | 495 | switch (*value) { |
456 | case no: | 496 | case 'n': |
457 | if (write_no) | 497 | return; |
458 | fprintf(out, "# %s%s is not set\n", | 498 | case 'm': |
459 | CONFIG_, sym->name); | 499 | suffix = "_MODULE"; |
460 | break; | 500 | /* FALLTHROUGH */ |
461 | case mod: | 501 | default: |
462 | fprintf(out, "%s%s=m\n", CONFIG_, sym->name); | 502 | value = "1"; |
463 | break; | ||
464 | case yes: | ||
465 | fprintf(out, "%s%s=y\n", CONFIG_, sym->name); | ||
466 | break; | ||
467 | } | 503 | } |
468 | break; | 504 | break; |
469 | case S_STRING: | 505 | default: |
470 | conf_write_string(false, sym->name, sym_get_string_value(sym), out); | ||
471 | break; | 506 | break; |
472 | case S_HEX: | 507 | } |
473 | case S_INT: | 508 | |
474 | str = sym_get_string_value(sym); | 509 | fprintf(fp, "#define %s%s%s %s\n", |
475 | fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); | 510 | CONFIG_, sym->name, suffix, value); |
511 | } | ||
512 | |||
513 | static void | ||
514 | header_print_comment(FILE *fp, const char *value, void *arg) | ||
515 | { | ||
516 | const char *p = value; | ||
517 | size_t l; | ||
518 | |||
519 | fprintf(fp, "/*\n"); | ||
520 | for (;;) { | ||
521 | l = strcspn(p, "\n"); | ||
522 | fprintf(fp, " *"); | ||
523 | if (l) { | ||
524 | fprintf(fp, " "); | ||
525 | fwrite(p, l, 1, fp); | ||
526 | p += l; | ||
527 | } | ||
528 | fprintf(fp, "\n"); | ||
529 | if (*p++ == '\0') | ||
530 | break; | ||
531 | } | ||
532 | fprintf(fp, " */\n"); | ||
533 | } | ||
534 | |||
535 | static struct conf_printer header_printer_cb = | ||
536 | { | ||
537 | .print_symbol = header_print_symbol, | ||
538 | .print_comment = header_print_comment, | ||
539 | }; | ||
540 | |||
541 | /* | ||
542 | * Function-style header printer | ||
543 | * | ||
544 | * This printer is used to generate the config_is_xxx() function-style macros | ||
545 | * in `include/generated/autoconf.h' | ||
546 | */ | ||
547 | static void | ||
548 | header_function_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) | ||
549 | { | ||
550 | int val = 0; | ||
551 | char c; | ||
552 | char *tmp, *d; | ||
553 | |||
554 | switch (sym->type) { | ||
555 | case S_BOOLEAN: | ||
556 | case S_TRISTATE: | ||
476 | break; | 557 | break; |
558 | default: | ||
559 | return; | ||
560 | } | ||
561 | if (*value == 'm') | ||
562 | val = 2; | ||
563 | else if (*value == 'y') | ||
564 | val = 1; | ||
565 | |||
566 | d = strdup(CONFIG_); | ||
567 | tmp = d; | ||
568 | while ((c = *d)) { | ||
569 | *d = tolower(c); | ||
570 | d++; | ||
571 | } | ||
572 | |||
573 | fprintf(fp, "#define %sis_", tmp); | ||
574 | free(tmp); | ||
575 | |||
576 | d = strdup(sym->name); | ||
577 | tmp = d; | ||
578 | while ((c = *d)) { | ||
579 | *d = tolower(c); | ||
580 | d++; | ||
581 | } | ||
582 | fprintf(fp, "%s%s() %d\n", tmp, (val > 1) ? "_module" : "", | ||
583 | val ? 1 : 0); | ||
584 | free(tmp); | ||
585 | } | ||
586 | |||
587 | static struct conf_printer header_function_printer_cb = | ||
588 | { | ||
589 | .print_symbol = header_function_print_symbol, | ||
590 | }; | ||
591 | |||
592 | |||
593 | /* | ||
594 | * Tristate printer | ||
595 | * | ||
596 | * This printer is used when generating the `include/config/tristate.conf' file. | ||
597 | */ | ||
598 | static void | ||
599 | tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) | ||
600 | { | ||
601 | |||
602 | if (sym->type == S_TRISTATE && *value != 'n') | ||
603 | fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); | ||
604 | } | ||
605 | |||
606 | static struct conf_printer tristate_printer_cb = | ||
607 | { | ||
608 | .print_symbol = tristate_print_symbol, | ||
609 | .print_comment = kconfig_print_comment, | ||
610 | }; | ||
611 | |||
612 | static void conf_write_symbol(FILE *fp, struct symbol *sym, | ||
613 | struct conf_printer *printer, void *printer_arg) | ||
614 | { | ||
615 | const char *str; | ||
616 | |||
617 | switch (sym->type) { | ||
477 | case S_OTHER: | 618 | case S_OTHER: |
478 | case S_UNKNOWN: | 619 | case S_UNKNOWN: |
479 | break; | 620 | break; |
621 | case S_STRING: | ||
622 | str = sym_get_string_value(sym); | ||
623 | str = sym_escape_string_value(str); | ||
624 | printer->print_symbol(fp, sym, str, printer_arg); | ||
625 | free((void *)str); | ||
626 | break; | ||
627 | default: | ||
628 | str = sym_get_string_value(sym); | ||
629 | printer->print_symbol(fp, sym, str, printer_arg); | ||
480 | } | 630 | } |
481 | } | 631 | } |
482 | 632 | ||
633 | static void | ||
634 | conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) | ||
635 | { | ||
636 | char buf[256]; | ||
637 | |||
638 | snprintf(buf, sizeof(buf), | ||
639 | "\n" | ||
640 | "Automatically generated file; DO NOT EDIT.\n" | ||
641 | "%s\n", | ||
642 | rootmenu.prompt->text); | ||
643 | |||
644 | printer->print_comment(fp, buf, printer_arg); | ||
645 | } | ||
646 | |||
483 | /* | 647 | /* |
484 | * Write out a minimal config. | 648 | * Write out a minimal config. |
485 | * All values that has default values are skipped as this is redundant. | 649 | * All values that has default values are skipped as this is redundant. |
@@ -536,7 +700,7 @@ int conf_write_defconfig(const char *filename) | |||
536 | goto next_menu; | 700 | goto next_menu; |
537 | } | 701 | } |
538 | } | 702 | } |
539 | conf_write_symbol(sym, out, true); | 703 | conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); |
540 | } | 704 | } |
541 | next_menu: | 705 | next_menu: |
542 | if (menu->list != NULL) { | 706 | if (menu->list != NULL) { |
@@ -601,11 +765,7 @@ int conf_write(const char *name) | |||
601 | if (!out) | 765 | if (!out) |
602 | return 1; | 766 | return 1; |
603 | 767 | ||
604 | fprintf(out, _("#\n" | 768 | conf_write_heading(out, &kconfig_printer_cb, NULL); |
605 | "# Automatically generated make config: don't edit\n" | ||
606 | "# %s\n" | ||
607 | "#\n"), | ||
608 | rootmenu.prompt->text); | ||
609 | 769 | ||
610 | if (!conf_get_changed()) | 770 | if (!conf_get_changed()) |
611 | sym_clear_all_valid(); | 771 | sym_clear_all_valid(); |
@@ -626,8 +786,8 @@ int conf_write(const char *name) | |||
626 | if (!(sym->flags & SYMBOL_WRITE)) | 786 | if (!(sym->flags & SYMBOL_WRITE)) |
627 | goto next; | 787 | goto next; |
628 | sym->flags &= ~SYMBOL_WRITE; | 788 | sym->flags &= ~SYMBOL_WRITE; |
629 | /* Write config symbol to file */ | 789 | |
630 | conf_write_symbol(sym, out, true); | 790 | conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); |
631 | } | 791 | } |
632 | 792 | ||
633 | next: | 793 | next: |
@@ -773,33 +933,9 @@ out: | |||
773 | return res; | 933 | return res; |
774 | } | 934 | } |
775 | 935 | ||
776 | static void conf_write_function_autoconf(FILE *out, char* conf, char* name, | ||
777 | int val) | ||
778 | { | ||
779 | char c; | ||
780 | char *tmp, *d; | ||
781 | |||
782 | d = strdup(conf); | ||
783 | tmp = d; | ||
784 | while ((c = *conf++)) | ||
785 | *d++ = tolower(c); | ||
786 | |||
787 | fprintf(out, "#define %sis_", tmp); | ||
788 | free(tmp); | ||
789 | |||
790 | d = strdup(name); | ||
791 | tmp = d; | ||
792 | while ((c = *name++)) | ||
793 | *d++ = tolower(c); | ||
794 | fprintf(out, "%s%s() %d\n", tmp, (val > 1) ? "_module" : "", | ||
795 | val ? 1 : 0); | ||
796 | free(tmp); | ||
797 | } | ||
798 | |||
799 | int conf_write_autoconf(void) | 936 | int conf_write_autoconf(void) |
800 | { | 937 | { |
801 | struct symbol *sym; | 938 | struct symbol *sym; |
802 | const char *str; | ||
803 | const char *name; | 939 | const char *name; |
804 | FILE *out, *tristate, *out_h; | 940 | FILE *out, *tristate, *out_h; |
805 | int i; | 941 | int i; |
@@ -828,72 +964,24 @@ int conf_write_autoconf(void) | |||
828 | return 1; | 964 | return 1; |
829 | } | 965 | } |
830 | 966 | ||
831 | fprintf(out, "#\n" | 967 | conf_write_heading(out, &kconfig_printer_cb, NULL); |
832 | "# Automatically generated make config: don't edit\n" | 968 | |
833 | "# %s\n" | 969 | conf_write_heading(tristate, &tristate_printer_cb, NULL); |
834 | "#\n", | 970 | |
835 | rootmenu.prompt->text); | 971 | conf_write_heading(out_h, &header_printer_cb, NULL); |
836 | fprintf(tristate, "#\n" | ||
837 | "# Automatically generated - do not edit\n" | ||
838 | "\n"); | ||
839 | fprintf(out_h, "/*\n" | ||
840 | " * Automatically generated C config: don't edit\n" | ||
841 | " * %s\n" | ||
842 | " */\n", | ||
843 | rootmenu.prompt->text); | ||
844 | 972 | ||
845 | for_all_symbols(i, sym) { | 973 | for_all_symbols(i, sym) { |
846 | int fct_val = 0; | ||
847 | sym_calc_value(sym); | 974 | sym_calc_value(sym); |
848 | if (!(sym->flags & SYMBOL_WRITE) || !sym->name) | 975 | if (!(sym->flags & SYMBOL_WRITE) || !sym->name) |
849 | continue; | 976 | continue; |
850 | 977 | ||
851 | /* write symbol to config file */ | 978 | /* write symbol to auto.conf, tristate and header files */ |
852 | conf_write_symbol(sym, out, false); | 979 | conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); |
853 | 980 | ||
854 | /* update autoconf and tristate files */ | 981 | conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); |
855 | switch (sym->type) { | 982 | |
856 | case S_BOOLEAN: | 983 | conf_write_symbol(out_h, sym, &header_printer_cb, NULL); |
857 | case S_TRISTATE: | 984 | conf_write_symbol(out_h, sym, &header_function_printer_cb, NULL); |
858 | switch (sym_get_tristate_value(sym)) { | ||
859 | case no: | ||
860 | break; | ||
861 | case mod: | ||
862 | fprintf(tristate, "%s%s=M\n", | ||
863 | CONFIG_, sym->name); | ||
864 | fprintf(out_h, "#define %s%s_MODULE 1\n", | ||
865 | CONFIG_, sym->name); | ||
866 | fct_val = 2; | ||
867 | break; | ||
868 | case yes: | ||
869 | if (sym->type == S_TRISTATE) | ||
870 | fprintf(tristate,"%s%s=Y\n", | ||
871 | CONFIG_, sym->name); | ||
872 | fprintf(out_h, "#define %s%s 1\n", | ||
873 | CONFIG_, sym->name); | ||
874 | fct_val = 1; | ||
875 | break; | ||
876 | } | ||
877 | conf_write_function_autoconf(out_h, CONFIG_, sym->name, fct_val); | ||
878 | break; | ||
879 | case S_STRING: | ||
880 | conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); | ||
881 | break; | ||
882 | case S_HEX: | ||
883 | str = sym_get_string_value(sym); | ||
884 | if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { | ||
885 | fprintf(out_h, "#define %s%s 0x%s\n", | ||
886 | CONFIG_, sym->name, str); | ||
887 | break; | ||
888 | } | ||
889 | case S_INT: | ||
890 | str = sym_get_string_value(sym); | ||
891 | fprintf(out_h, "#define %s%s %s\n", | ||
892 | CONFIG_, sym->name, str); | ||
893 | break; | ||
894 | default: | ||
895 | break; | ||
896 | } | ||
897 | } | 985 | } |
898 | fclose(out); | 986 | fclose(out); |
899 | fclose(tristate); | 987 | fclose(tristate); |
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 625ec69ebeee..306c5a59efc2 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h | |||
@@ -87,6 +87,11 @@ void sym_set_change_count(int count); | |||
87 | void sym_add_change_count(int count); | 87 | void sym_add_change_count(int count); |
88 | void conf_set_all_new_symbols(enum conf_def_mode mode); | 88 | void conf_set_all_new_symbols(enum conf_def_mode mode); |
89 | 89 | ||
90 | struct conf_printer { | ||
91 | void (*print_symbol)(FILE *, struct symbol *, const char *, void *); | ||
92 | void (*print_comment)(FILE *, const char *, void *); | ||
93 | }; | ||
94 | |||
90 | /* confdata.c and expr.c */ | 95 | /* confdata.c and expr.c */ |
91 | static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) | 96 | static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) |
92 | { | 97 | { |
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 17342fef38b9..47fe9c340f9a 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h | |||
@@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); | |||
31 | P(sym_lookup,struct symbol *,(const char *name, int flags)); | 31 | P(sym_lookup,struct symbol *,(const char *name, int flags)); |
32 | P(sym_find,struct symbol *,(const char *name)); | 32 | P(sym_find,struct symbol *,(const char *name)); |
33 | P(sym_expand_string_value,const char *,(const char *in)); | 33 | P(sym_expand_string_value,const char *,(const char *in)); |
34 | P(sym_escape_string_value, const char *,(const char *in)); | ||
34 | P(sym_re_search,struct symbol **,(const char *pattern)); | 35 | P(sym_re_search,struct symbol **,(const char *pattern)); |
35 | P(sym_type_name,const char *,(enum symbol_type type)); | 36 | P(sym_type_name,const char *,(enum symbol_type type)); |
36 | P(sym_calc_value,void,(struct symbol *sym)); | 37 | P(sym_calc_value,void,(struct symbol *sym)); |
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index cf8edf4fc429..071f00c3046e 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c | |||
@@ -750,7 +750,8 @@ const char *sym_get_string_value(struct symbol *sym) | |||
750 | case no: | 750 | case no: |
751 | return "n"; | 751 | return "n"; |
752 | case mod: | 752 | case mod: |
753 | return "m"; | 753 | sym_calc_value(modules_sym); |
754 | return (modules_sym->curr.tri == no) ? "n" : "m"; | ||
754 | case yes: | 755 | case yes: |
755 | return "y"; | 756 | return "y"; |
756 | } | 757 | } |
@@ -892,6 +893,49 @@ const char *sym_expand_string_value(const char *in) | |||
892 | return res; | 893 | return res; |
893 | } | 894 | } |
894 | 895 | ||
896 | const char *sym_escape_string_value(const char *in) | ||
897 | { | ||
898 | const char *p; | ||
899 | size_t reslen; | ||
900 | char *res; | ||
901 | size_t l; | ||
902 | |||
903 | reslen = strlen(in) + strlen("\"\"") + 1; | ||
904 | |||
905 | p = in; | ||
906 | for (;;) { | ||
907 | l = strcspn(p, "\"\\"); | ||
908 | p += l; | ||
909 | |||
910 | if (p[0] == '\0') | ||
911 | break; | ||
912 | |||
913 | reslen++; | ||
914 | p++; | ||
915 | } | ||
916 | |||
917 | res = malloc(reslen); | ||
918 | res[0] = '\0'; | ||
919 | |||
920 | strcat(res, "\""); | ||
921 | |||
922 | p = in; | ||
923 | for (;;) { | ||
924 | l = strcspn(p, "\"\\"); | ||
925 | strncat(res, p, l); | ||
926 | p += l; | ||
927 | |||
928 | if (p[0] == '\0') | ||
929 | break; | ||
930 | |||
931 | strcat(res, "\\"); | ||
932 | strncat(res, p++, 1); | ||
933 | } | ||
934 | |||
935 | strcat(res, "\""); | ||
936 | return res; | ||
937 | } | ||
938 | |||
895 | struct symbol **sym_re_search(const char *pattern) | 939 | struct symbol **sym_re_search(const char *pattern) |
896 | { | 940 | { |
897 | struct symbol *sym, **sym_arr = NULL; | 941 | struct symbol *sym, **sym_arr = NULL; |