Commit e54e692ba613c2170c66ce36a3791c009680af08
Committed by
Michal Marek
1 parent
ec6452a5ec
Exists in
master
and in
4 other branches
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>
Showing 4 changed files with 266 additions and 128 deletions Side-by-side Diff
scripts/kconfig/confdata.c
... | ... | @@ -422,64 +422,228 @@ |
422 | 422 | return 0; |
423 | 423 | } |
424 | 424 | |
425 | -/* Write a S_STRING */ | |
426 | -static void conf_write_string(bool headerfile, const char *name, | |
427 | - const char *str, FILE *out) | |
425 | +/* | |
426 | + * Kconfig configuration printer | |
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) | |
428 | 435 | { |
429 | - int l; | |
430 | - if (headerfile) | |
431 | - fprintf(out, "#define %s%s \"", CONFIG_, name); | |
432 | - else | |
433 | - fprintf(out, "%s%s=\"", CONFIG_, name); | |
434 | 436 | |
435 | - while (1) { | |
436 | - l = strcspn(str, "\"\\"); | |
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) | |
458 | +{ | |
459 | + const char *p = value; | |
460 | + size_t l; | |
461 | + | |
462 | + for (;;) { | |
463 | + l = strcspn(p, "\n"); | |
464 | + fprintf(fp, "#"); | |
437 | 465 | if (l) { |
438 | - xfwrite(str, l, 1, out); | |
439 | - str += l; | |
466 | + fprintf(fp, " "); | |
467 | + fwrite(p, l, 1, fp); | |
468 | + p += l; | |
440 | 469 | } |
441 | - if (!*str) | |
470 | + fprintf(fp, "\n"); | |
471 | + if (*p++ == '\0') | |
442 | 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 | +}; | |
451 | 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 = ""; | |
491 | + | |
452 | 492 | switch (sym->type) { |
453 | 493 | case S_BOOLEAN: |
454 | 494 | case S_TRISTATE: |
455 | - switch (sym_get_tristate_value(sym)) { | |
456 | - case no: | |
457 | - if (write_no) | |
458 | - fprintf(out, "# %s%s is not set\n", | |
459 | - CONFIG_, sym->name); | |
460 | - break; | |
461 | - case mod: | |
462 | - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); | |
463 | - break; | |
464 | - case yes: | |
465 | - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); | |
466 | - break; | |
495 | + switch (*value) { | |
496 | + case 'n': | |
497 | + return; | |
498 | + case 'm': | |
499 | + suffix = "_MODULE"; | |
500 | + /* FALLTHROUGH */ | |
501 | + default: | |
502 | + value = "1"; | |
467 | 503 | } |
468 | 504 | break; |
469 | - case S_STRING: | |
470 | - conf_write_string(false, sym->name, sym_get_string_value(sym), out); | |
505 | + default: | |
471 | 506 | break; |
472 | - case S_HEX: | |
473 | - case S_INT: | |
474 | - str = sym_get_string_value(sym); | |
475 | - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); | |
507 | + } | |
508 | + | |
509 | + fprintf(fp, "#define %s%s%s %s\n", | |
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 | 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 | 618 | case S_OTHER: |
478 | 619 | case S_UNKNOWN: |
479 | 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 | 648 | * Write out a minimal config. |
485 | 649 | * All values that has default values are skipped as this is redundant. |
... | ... | @@ -536,7 +700,7 @@ |
536 | 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 | 705 | next_menu: |
542 | 706 | if (menu->list != NULL) { |
... | ... | @@ -601,11 +765,7 @@ |
601 | 765 | if (!out) |
602 | 766 | return 1; |
603 | 767 | |
604 | - fprintf(out, _("#\n" | |
605 | - "# Automatically generated make config: don't edit\n" | |
606 | - "# %s\n" | |
607 | - "#\n"), | |
608 | - rootmenu.prompt->text); | |
768 | + conf_write_heading(out, &kconfig_printer_cb, NULL); | |
609 | 769 | |
610 | 770 | if (!conf_get_changed()) |
611 | 771 | sym_clear_all_valid(); |
... | ... | @@ -626,8 +786,8 @@ |
626 | 786 | if (!(sym->flags & SYMBOL_WRITE)) |
627 | 787 | goto next; |
628 | 788 | sym->flags &= ~SYMBOL_WRITE; |
629 | - /* Write config symbol to file */ | |
630 | - conf_write_symbol(sym, out, true); | |
789 | + | |
790 | + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); | |
631 | 791 | } |
632 | 792 | |
633 | 793 | next: |
634 | 794 | |
... | ... | @@ -773,33 +933,9 @@ |
773 | 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 | 936 | int conf_write_autoconf(void) |
800 | 937 | { |
801 | 938 | struct symbol *sym; |
802 | - const char *str; | |
803 | 939 | const char *name; |
804 | 940 | FILE *out, *tristate, *out_h; |
805 | 941 | int i; |
806 | 942 | |
807 | 943 | |
808 | 944 | |
809 | 945 | |
... | ... | @@ -828,72 +964,24 @@ |
828 | 964 | return 1; |
829 | 965 | } |
830 | 966 | |
831 | - fprintf(out, "#\n" | |
832 | - "# Automatically generated make config: don't edit\n" | |
833 | - "# %s\n" | |
834 | - "#\n", | |
835 | - rootmenu.prompt->text); | |
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); | |
967 | + conf_write_heading(out, &kconfig_printer_cb, NULL); | |
844 | 968 | |
969 | + conf_write_heading(tristate, &tristate_printer_cb, NULL); | |
970 | + | |
971 | + conf_write_heading(out_h, &header_printer_cb, NULL); | |
972 | + | |
845 | 973 | for_all_symbols(i, sym) { |
846 | - int fct_val = 0; | |
847 | 974 | sym_calc_value(sym); |
848 | 975 | if (!(sym->flags & SYMBOL_WRITE) || !sym->name) |
849 | 976 | continue; |
850 | 977 | |
851 | - /* write symbol to config file */ | |
852 | - conf_write_symbol(sym, out, false); | |
978 | + /* write symbol to auto.conf, tristate and header files */ | |
979 | + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); | |
853 | 980 | |
854 | - /* update autoconf and tristate files */ | |
855 | - switch (sym->type) { | |
856 | - case S_BOOLEAN: | |
857 | - case S_TRISTATE: | |
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 | - } | |
981 | + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); | |
982 | + | |
983 | + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); | |
984 | + conf_write_symbol(out_h, sym, &header_function_printer_cb, NULL); | |
897 | 985 | } |
898 | 986 | fclose(out); |
899 | 987 | fclose(tristate); |
scripts/kconfig/lkc.h
... | ... | @@ -87,6 +87,11 @@ |
87 | 87 | void sym_add_change_count(int count); |
88 | 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 | 95 | /* confdata.c and expr.c */ |
91 | 96 | static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) |
92 | 97 | { |
scripts/kconfig/lkc_proto.h
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | P(sym_lookup,struct symbol *,(const char *name, int flags)); |
32 | 32 | P(sym_find,struct symbol *,(const char *name)); |
33 | 33 | P(sym_expand_string_value,const char *,(const char *in)); |
34 | +P(sym_escape_string_value, const char *,(const char *in)); | |
34 | 35 | P(sym_re_search,struct symbol **,(const char *pattern)); |
35 | 36 | P(sym_type_name,const char *,(enum symbol_type type)); |
36 | 37 | P(sym_calc_value,void,(struct symbol *sym)); |
scripts/kconfig/symbol.c
... | ... | @@ -750,7 +750,8 @@ |
750 | 750 | case no: |
751 | 751 | return "n"; |
752 | 752 | case mod: |
753 | - return "m"; | |
753 | + sym_calc_value(modules_sym); | |
754 | + return (modules_sym->curr.tri == no) ? "n" : "m"; | |
754 | 755 | case yes: |
755 | 756 | return "y"; |
756 | 757 | } |
... | ... | @@ -889,6 +890,49 @@ |
889 | 890 | } |
890 | 891 | strcat(res, in); |
891 | 892 | |
893 | + return res; | |
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, "\""); | |
892 | 936 | return res; |
893 | 937 | } |
894 | 938 |