* [PATCH 1/2] [RFC] kconfig: introduce specialized printer @ 2010-12-05 6:35 Arnaud Lacombe 2010-12-05 6:35 ` [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel Arnaud Lacombe ` (2 more replies) 0 siblings, 3 replies; 17+ messages in thread From: Arnaud Lacombe @ 2010-12-05 6:35 UTC (permalink / raw) To: linux-kbuild; +Cc: Arnaud Lacombe, Ben Hutchings The goal of this patch is to 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 became mostly only to prepare a string for the printer. This avoid to have to pass specialized flag to generic functions. CC: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> --- scripts/kconfig/confdata.c | 284 +++++++++++++++++++++++++----------------- scripts/kconfig/lkc.h | 5 + scripts/kconfig/lkc_proto.h | 1 + scripts/kconfig/symbol.c | 46 +++++++- 4 files changed, 220 insertions(+), 116 deletions(-) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 6fd43d7..31d06da 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -417,64 +417,182 @@ int conf_read(const char *name) return 0; } -/* Write a S_STRING */ -static void conf_write_string(bool headerfile, const char *name, - const char *str, FILE *out) +/* + * Generic printers + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) { - int l; - if (headerfile) - fprintf(out, "#define %s%s \"", CONFIG_, name); - else - fprintf(out, "%s%s=\"", CONFIG_, name); - - while (1) { - l = strcspn(str, "\"\\"); + + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (*value) { + case 'n': + if (arg != NULL) + return; + + fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name); + return; + default: + break; + } + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); if (l) { - xfwrite(str, l, 1, out); - str += l; + fprintf(fp, " "); + fwrite(p, l, 1, fp); + p += l; } - if (!*str) + fprintf(fp, "\n"); + if (*p++ == '\0') break; - fprintf(out, "\\%c", *str++); } - fputs("\"\n", out); } -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) +static struct conf_printer kconfig_printer_cb = { - const char *str; + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + const char *suffix = ""; switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - if (write_no) - fprintf(out, "# %s%s is not set\n", - CONFIG_, sym->name); - break; - case mod: - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); - break; - case yes: - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); - break; + switch (*value) { + case 'n': + return; + case 'm': + suffix = "_MODULE"; + default: + value = "1"; } break; - case S_STRING: - conf_write_string(false, sym->name, sym_get_string_value(sym), out); + default: break; - case S_HEX: - case S_INT: - str = sym_get_string_value(sym); - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); + } + + fprintf(fp, "#define %s%s%s %s\n", + CONFIG_, sym->name, suffix, value); +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + fwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + kconfig_print_symbol(fp, sym, value, arg); + break; + default: break; + } +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * + */ + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { case S_OTHER: case S_UNKNOWN: break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); } } +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + const char *env; + char buf[256]; + time_t now; + int use_timestamp = 1; + + time(&now); + env = getenv("KCONFIG_NOTIMESTAMP"); + if (env && *env) + use_timestamp = 0; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n" + "%s", + rootmenu.prompt->text, + use_timestamp ? ctime(&now) : ""); + + printer->print_comment(fp, buf, printer_arg); +} + /* * Write out a minimal config. * All values that has default values are skipped as this is redundant. @@ -531,7 +649,7 @@ int conf_write_defconfig(const char *filename) goto next_menu; } } - conf_write_symbol(sym, out, true); + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next_menu: if (menu->list != NULL) { @@ -561,9 +679,7 @@ int conf_write(const char *name) const char *str; char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; enum symbol_type type; - time_t now; - int use_timestamp = 1; - char *env; + const char *env; dirname[0] = 0; if (name && name[0]) { @@ -599,19 +715,7 @@ int conf_write(const char *name) if (!out) return 1; - time(&now); - env = getenv("KCONFIG_NOTIMESTAMP"); - if (env && *env) - use_timestamp = 0; - - fprintf(out, _("#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "%s%s" - "#\n"), - rootmenu.prompt->text, - use_timestamp ? "# " : "", - use_timestamp ? ctime(&now) : ""); + conf_write_heading(out, &kconfig_printer_cb, NULL); if (!conf_get_changed()) sym_clear_all_valid(); @@ -632,8 +736,8 @@ int conf_write(const char *name) if (!(sym->flags & SYMBOL_WRITE)) goto next; sym->flags &= ~SYMBOL_WRITE; - /* Write config symbol to file */ - conf_write_symbol(sym, out, true); + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next: @@ -782,10 +886,8 @@ out: int conf_write_autoconf(void) { struct symbol *sym; - const char *str; const char *name; FILE *out, *tristate, *out_h; - time_t now; int i; sym_clear_all_valid(); @@ -812,71 +914,23 @@ int conf_write_autoconf(void) return 1; } - time(&now); - fprintf(out, "#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "# %s" - "#\n", - rootmenu.prompt->text, ctime(&now)); - fprintf(tristate, "#\n" - "# Automatically generated - do not edit\n" - "\n"); - fprintf(out_h, "/*\n" - " * Automatically generated C config: don't edit\n" - " * %s\n" - " * %s" - " */\n", - rootmenu.prompt->text, ctime(&now)); + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; - /* write symbol to config file */ - conf_write_symbol(sym, out, false); + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); - /* update autoconf and tristate files */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - break; - case mod: - fprintf(tristate, "%s%s=M\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s_MODULE 1\n", - CONFIG_, sym->name); - break; - case yes: - if (sym->type == S_TRISTATE) - fprintf(tristate,"%s%s=Y\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s 1\n", - CONFIG_, sym->name); - break; - } - break; - case S_STRING: - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); - break; - case S_HEX: - str = sym_get_string_value(sym); - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out_h, "#define %s%s 0x%s\n", - CONFIG_, sym->name, str); - break; - } - case S_INT: - str = sym_get_string_value(sym); - fprintf(out_h, "#define %s%s %s\n", - CONFIG_, sym->name, str); - break; - default: - break; - } + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); } fclose(out); fclose(tristate); diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 753cdbd..3633d5a 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -89,6 +89,11 @@ void sym_set_change_count(int count); void sym_add_change_count(int count); void conf_set_all_new_symbols(enum conf_def_mode mode); +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + /* confdata.c and expr.c */ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) { diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 17342fe..47fe9c3 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); P(sym_lookup,struct symbol *,(const char *name, int flags)); P(sym_find,struct symbol *,(const char *name)); P(sym_expand_string_value,const char *,(const char *in)); +P(sym_escape_string_value, const char *,(const char *in)); P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_type_name,const char *,(enum symbol_type type)); P(sym_calc_value,void,(struct symbol *sym)); diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index ad7dbe7..e42240d 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -749,7 +749,8 @@ const char *sym_get_string_value(struct symbol *sym) case no: return "n"; case mod: - return "m"; + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; case yes: return "y"; } @@ -891,6 +892,49 @@ const char *sym_expand_string_value(const char *in) return res; } +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = malloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + struct symbol **sym_re_search(const char *pattern) { struct symbol *sym, **sym_arr = NULL; -- 1.7.2.30.gc37d7.dirty ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel 2010-12-05 6:35 [PATCH 1/2] [RFC] kconfig: introduce specialized printer Arnaud Lacombe @ 2010-12-05 6:35 ` Arnaud Lacombe 2010-12-15 6:28 ` Arnaud Lacombe 2010-12-21 16:47 ` Michal Marek 2010-12-15 6:27 ` [PATCH 1/2] [RFC] kconfig: introduce specialized printer Arnaud Lacombe 2010-12-21 16:37 ` Michal Marek 2 siblings, 2 replies; 17+ messages in thread From: Arnaud Lacombe @ 2010-12-05 6:35 UTC (permalink / raw) To: linux-kbuild; +Cc: Arnaud Lacombe, Ben Hutchings note: I would not mind adding the KCONFIG_VERBOSE logic. Original idea and implementation by Bastian Blank <waldi@debian.org>, Maximilian Attems <max@stro.at> and Ben Hutchings <ben@decadent.org.uk> CC: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> --- scripts/kconfig/conf.c | 14 +++++++++++++- scripts/kconfig/confdata.c | 4 ++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 5459a38..1b58129 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -411,6 +411,17 @@ conf_childs: indent -= 2; } + +static void +listnewconfig_print_symbol(FILE *fp, struct symbol *sym, const char *val, void *arg) +{ + fprintf(fp, "%s%s (default: %s)\n", CONFIG_, sym->name, val); +} + +static struct conf_printer listnewconfig_printers = { + .print_symbol = listnewconfig_print_symbol, +}; + static void check_conf(struct menu *menu) { struct symbol *sym; @@ -425,7 +436,8 @@ static void check_conf(struct menu *menu) (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { if (input_mode == listnewconfig) { if (sym->name && !sym_is_choice_value(sym)) { - printf("%s%s\n", CONFIG_, sym->name); + conf_write_symbol(stdout, sym, + &listnewconfig_printers, NULL); } } else if (input_mode != oldnoconfig) { if (!conf_cnt++) diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 31d06da..6f2f3a4 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -548,8 +548,8 @@ static struct conf_printer tristate_printer_cb = * */ -static void conf_write_symbol(FILE *fp, struct symbol *sym, - struct conf_printer *printer, void *printer_arg) +void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) { const char *str; -- 1.7.2.30.gc37d7.dirty ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel 2010-12-05 6:35 ` [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel Arnaud Lacombe @ 2010-12-15 6:28 ` Arnaud Lacombe 2010-12-21 16:47 ` Michal Marek 1 sibling, 0 replies; 17+ messages in thread From: Arnaud Lacombe @ 2010-12-15 6:28 UTC (permalink / raw) To: linux-kbuild; +Cc: Ben Hutchings, Michal Marek Hi, On Sun, Dec 5, 2010 at 1:35 AM, Arnaud Lacombe <lacombar@gmail.com> wrote: > note: I would not mind adding the KCONFIG_VERBOSE logic. > > Original idea and implementation by Bastian Blank <waldi@debian.org>, > Maximilian Attems <max@stro.at> and Ben Hutchings <ben@decadent.org.uk> > > CC: Ben Hutchings <ben@decadent.org.uk> > Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> > --- > scripts/kconfig/conf.c | 14 +++++++++++++- > scripts/kconfig/confdata.c | 4 ++-- > 2 files changed, 15 insertions(+), 3 deletions(-) > ping ? - Arnaud > diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c > index 5459a38..1b58129 100644 > --- a/scripts/kconfig/conf.c > +++ b/scripts/kconfig/conf.c > @@ -411,6 +411,17 @@ conf_childs: > indent -= 2; > } > > + > +static void > +listnewconfig_print_symbol(FILE *fp, struct symbol *sym, const char *val, void *arg) > +{ > + fprintf(fp, "%s%s (default: %s)\n", CONFIG_, sym->name, val); > +} > + > +static struct conf_printer listnewconfig_printers = { > + .print_symbol = listnewconfig_print_symbol, > +}; > + > static void check_conf(struct menu *menu) > { > struct symbol *sym; > @@ -425,7 +436,8 @@ static void check_conf(struct menu *menu) > (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { > if (input_mode == listnewconfig) { > if (sym->name && !sym_is_choice_value(sym)) { > - printf("%s%s\n", CONFIG_, sym->name); > + conf_write_symbol(stdout, sym, > + &listnewconfig_printers, NULL); > } > } else if (input_mode != oldnoconfig) { > if (!conf_cnt++) > diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c > index 31d06da..6f2f3a4 100644 > --- a/scripts/kconfig/confdata.c > +++ b/scripts/kconfig/confdata.c > @@ -548,8 +548,8 @@ static struct conf_printer tristate_printer_cb = > * > */ > > -static void conf_write_symbol(FILE *fp, struct symbol *sym, > - struct conf_printer *printer, void *printer_arg) > +void conf_write_symbol(FILE *fp, struct symbol *sym, > + struct conf_printer *printer, void *printer_arg) > { > const char *str; > > -- > 1.7.2.30.gc37d7.dirty > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel 2010-12-05 6:35 ` [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel Arnaud Lacombe 2010-12-15 6:28 ` Arnaud Lacombe @ 2010-12-21 16:47 ` Michal Marek 2010-12-21 17:54 ` Arnaud Lacombe 2010-12-22 4:44 ` Ben Hutchings 1 sibling, 2 replies; 17+ messages in thread From: Michal Marek @ 2010-12-21 16:47 UTC (permalink / raw) To: Arnaud Lacombe; +Cc: linux-kbuild, Ben Hutchings On 5.12.2010 07:35, Arnaud Lacombe wrote: > note: I would not mind adding the KCONFIG_VERBOSE logic. > > Original idea and implementation by Bastian Blank <waldi@debian.org>, > Maximilian Attems <max@stro.at> and Ben Hutchings <ben@decadent.org.uk> > > CC: Ben Hutchings <ben@decadent.org.uk> > Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> > --- > scripts/kconfig/conf.c | 14 +++++++++++++- > scripts/kconfig/confdata.c | 4 ++-- > 2 files changed, 15 insertions(+), 3 deletions(-) > > diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c > index 5459a38..1b58129 100644 > --- a/scripts/kconfig/conf.c > +++ b/scripts/kconfig/conf.c > @@ -411,6 +411,17 @@ conf_childs: > indent -= 2; > } > > + > +static void > +listnewconfig_print_symbol(FILE *fp, struct symbol *sym, const char *val, void *arg) > +{ > + fprintf(fp, "%s%s (default: %s)\n", CONFIG_, sym->name, val); > +} Ben, do you have an opinion on this format versus the standard .config produced by your patch? Michal > + > +static struct conf_printer listnewconfig_printers = { > + .print_symbol = listnewconfig_print_symbol, > +}; > + > static void check_conf(struct menu *menu) > { > struct symbol *sym; > @@ -425,7 +436,8 @@ static void check_conf(struct menu *menu) > (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { > if (input_mode == listnewconfig) { > if (sym->name && !sym_is_choice_value(sym)) { > - printf("%s%s\n", CONFIG_, sym->name); > + conf_write_symbol(stdout, sym, > + &listnewconfig_printers, NULL); > } > } else if (input_mode != oldnoconfig) { > if (!conf_cnt++) > diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c > index 31d06da..6f2f3a4 100644 > --- a/scripts/kconfig/confdata.c > +++ b/scripts/kconfig/confdata.c > @@ -548,8 +548,8 @@ static struct conf_printer tristate_printer_cb = > * > */ > > -static void conf_write_symbol(FILE *fp, struct symbol *sym, > - struct conf_printer *printer, void *printer_arg) > +void conf_write_symbol(FILE *fp, struct symbol *sym, > + struct conf_printer *printer, void *printer_arg) > { > const char *str; > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel 2010-12-21 16:47 ` Michal Marek @ 2010-12-21 17:54 ` Arnaud Lacombe 2010-12-22 4:44 ` Ben Hutchings 1 sibling, 0 replies; 17+ messages in thread From: Arnaud Lacombe @ 2010-12-21 17:54 UTC (permalink / raw) To: Michal Marek; +Cc: linux-kbuild, Ben Hutchings Hi, 2010/12/21 Michal Marek <mmarek@suse.cz>: > On 5.12.2010 07:35, Arnaud Lacombe wrote: >> note: I would not mind adding the KCONFIG_VERBOSE logic. >> >> Original idea and implementation by Bastian Blank <waldi@debian.org>, >> Maximilian Attems <max@stro.at> and Ben Hutchings <ben@decadent.org.uk> >> >> CC: Ben Hutchings <ben@decadent.org.uk> >> Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> >> --- >> scripts/kconfig/conf.c | 14 +++++++++++++- >> scripts/kconfig/confdata.c | 4 ++-- >> 2 files changed, 15 insertions(+), 3 deletions(-) >> >> diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c >> index 5459a38..1b58129 100644 >> --- a/scripts/kconfig/conf.c >> +++ b/scripts/kconfig/conf.c >> @@ -411,6 +411,17 @@ conf_childs: >> indent -= 2; >> } >> >> + >> +static void >> +listnewconfig_print_symbol(FILE *fp, struct symbol *sym, const char *val, void *arg) >> +{ >> + fprintf(fp, "%s%s (default: %s)\n", CONFIG_, sym->name, val); >> +} > > Ben, do you have an opinion on this format versus the standard .config > produced by your patch? > FWIW, this was just a quick and dirty implementation using the previous patch. I do not really care about the printed format, nor how it interacts with the environment. So I'm open to anything :) - Arnaud > Michal >> + >> +static struct conf_printer listnewconfig_printers = { >> + .print_symbol = listnewconfig_print_symbol, >> +}; >> + >> static void check_conf(struct menu *menu) >> { >> struct symbol *sym; >> @@ -425,7 +436,8 @@ static void check_conf(struct menu *menu) >> (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { >> if (input_mode == listnewconfig) { >> if (sym->name && !sym_is_choice_value(sym)) { >> - printf("%s%s\n", CONFIG_, sym->name); >> + conf_write_symbol(stdout, sym, >> + &listnewconfig_printers, NULL); >> } >> } else if (input_mode != oldnoconfig) { >> if (!conf_cnt++) >> diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c >> index 31d06da..6f2f3a4 100644 >> --- a/scripts/kconfig/confdata.c >> +++ b/scripts/kconfig/confdata.c >> @@ -548,8 +548,8 @@ static struct conf_printer tristate_printer_cb = >> * >> */ >> >> -static void conf_write_symbol(FILE *fp, struct symbol *sym, >> - struct conf_printer *printer, void *printer_arg) >> +void conf_write_symbol(FILE *fp, struct symbol *sym, >> + struct conf_printer *printer, void *printer_arg) >> { >> const char *str; >> > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel 2010-12-21 16:47 ` Michal Marek 2010-12-21 17:54 ` Arnaud Lacombe @ 2010-12-22 4:44 ` Ben Hutchings 2010-12-22 5:39 ` Arnaud Lacombe 1 sibling, 1 reply; 17+ messages in thread From: Ben Hutchings @ 2010-12-22 4:44 UTC (permalink / raw) To: Michal Marek; +Cc: Arnaud Lacombe, linux-kbuild [-- Attachment #1: Type: text/plain, Size: 1517 bytes --] On Tue, 2010-12-21 at 17:47 +0100, Michal Marek wrote: > On 5.12.2010 07:35, Arnaud Lacombe wrote: > > note: I would not mind adding the KCONFIG_VERBOSE logic. > > > > Original idea and implementation by Bastian Blank <waldi@debian.org>, > > Maximilian Attems <max@stro.at> and Ben Hutchings <ben@decadent.org.uk> > > > > CC: Ben Hutchings <ben@decadent.org.uk> > > Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> > > --- > > scripts/kconfig/conf.c | 14 +++++++++++++- > > scripts/kconfig/confdata.c | 4 ++-- > > 2 files changed, 15 insertions(+), 3 deletions(-) > > > > diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c > > index 5459a38..1b58129 100644 > > --- a/scripts/kconfig/conf.c > > +++ b/scripts/kconfig/conf.c > > @@ -411,6 +411,17 @@ conf_childs: > > indent -= 2; > > } > > > > + > > +static void > > +listnewconfig_print_symbol(FILE *fp, struct symbol *sym, const char *val, void *arg) > > +{ > > + fprintf(fp, "%s%s (default: %s)\n", CONFIG_, sym->name, val); > > +} > > Ben, do you have an opinion on this format versus the standard .config > produced by your patch? [...] The .config format is more useful as it is then possible to copy lines directly into a .config file. If you're going to apply Arnaud's preceding patch (1/2) then please let me rewrite mine to apply on top of that, rather than applying this second patch. Ben. -- Ben Hutchings Once a job is fouled up, anything done to improve it makes it worse. [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 828 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel 2010-12-22 4:44 ` Ben Hutchings @ 2010-12-22 5:39 ` Arnaud Lacombe 0 siblings, 0 replies; 17+ messages in thread From: Arnaud Lacombe @ 2010-12-22 5:39 UTC (permalink / raw) To: Ben Hutchings; +Cc: Michal Marek, linux-kbuild Hi, On Tue, Dec 21, 2010 at 11:44 PM, Ben Hutchings <ben@decadent.org.uk> wrote: > On Tue, 2010-12-21 at 17:47 +0100, Michal Marek wrote: >> On 5.12.2010 07:35, Arnaud Lacombe wrote: >> > note: I would not mind adding the KCONFIG_VERBOSE logic. >> > >> > Original idea and implementation by Bastian Blank <waldi@debian.org>, >> > Maximilian Attems <max@stro.at> and Ben Hutchings <ben@decadent.org.uk> >> > >> > CC: Ben Hutchings <ben@decadent.org.uk> >> > Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> >> > --- >> > scripts/kconfig/conf.c | 14 +++++++++++++- >> > scripts/kconfig/confdata.c | 4 ++-- >> > 2 files changed, 15 insertions(+), 3 deletions(-) >> > >> > diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c >> > index 5459a38..1b58129 100644 >> > --- a/scripts/kconfig/conf.c >> > +++ b/scripts/kconfig/conf.c >> > @@ -411,6 +411,17 @@ conf_childs: >> > indent -= 2; >> > } >> > >> > + >> > +static void >> > +listnewconfig_print_symbol(FILE *fp, struct symbol *sym, const char *val, void *arg) >> > +{ >> > + fprintf(fp, "%s%s (default: %s)\n", CONFIG_, sym->name, val); >> > +} >> >> Ben, do you have an opinion on this format versus the standard .config >> produced by your patch? > [...] > > The .config format is more useful as it is then possible to copy lines > directly into a .config file. If you're going to apply Arnaud's > preceding patch (1/2) then please let me rewrite mine to apply on top of > that, rather than applying this second patch. > I'm fine if you do so, I do not really care about any specific formatting. However, I'd like to avoid the SYMBOL_NEW part, which is broken and not needed. I did not had the time to address Michal's comment on [1/2] this evening because of some rush @WORK, hope to do that tomorrow :/. - Arnaud ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/2] [RFC] kconfig: introduce specialized printer 2010-12-05 6:35 [PATCH 1/2] [RFC] kconfig: introduce specialized printer Arnaud Lacombe 2010-12-05 6:35 ` [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel Arnaud Lacombe @ 2010-12-15 6:27 ` Arnaud Lacombe 2010-12-21 16:37 ` Michal Marek 2 siblings, 0 replies; 17+ messages in thread From: Arnaud Lacombe @ 2010-12-15 6:27 UTC (permalink / raw) To: linux-kbuild; +Cc: Ben Hutchings, Michal Marek Hi, On Sun, Dec 5, 2010 at 1:35 AM, Arnaud Lacombe <lacombar@gmail.com> wrote: > The goal of this patch is to 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 became mostly only to prepare a string for the > printer. This avoid to have to pass specialized flag to generic functions. > > CC: Ben Hutchings <ben@decadent.org.uk> > Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> > --- > scripts/kconfig/confdata.c | 284 +++++++++++++++++++++++++----------------- > scripts/kconfig/lkc.h | 5 + > scripts/kconfig/lkc_proto.h | 1 + > scripts/kconfig/symbol.c | 46 +++++++- > 4 files changed, 220 insertions(+), 116 deletions(-) > ping ? - Arnaud > diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c > index 6fd43d7..31d06da 100644 > --- a/scripts/kconfig/confdata.c > +++ b/scripts/kconfig/confdata.c > @@ -417,64 +417,182 @@ int conf_read(const char *name) > return 0; > } > > -/* Write a S_STRING */ > -static void conf_write_string(bool headerfile, const char *name, > - const char *str, FILE *out) > +/* > + * Generic printers > + */ > +static void > +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > { > - int l; > - if (headerfile) > - fprintf(out, "#define %s%s \"", CONFIG_, name); > - else > - fprintf(out, "%s%s=\"", CONFIG_, name); > - > - while (1) { > - l = strcspn(str, "\"\\"); > + > + > + switch (sym->type) { > + case S_BOOLEAN: > + case S_TRISTATE: > + switch (*value) { > + case 'n': > + if (arg != NULL) > + return; > + > + fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name); > + return; > + default: > + break; > + } > + default: > + break; > + } > + > + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); > +} > + > +static void > +kconfig_print_comment(FILE *fp, const char *value, void *arg) > +{ > + const char *p = value; > + size_t l; > + > + for (;;) { > + l = strcspn(p, "\n"); > + fprintf(fp, "#"); > if (l) { > - xfwrite(str, l, 1, out); > - str += l; > + fprintf(fp, " "); > + fwrite(p, l, 1, fp); > + p += l; > } > - if (!*str) > + fprintf(fp, "\n"); > + if (*p++ == '\0') > break; > - fprintf(out, "\\%c", *str++); > } > - fputs("\"\n", out); > } > > -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) > +static struct conf_printer kconfig_printer_cb = > { > - const char *str; > + .print_symbol = kconfig_print_symbol, > + .print_comment = kconfig_print_comment, > +}; > + > +static void > +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > +{ > + const char *suffix = ""; > > switch (sym->type) { > case S_BOOLEAN: > case S_TRISTATE: > - switch (sym_get_tristate_value(sym)) { > - case no: > - if (write_no) > - fprintf(out, "# %s%s is not set\n", > - CONFIG_, sym->name); > - break; > - case mod: > - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); > - break; > - case yes: > - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); > - break; > + switch (*value) { > + case 'n': > + return; > + case 'm': > + suffix = "_MODULE"; > + default: > + value = "1"; > } > break; > - case S_STRING: > - conf_write_string(false, sym->name, sym_get_string_value(sym), out); > + default: > break; > - case S_HEX: > - case S_INT: > - str = sym_get_string_value(sym); > - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); > + } > + > + fprintf(fp, "#define %s%s%s %s\n", > + CONFIG_, sym->name, suffix, value); > +} > + > +static void > +header_print_comment(FILE *fp, const char *value, void *arg) > +{ > + const char *p = value; > + size_t l; > + > + fprintf(fp, "/*\n"); > + for (;;) { > + l = strcspn(p, "\n"); > + fprintf(fp, " *"); > + if (l) { > + fprintf(fp, " "); > + fwrite(p, l, 1, fp); > + p += l; > + } > + fprintf(fp, "\n"); > + if (*p++ == '\0') > + break; > + } > + fprintf(fp, " */\n"); > +} > + > +static struct conf_printer header_printer_cb = > +{ > + .print_symbol = header_print_symbol, > + .print_comment = header_print_comment, > +}; > + > +static void > +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > +{ > + > + switch (sym->type) { > + case S_BOOLEAN: > + case S_TRISTATE: > + kconfig_print_symbol(fp, sym, value, arg); > + break; > + default: > break; > + } > +} > + > +static struct conf_printer tristate_printer_cb = > +{ > + .print_symbol = tristate_print_symbol, > + .print_comment = kconfig_print_comment, > +}; > + > +/* > + * > + */ > + > +static void conf_write_symbol(FILE *fp, struct symbol *sym, > + struct conf_printer *printer, void *printer_arg) > +{ > + const char *str; > + > + switch (sym->type) { > case S_OTHER: > case S_UNKNOWN: > break; > + case S_STRING: > + str = sym_get_string_value(sym); > + str = sym_escape_string_value(str); > + printer->print_symbol(fp, sym, str, printer_arg); > + free((void *)str); > + break; > + default: > + str = sym_get_string_value(sym); > + printer->print_symbol(fp, sym, str, printer_arg); > } > } > > +static void > +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) > +{ > + const char *env; > + char buf[256]; > + time_t now; > + int use_timestamp = 1; > + > + time(&now); > + env = getenv("KCONFIG_NOTIMESTAMP"); > + if (env && *env) > + use_timestamp = 0; > + > + snprintf(buf, sizeof(buf), > + "\n" > + "Automatically generated file; DO NOT EDIT.\n" > + "%s\n" > + "%s", > + rootmenu.prompt->text, > + use_timestamp ? ctime(&now) : ""); > + > + printer->print_comment(fp, buf, printer_arg); > +} > + > /* > * Write out a minimal config. > * All values that has default values are skipped as this is redundant. > @@ -531,7 +649,7 @@ int conf_write_defconfig(const char *filename) > goto next_menu; > } > } > - conf_write_symbol(sym, out, true); > + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); > } > next_menu: > if (menu->list != NULL) { > @@ -561,9 +679,7 @@ int conf_write(const char *name) > const char *str; > char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; > enum symbol_type type; > - time_t now; > - int use_timestamp = 1; > - char *env; > + const char *env; > > dirname[0] = 0; > if (name && name[0]) { > @@ -599,19 +715,7 @@ int conf_write(const char *name) > if (!out) > return 1; > > - time(&now); > - env = getenv("KCONFIG_NOTIMESTAMP"); > - if (env && *env) > - use_timestamp = 0; > - > - fprintf(out, _("#\n" > - "# Automatically generated make config: don't edit\n" > - "# %s\n" > - "%s%s" > - "#\n"), > - rootmenu.prompt->text, > - use_timestamp ? "# " : "", > - use_timestamp ? ctime(&now) : ""); > + conf_write_heading(out, &kconfig_printer_cb, NULL); > > if (!conf_get_changed()) > sym_clear_all_valid(); > @@ -632,8 +736,8 @@ int conf_write(const char *name) > if (!(sym->flags & SYMBOL_WRITE)) > goto next; > sym->flags &= ~SYMBOL_WRITE; > - /* Write config symbol to file */ > - conf_write_symbol(sym, out, true); > + > + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); > } > > next: > @@ -782,10 +886,8 @@ out: > int conf_write_autoconf(void) > { > struct symbol *sym; > - const char *str; > const char *name; > FILE *out, *tristate, *out_h; > - time_t now; > int i; > > sym_clear_all_valid(); > @@ -812,71 +914,23 @@ int conf_write_autoconf(void) > return 1; > } > > - time(&now); > - fprintf(out, "#\n" > - "# Automatically generated make config: don't edit\n" > - "# %s\n" > - "# %s" > - "#\n", > - rootmenu.prompt->text, ctime(&now)); > - fprintf(tristate, "#\n" > - "# Automatically generated - do not edit\n" > - "\n"); > - fprintf(out_h, "/*\n" > - " * Automatically generated C config: don't edit\n" > - " * %s\n" > - " * %s" > - " */\n", > - rootmenu.prompt->text, ctime(&now)); > + conf_write_heading(out, &kconfig_printer_cb, NULL); > + > + conf_write_heading(tristate, &tristate_printer_cb, NULL); > + > + conf_write_heading(out_h, &header_printer_cb, NULL); > > for_all_symbols(i, sym) { > sym_calc_value(sym); > if (!(sym->flags & SYMBOL_WRITE) || !sym->name) > continue; > > - /* write symbol to config file */ > - conf_write_symbol(sym, out, false); > + /* write symbol to auto.conf, tristate and header files */ > + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); > > - /* update autoconf and tristate files */ > - switch (sym->type) { > - case S_BOOLEAN: > - case S_TRISTATE: > - switch (sym_get_tristate_value(sym)) { > - case no: > - break; > - case mod: > - fprintf(tristate, "%s%s=M\n", > - CONFIG_, sym->name); > - fprintf(out_h, "#define %s%s_MODULE 1\n", > - CONFIG_, sym->name); > - break; > - case yes: > - if (sym->type == S_TRISTATE) > - fprintf(tristate,"%s%s=Y\n", > - CONFIG_, sym->name); > - fprintf(out_h, "#define %s%s 1\n", > - CONFIG_, sym->name); > - break; > - } > - break; > - case S_STRING: > - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); > - break; > - case S_HEX: > - str = sym_get_string_value(sym); > - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { > - fprintf(out_h, "#define %s%s 0x%s\n", > - CONFIG_, sym->name, str); > - break; > - } > - case S_INT: > - str = sym_get_string_value(sym); > - fprintf(out_h, "#define %s%s %s\n", > - CONFIG_, sym->name, str); > - break; > - default: > - break; > - } > + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); > + > + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); > } > fclose(out); > fclose(tristate); > diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h > index 753cdbd..3633d5a 100644 > --- a/scripts/kconfig/lkc.h > +++ b/scripts/kconfig/lkc.h > @@ -89,6 +89,11 @@ void sym_set_change_count(int count); > void sym_add_change_count(int count); > void conf_set_all_new_symbols(enum conf_def_mode mode); > > +struct conf_printer { > + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); > + void (*print_comment)(FILE *, const char *, void *); > +}; > + > /* confdata.c and expr.c */ > static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) > { > diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h > index 17342fe..47fe9c3 100644 > --- a/scripts/kconfig/lkc_proto.h > +++ b/scripts/kconfig/lkc_proto.h > @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); > P(sym_lookup,struct symbol *,(const char *name, int flags)); > P(sym_find,struct symbol *,(const char *name)); > P(sym_expand_string_value,const char *,(const char *in)); > +P(sym_escape_string_value, const char *,(const char *in)); > P(sym_re_search,struct symbol **,(const char *pattern)); > P(sym_type_name,const char *,(enum symbol_type type)); > P(sym_calc_value,void,(struct symbol *sym)); > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c > index ad7dbe7..e42240d 100644 > --- a/scripts/kconfig/symbol.c > +++ b/scripts/kconfig/symbol.c > @@ -749,7 +749,8 @@ const char *sym_get_string_value(struct symbol *sym) > case no: > return "n"; > case mod: > - return "m"; > + sym_calc_value(modules_sym); > + return (modules_sym->curr.tri == no) ? "n" : "m"; > case yes: > return "y"; > } > @@ -891,6 +892,49 @@ const char *sym_expand_string_value(const char *in) > return res; > } > > +const char *sym_escape_string_value(const char *in) > +{ > + const char *p; > + size_t reslen; > + char *res; > + size_t l; > + > + reslen = strlen(in) + strlen("\"\"") + 1; > + > + p = in; > + for (;;) { > + l = strcspn(p, "\"\\"); > + p += l; > + > + if (p[0] == '\0') > + break; > + > + reslen++; > + p++; > + } > + > + res = malloc(reslen); > + res[0] = '\0'; > + > + strcat(res, "\""); > + > + p = in; > + for (;;) { > + l = strcspn(p, "\"\\"); > + strncat(res, p, l); > + p += l; > + > + if (p[0] == '\0') > + break; > + > + strcat(res, "\\"); > + strncat(res, p++, 1); > + } > + > + strcat(res, "\""); > + return res; > +} > + > struct symbol **sym_re_search(const char *pattern) > { > struct symbol *sym, **sym_arr = NULL; > -- > 1.7.2.30.gc37d7.dirty > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/2] [RFC] kconfig: introduce specialized printer 2010-12-05 6:35 [PATCH 1/2] [RFC] kconfig: introduce specialized printer Arnaud Lacombe 2010-12-05 6:35 ` [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel Arnaud Lacombe 2010-12-15 6:27 ` [PATCH 1/2] [RFC] kconfig: introduce specialized printer Arnaud Lacombe @ 2010-12-21 16:37 ` Michal Marek 2010-12-21 16:42 ` Arnaud Lacombe 2011-05-16 3:42 ` [PATCHv2] " Arnaud Lacombe 2 siblings, 2 replies; 17+ messages in thread From: Michal Marek @ 2010-12-21 16:37 UTC (permalink / raw) To: Arnaud Lacombe; +Cc: linux-kbuild, Ben Hutchings On 5.12.2010 07:35, Arnaud Lacombe wrote: > The goal of this patch is to 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 became mostly only to prepare a string for the > printer. This avoid to have to pass specialized flag to generic functions. I like the idea, I only have a few comments below. > > CC: Ben Hutchings <ben@decadent.org.uk> > Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> > --- > scripts/kconfig/confdata.c | 284 +++++++++++++++++++++++++----------------- > scripts/kconfig/lkc.h | 5 + > scripts/kconfig/lkc_proto.h | 1 + > scripts/kconfig/symbol.c | 46 +++++++- > 4 files changed, 220 insertions(+), 116 deletions(-) > > diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c > index 6fd43d7..31d06da 100644 > --- a/scripts/kconfig/confdata.c > +++ b/scripts/kconfig/confdata.c > @@ -417,64 +417,182 @@ int conf_read(const char *name) > return 0; > } > > -/* Write a S_STRING */ > -static void conf_write_string(bool headerfile, const char *name, > - const char *str, FILE *out) > +/* > + * Generic printers > + */ It would not hurt to add a brief comment to each of the printers - what format it generates and where is it used. > +static void > +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > { > - int l; > - if (headerfile) > - fprintf(out, "#define %s%s \"", CONFIG_, name); > - else > - fprintf(out, "%s%s=\"", CONFIG_, name); > - > - while (1) { > - l = strcspn(str, "\"\\"); > + > + > + switch (sym->type) { > + case S_BOOLEAN: > + case S_TRISTATE: > + switch (*value) { > + case 'n': > + if (arg != NULL) > + return; I would name the argument "skip_unset" or so, to make it clear what it means in this context. > + > + fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name); > + return; > + default: > + break; > + } The inner switch statement can be replaced with a simple if (*value == 'n'). > + default: > + break; > + } > + > + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); > +} > + > +static void > +kconfig_print_comment(FILE *fp, const char *value, void *arg) > +{ > + const char *p = value; > + size_t l; > + > + for (;;) { > + l = strcspn(p, "\n"); > + fprintf(fp, "#"); > if (l) { > - xfwrite(str, l, 1, out); > - str += l; > + fprintf(fp, " "); > + fwrite(p, l, 1, fp); > + p += l; > } > - if (!*str) > + fprintf(fp, "\n"); > + if (*p++ == '\0') > break; > - fprintf(out, "\\%c", *str++); > } > - fputs("\"\n", out); > } > > -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) > +static struct conf_printer kconfig_printer_cb = > { > - const char *str; > + .print_symbol = kconfig_print_symbol, > + .print_comment = kconfig_print_comment, > +}; > + > +static void > +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > +{ > + const char *suffix = ""; > > switch (sym->type) { > case S_BOOLEAN: > case S_TRISTATE: > - switch (sym_get_tristate_value(sym)) { > - case no: > - if (write_no) > - fprintf(out, "# %s%s is not set\n", > - CONFIG_, sym->name); > - break; > - case mod: > - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); > - break; > - case yes: > - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); > - break; > + switch (*value) { > + case 'n': > + return; > + case 'm': > + suffix = "_MODULE"; Please annotate the fallthrough here. > + default: > + value = "1"; > } > break; > - case S_STRING: > - conf_write_string(false, sym->name, sym_get_string_value(sym), out); > + default: > break; > - case S_HEX: > - case S_INT: > - str = sym_get_string_value(sym); > - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); > + } > + > + fprintf(fp, "#define %s%s%s %s\n", > + CONFIG_, sym->name, suffix, value); > +} > + > +static void > +header_print_comment(FILE *fp, const char *value, void *arg) > +{ > + const char *p = value; > + size_t l; > + > + fprintf(fp, "/*\n"); > + for (;;) { > + l = strcspn(p, "\n"); > + fprintf(fp, " *"); > + if (l) { > + fprintf(fp, " "); > + fwrite(p, l, 1, fp); > + p += l; > + } > + fprintf(fp, "\n"); > + if (*p++ == '\0') > + break; > + } > + fprintf(fp, " */\n"); > +} > + > +static struct conf_printer header_printer_cb = > +{ > + .print_symbol = header_print_symbol, > + .print_comment = header_print_comment, > +}; > + > +static void > +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > +{ > + > + switch (sym->type) { > + case S_BOOLEAN: > + case S_TRISTATE: > + kconfig_print_symbol(fp, sym, value, arg); This is wrong, include/config/tristate.conf should only contain tristate options and the value needs to be uppercase ('Y' or 'M'). Michal > + break; > + default: > break; > + } > +} > + > +static struct conf_printer tristate_printer_cb = > +{ > + .print_symbol = tristate_print_symbol, > + .print_comment = kconfig_print_comment, > +}; > + > +/* > + * > + */ > + > +static void conf_write_symbol(FILE *fp, struct symbol *sym, > + struct conf_printer *printer, void *printer_arg) > +{ > + const char *str; > + > + switch (sym->type) { > case S_OTHER: > case S_UNKNOWN: > break; > + case S_STRING: > + str = sym_get_string_value(sym); > + str = sym_escape_string_value(str); > + printer->print_symbol(fp, sym, str, printer_arg); > + free((void *)str); > + break; > + default: > + str = sym_get_string_value(sym); > + printer->print_symbol(fp, sym, str, printer_arg); > } > } > > +static void > +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) > +{ > + const char *env; > + char buf[256]; > + time_t now; > + int use_timestamp = 1; > + > + time(&now); > + env = getenv("KCONFIG_NOTIMESTAMP"); > + if (env && *env) > + use_timestamp = 0; > + > + snprintf(buf, sizeof(buf), > + "\n" > + "Automatically generated file; DO NOT EDIT.\n" > + "%s\n" > + "%s", > + rootmenu.prompt->text, > + use_timestamp ? ctime(&now) : ""); > + > + printer->print_comment(fp, buf, printer_arg); > +} > + > /* > * Write out a minimal config. > * All values that has default values are skipped as this is redundant. > @@ -531,7 +649,7 @@ int conf_write_defconfig(const char *filename) > goto next_menu; > } > } > - conf_write_symbol(sym, out, true); > + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); > } > next_menu: > if (menu->list != NULL) { > @@ -561,9 +679,7 @@ int conf_write(const char *name) > const char *str; > char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; > enum symbol_type type; > - time_t now; > - int use_timestamp = 1; > - char *env; > + const char *env; > > dirname[0] = 0; > if (name && name[0]) { > @@ -599,19 +715,7 @@ int conf_write(const char *name) > if (!out) > return 1; > > - time(&now); > - env = getenv("KCONFIG_NOTIMESTAMP"); > - if (env && *env) > - use_timestamp = 0; > - > - fprintf(out, _("#\n" > - "# Automatically generated make config: don't edit\n" > - "# %s\n" > - "%s%s" > - "#\n"), > - rootmenu.prompt->text, > - use_timestamp ? "# " : "", > - use_timestamp ? ctime(&now) : ""); > + conf_write_heading(out, &kconfig_printer_cb, NULL); > > if (!conf_get_changed()) > sym_clear_all_valid(); > @@ -632,8 +736,8 @@ int conf_write(const char *name) > if (!(sym->flags & SYMBOL_WRITE)) > goto next; > sym->flags &= ~SYMBOL_WRITE; > - /* Write config symbol to file */ > - conf_write_symbol(sym, out, true); > + > + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); > } > > next: > @@ -782,10 +886,8 @@ out: > int conf_write_autoconf(void) > { > struct symbol *sym; > - const char *str; > const char *name; > FILE *out, *tristate, *out_h; > - time_t now; > int i; > > sym_clear_all_valid(); > @@ -812,71 +914,23 @@ int conf_write_autoconf(void) > return 1; > } > > - time(&now); > - fprintf(out, "#\n" > - "# Automatically generated make config: don't edit\n" > - "# %s\n" > - "# %s" > - "#\n", > - rootmenu.prompt->text, ctime(&now)); > - fprintf(tristate, "#\n" > - "# Automatically generated - do not edit\n" > - "\n"); > - fprintf(out_h, "/*\n" > - " * Automatically generated C config: don't edit\n" > - " * %s\n" > - " * %s" > - " */\n", > - rootmenu.prompt->text, ctime(&now)); > + conf_write_heading(out, &kconfig_printer_cb, NULL); > + > + conf_write_heading(tristate, &tristate_printer_cb, NULL); > + > + conf_write_heading(out_h, &header_printer_cb, NULL); > > for_all_symbols(i, sym) { > sym_calc_value(sym); > if (!(sym->flags & SYMBOL_WRITE) || !sym->name) > continue; > > - /* write symbol to config file */ > - conf_write_symbol(sym, out, false); > + /* write symbol to auto.conf, tristate and header files */ > + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); > > - /* update autoconf and tristate files */ > - switch (sym->type) { > - case S_BOOLEAN: > - case S_TRISTATE: > - switch (sym_get_tristate_value(sym)) { > - case no: > - break; > - case mod: > - fprintf(tristate, "%s%s=M\n", > - CONFIG_, sym->name); > - fprintf(out_h, "#define %s%s_MODULE 1\n", > - CONFIG_, sym->name); > - break; > - case yes: > - if (sym->type == S_TRISTATE) > - fprintf(tristate,"%s%s=Y\n", > - CONFIG_, sym->name); > - fprintf(out_h, "#define %s%s 1\n", > - CONFIG_, sym->name); > - break; > - } > - break; > - case S_STRING: > - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); > - break; > - case S_HEX: > - str = sym_get_string_value(sym); > - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { > - fprintf(out_h, "#define %s%s 0x%s\n", > - CONFIG_, sym->name, str); > - break; > - } > - case S_INT: > - str = sym_get_string_value(sym); > - fprintf(out_h, "#define %s%s %s\n", > - CONFIG_, sym->name, str); > - break; > - default: > - break; > - } > + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); > + > + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); > } > fclose(out); > fclose(tristate); > diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h > index 753cdbd..3633d5a 100644 > --- a/scripts/kconfig/lkc.h > +++ b/scripts/kconfig/lkc.h > @@ -89,6 +89,11 @@ void sym_set_change_count(int count); > void sym_add_change_count(int count); > void conf_set_all_new_symbols(enum conf_def_mode mode); > > +struct conf_printer { > + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); > + void (*print_comment)(FILE *, const char *, void *); > +}; > + > /* confdata.c and expr.c */ > static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) > { > diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h > index 17342fe..47fe9c3 100644 > --- a/scripts/kconfig/lkc_proto.h > +++ b/scripts/kconfig/lkc_proto.h > @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); > P(sym_lookup,struct symbol *,(const char *name, int flags)); > P(sym_find,struct symbol *,(const char *name)); > P(sym_expand_string_value,const char *,(const char *in)); > +P(sym_escape_string_value, const char *,(const char *in)); > P(sym_re_search,struct symbol **,(const char *pattern)); > P(sym_type_name,const char *,(enum symbol_type type)); > P(sym_calc_value,void,(struct symbol *sym)); > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c > index ad7dbe7..e42240d 100644 > --- a/scripts/kconfig/symbol.c > +++ b/scripts/kconfig/symbol.c > @@ -749,7 +749,8 @@ const char *sym_get_string_value(struct symbol *sym) > case no: > return "n"; > case mod: > - return "m"; > + sym_calc_value(modules_sym); > + return (modules_sym->curr.tri == no) ? "n" : "m"; > case yes: > return "y"; > } > @@ -891,6 +892,49 @@ const char *sym_expand_string_value(const char *in) > return res; > } > > +const char *sym_escape_string_value(const char *in) > +{ > + const char *p; > + size_t reslen; > + char *res; > + size_t l; > + > + reslen = strlen(in) + strlen("\"\"") + 1; > + > + p = in; > + for (;;) { > + l = strcspn(p, "\"\\"); > + p += l; > + > + if (p[0] == '\0') > + break; > + > + reslen++; > + p++; > + } > + > + res = malloc(reslen); > + res[0] = '\0'; > + > + strcat(res, "\""); > + > + p = in; > + for (;;) { > + l = strcspn(p, "\"\\"); > + strncat(res, p, l); > + p += l; > + > + if (p[0] == '\0') > + break; > + > + strcat(res, "\\"); > + strncat(res, p++, 1); > + } > + > + strcat(res, "\""); > + return res; > +} > + > struct symbol **sym_re_search(const char *pattern) > { > struct symbol *sym, **sym_arr = NULL; ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/2] [RFC] kconfig: introduce specialized printer 2010-12-21 16:37 ` Michal Marek @ 2010-12-21 16:42 ` Arnaud Lacombe 2011-05-16 3:42 ` [PATCHv2] " Arnaud Lacombe 1 sibling, 0 replies; 17+ messages in thread From: Arnaud Lacombe @ 2010-12-21 16:42 UTC (permalink / raw) To: Michal Marek; +Cc: linux-kbuild, Ben Hutchings Hi, 2010/12/21 Michal Marek <mmarek@suse.cz>: > On 5.12.2010 07:35, Arnaud Lacombe wrote: >> The goal of this patch is to 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 became mostly only to prepare a string for the >> printer. This avoid to have to pass specialized flag to generic functions. > > I like the idea, I only have a few comments below. > Thanks for the review, I will address your comments tonight and send an updated version of the patch. I'll certainly also split the symbol.c part to a separate entity. - Arnaud >> >> CC: Ben Hutchings <ben@decadent.org.uk> >> Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> >> --- >> scripts/kconfig/confdata.c | 284 +++++++++++++++++++++++++----------------- >> scripts/kconfig/lkc.h | 5 + >> scripts/kconfig/lkc_proto.h | 1 + >> scripts/kconfig/symbol.c | 46 +++++++- >> 4 files changed, 220 insertions(+), 116 deletions(-) >> >> diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c >> index 6fd43d7..31d06da 100644 >> --- a/scripts/kconfig/confdata.c >> +++ b/scripts/kconfig/confdata.c >> @@ -417,64 +417,182 @@ int conf_read(const char *name) >> return 0; >> } >> >> -/* Write a S_STRING */ >> -static void conf_write_string(bool headerfile, const char *name, >> - const char *str, FILE *out) >> +/* >> + * Generic printers >> + */ > > It would not hurt to add a brief comment to each of the printers - what > format it generates and where is it used. > > >> +static void >> +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) >> { >> - int l; >> - if (headerfile) >> - fprintf(out, "#define %s%s \"", CONFIG_, name); >> - else >> - fprintf(out, "%s%s=\"", CONFIG_, name); >> - >> - while (1) { >> - l = strcspn(str, "\"\\"); >> + >> + >> + switch (sym->type) { >> + case S_BOOLEAN: >> + case S_TRISTATE: >> + switch (*value) { >> + case 'n': >> + if (arg != NULL) >> + return; > > I would name the argument "skip_unset" or so, to make it clear what it > means in this context. >> + >> + fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name); >> + return; >> + default: >> + break; >> + } > > The inner switch statement can be replaced with a simple if (*value == 'n'). > > >> + default: >> + break; >> + } >> + >> + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); >> +} >> + >> +static void >> +kconfig_print_comment(FILE *fp, const char *value, void *arg) >> +{ >> + const char *p = value; >> + size_t l; >> + >> + for (;;) { >> + l = strcspn(p, "\n"); >> + fprintf(fp, "#"); >> if (l) { >> - xfwrite(str, l, 1, out); >> - str += l; >> + fprintf(fp, " "); >> + fwrite(p, l, 1, fp); >> + p += l; >> } >> - if (!*str) >> + fprintf(fp, "\n"); >> + if (*p++ == '\0') >> break; >> - fprintf(out, "\\%c", *str++); >> } >> - fputs("\"\n", out); >> } >> >> -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) >> +static struct conf_printer kconfig_printer_cb = >> { >> - const char *str; >> + .print_symbol = kconfig_print_symbol, >> + .print_comment = kconfig_print_comment, >> +}; >> + >> +static void >> +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) >> +{ >> + const char *suffix = ""; >> >> switch (sym->type) { >> case S_BOOLEAN: >> case S_TRISTATE: >> - switch (sym_get_tristate_value(sym)) { >> - case no: >> - if (write_no) >> - fprintf(out, "# %s%s is not set\n", >> - CONFIG_, sym->name); >> - break; >> - case mod: >> - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); >> - break; >> - case yes: >> - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); >> - break; >> + switch (*value) { >> + case 'n': >> + return; >> + case 'm': >> + suffix = "_MODULE"; > > Please annotate the fallthrough here. > > >> + default: >> + value = "1"; >> } >> break; >> - case S_STRING: >> - conf_write_string(false, sym->name, sym_get_string_value(sym), out); >> + default: >> break; >> - case S_HEX: >> - case S_INT: >> - str = sym_get_string_value(sym); >> - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); >> + } >> + >> + fprintf(fp, "#define %s%s%s %s\n", >> + CONFIG_, sym->name, suffix, value); >> +} >> + >> +static void >> +header_print_comment(FILE *fp, const char *value, void *arg) >> +{ >> + const char *p = value; >> + size_t l; >> + >> + fprintf(fp, "/*\n"); >> + for (;;) { >> + l = strcspn(p, "\n"); >> + fprintf(fp, " *"); >> + if (l) { >> + fprintf(fp, " "); >> + fwrite(p, l, 1, fp); >> + p += l; >> + } >> + fprintf(fp, "\n"); >> + if (*p++ == '\0') >> + break; >> + } >> + fprintf(fp, " */\n"); >> +} >> + >> +static struct conf_printer header_printer_cb = >> +{ >> + .print_symbol = header_print_symbol, >> + .print_comment = header_print_comment, >> +}; >> + >> +static void >> +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) >> +{ >> + >> + switch (sym->type) { >> + case S_BOOLEAN: >> + case S_TRISTATE: >> + kconfig_print_symbol(fp, sym, value, arg); > > This is wrong, include/config/tristate.conf should only contain tristate > options and the value needs to be uppercase ('Y' or 'M'). > > Michal > >> + break; >> + default: >> break; >> + } >> +} >> + >> +static struct conf_printer tristate_printer_cb = >> +{ >> + .print_symbol = tristate_print_symbol, >> + .print_comment = kconfig_print_comment, >> +}; >> + >> +/* >> + * >> + */ >> + >> +static void conf_write_symbol(FILE *fp, struct symbol *sym, >> + struct conf_printer *printer, void *printer_arg) >> +{ >> + const char *str; >> + >> + switch (sym->type) { >> case S_OTHER: >> case S_UNKNOWN: >> break; >> + case S_STRING: >> + str = sym_get_string_value(sym); >> + str = sym_escape_string_value(str); >> + printer->print_symbol(fp, sym, str, printer_arg); >> + free((void *)str); >> + break; >> + default: >> + str = sym_get_string_value(sym); >> + printer->print_symbol(fp, sym, str, printer_arg); >> } >> } >> >> +static void >> +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) >> +{ >> + const char *env; >> + char buf[256]; >> + time_t now; >> + int use_timestamp = 1; >> + >> + time(&now); >> + env = getenv("KCONFIG_NOTIMESTAMP"); >> + if (env && *env) >> + use_timestamp = 0; >> + >> + snprintf(buf, sizeof(buf), >> + "\n" >> + "Automatically generated file; DO NOT EDIT.\n" >> + "%s\n" >> + "%s", >> + rootmenu.prompt->text, >> + use_timestamp ? ctime(&now) : ""); >> + >> + printer->print_comment(fp, buf, printer_arg); >> +} >> + >> /* >> * Write out a minimal config. >> * All values that has default values are skipped as this is redundant. >> @@ -531,7 +649,7 @@ int conf_write_defconfig(const char *filename) >> goto next_menu; >> } >> } >> - conf_write_symbol(sym, out, true); >> + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); >> } >> next_menu: >> if (menu->list != NULL) { >> @@ -561,9 +679,7 @@ int conf_write(const char *name) >> const char *str; >> char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; >> enum symbol_type type; >> - time_t now; >> - int use_timestamp = 1; >> - char *env; >> + const char *env; >> >> dirname[0] = 0; >> if (name && name[0]) { >> @@ -599,19 +715,7 @@ int conf_write(const char *name) >> if (!out) >> return 1; >> >> - time(&now); >> - env = getenv("KCONFIG_NOTIMESTAMP"); >> - if (env && *env) >> - use_timestamp = 0; >> - >> - fprintf(out, _("#\n" >> - "# Automatically generated make config: don't edit\n" >> - "# %s\n" >> - "%s%s" >> - "#\n"), >> - rootmenu.prompt->text, >> - use_timestamp ? "# " : "", >> - use_timestamp ? ctime(&now) : ""); >> + conf_write_heading(out, &kconfig_printer_cb, NULL); >> >> if (!conf_get_changed()) >> sym_clear_all_valid(); >> @@ -632,8 +736,8 @@ int conf_write(const char *name) >> if (!(sym->flags & SYMBOL_WRITE)) >> goto next; >> sym->flags &= ~SYMBOL_WRITE; >> - /* Write config symbol to file */ >> - conf_write_symbol(sym, out, true); >> + >> + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); >> } >> >> next: >> @@ -782,10 +886,8 @@ out: >> int conf_write_autoconf(void) >> { >> struct symbol *sym; >> - const char *str; >> const char *name; >> FILE *out, *tristate, *out_h; >> - time_t now; >> int i; >> >> sym_clear_all_valid(); >> @@ -812,71 +914,23 @@ int conf_write_autoconf(void) >> return 1; >> } >> >> - time(&now); >> - fprintf(out, "#\n" >> - "# Automatically generated make config: don't edit\n" >> - "# %s\n" >> - "# %s" >> - "#\n", >> - rootmenu.prompt->text, ctime(&now)); >> - fprintf(tristate, "#\n" >> - "# Automatically generated - do not edit\n" >> - "\n"); >> - fprintf(out_h, "/*\n" >> - " * Automatically generated C config: don't edit\n" >> - " * %s\n" >> - " * %s" >> - " */\n", >> - rootmenu.prompt->text, ctime(&now)); >> + conf_write_heading(out, &kconfig_printer_cb, NULL); >> + >> + conf_write_heading(tristate, &tristate_printer_cb, NULL); >> + >> + conf_write_heading(out_h, &header_printer_cb, NULL); >> >> for_all_symbols(i, sym) { >> sym_calc_value(sym); >> if (!(sym->flags & SYMBOL_WRITE) || !sym->name) >> continue; >> >> - /* write symbol to config file */ >> - conf_write_symbol(sym, out, false); >> + /* write symbol to auto.conf, tristate and header files */ >> + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); >> >> - /* update autoconf and tristate files */ >> - switch (sym->type) { >> - case S_BOOLEAN: >> - case S_TRISTATE: >> - switch (sym_get_tristate_value(sym)) { >> - case no: >> - break; >> - case mod: >> - fprintf(tristate, "%s%s=M\n", >> - CONFIG_, sym->name); >> - fprintf(out_h, "#define %s%s_MODULE 1\n", >> - CONFIG_, sym->name); >> - break; >> - case yes: >> - if (sym->type == S_TRISTATE) >> - fprintf(tristate,"%s%s=Y\n", >> - CONFIG_, sym->name); >> - fprintf(out_h, "#define %s%s 1\n", >> - CONFIG_, sym->name); >> - break; >> - } >> - break; >> - case S_STRING: >> - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); >> - break; >> - case S_HEX: >> - str = sym_get_string_value(sym); >> - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { >> - fprintf(out_h, "#define %s%s 0x%s\n", >> - CONFIG_, sym->name, str); >> - break; >> - } >> - case S_INT: >> - str = sym_get_string_value(sym); >> - fprintf(out_h, "#define %s%s %s\n", >> - CONFIG_, sym->name, str); >> - break; >> - default: >> - break; >> - } >> + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); >> + >> + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); >> } >> fclose(out); >> fclose(tristate); >> diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h >> index 753cdbd..3633d5a 100644 >> --- a/scripts/kconfig/lkc.h >> +++ b/scripts/kconfig/lkc.h >> @@ -89,6 +89,11 @@ void sym_set_change_count(int count); >> void sym_add_change_count(int count); >> void conf_set_all_new_symbols(enum conf_def_mode mode); >> >> +struct conf_printer { >> + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); >> + void (*print_comment)(FILE *, const char *, void *); >> +}; >> + >> /* confdata.c and expr.c */ >> static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) >> { >> diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h >> index 17342fe..47fe9c3 100644 >> --- a/scripts/kconfig/lkc_proto.h >> +++ b/scripts/kconfig/lkc_proto.h >> @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); >> P(sym_lookup,struct symbol *,(const char *name, int flags)); >> P(sym_find,struct symbol *,(const char *name)); >> P(sym_expand_string_value,const char *,(const char *in)); >> +P(sym_escape_string_value, const char *,(const char *in)); >> P(sym_re_search,struct symbol **,(const char *pattern)); >> P(sym_type_name,const char *,(enum symbol_type type)); >> P(sym_calc_value,void,(struct symbol *sym)); >> diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c >> index ad7dbe7..e42240d 100644 >> --- a/scripts/kconfig/symbol.c >> +++ b/scripts/kconfig/symbol.c >> @@ -749,7 +749,8 @@ const char *sym_get_string_value(struct symbol *sym) >> case no: >> return "n"; >> case mod: >> - return "m"; >> + sym_calc_value(modules_sym); >> + return (modules_sym->curr.tri == no) ? "n" : "m"; >> case yes: >> return "y"; >> } >> @@ -891,6 +892,49 @@ const char *sym_expand_string_value(const char *in) >> return res; >> } >> >> +const char *sym_escape_string_value(const char *in) >> +{ >> + const char *p; >> + size_t reslen; >> + char *res; >> + size_t l; >> + >> + reslen = strlen(in) + strlen("\"\"") + 1; >> + >> + p = in; >> + for (;;) { >> + l = strcspn(p, "\"\\"); >> + p += l; >> + >> + if (p[0] == '\0') >> + break; >> + >> + reslen++; >> + p++; >> + } >> + >> + res = malloc(reslen); >> + res[0] = '\0'; >> + >> + strcat(res, "\""); >> + >> + p = in; >> + for (;;) { >> + l = strcspn(p, "\"\\"); >> + strncat(res, p, l); >> + p += l; >> + >> + if (p[0] == '\0') >> + break; >> + >> + strcat(res, "\\"); >> + strncat(res, p++, 1); >> + } >> + >> + strcat(res, "\""); >> + return res; >> +} >> + >> struct symbol **sym_re_search(const char *pattern) >> { >> struct symbol *sym, **sym_arr = NULL; > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCHv2] kconfig: introduce specialized printer 2010-12-21 16:37 ` Michal Marek 2010-12-21 16:42 ` Arnaud Lacombe @ 2011-05-16 3:42 ` Arnaud Lacombe 2011-05-31 1:26 ` Arnaud Lacombe 2011-06-09 13:01 ` Michal Marek 1 sibling, 2 replies; 17+ messages in thread From: Arnaud Lacombe @ 2011-05-16 3:42 UTC (permalink / raw) To: linux-kbuild; +Cc: Michal Marek, linux-kernel, Arnaud Lacombe 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> --- scripts/kconfig/confdata.c | 268 +++++++++++++++++++++++++++---------------- scripts/kconfig/lkc.h | 5 + scripts/kconfig/lkc_proto.h | 1 + scripts/kconfig/symbol.c | 46 +++++++- 4 files changed, 219 insertions(+), 101 deletions(-) History: v2: Address Michal's comment in msg-id <4D10D7DF.7040903@suse.cz>: - add brief comment before each printer - introduce a `skip_unset' variable in kconfig printer - merge inner switch in an if() statement - annotate fallthrough - fix tristate printer behavior v1: cf. https://patchwork.kernel.org/patch/380631/ diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 2bafd9a..46e92e9 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -417,64 +417,176 @@ int conf_read(const char *name) return 0; } -/* Write a S_STRING */ -static void conf_write_string(bool headerfile, const char *name, - const char *str, FILE *out) +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) { - int l; - if (headerfile) - fprintf(out, "#define %s%s \"", CONFIG_, name); - else - fprintf(out, "%s%s=\"", CONFIG_, name); - - while (1) { - l = strcspn(str, "\"\\"); + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); if (l) { - xfwrite(str, l, 1, out); - str += l; + fprintf(fp, " "); + fwrite(p, l, 1, fp); + p += l; } - if (!*str) + fprintf(fp, "\n"); + if (*p++ == '\0') break; - fprintf(out, "\\%c", *str++); } - fputs("\"\n", out); } -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) +static struct conf_printer kconfig_printer_cb = { - const char *str; + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + const char *suffix = ""; switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - if (write_no) - fprintf(out, "# %s%s is not set\n", - CONFIG_, sym->name); - break; - case mod: - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); - break; - case yes: - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); - break; + switch (*value) { + case 'n': + return; + case 'm': + suffix = "_MODULE"; + /* FALLTHROUGH */ + default: + value = "1"; } break; - case S_STRING: - conf_write_string(false, sym->name, sym_get_string_value(sym), out); - break; - case S_HEX: - case S_INT: - str = sym_get_string_value(sym); - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); + default: break; + } + + fprintf(fp, "#define %s%s%s %s\n", + CONFIG_, sym->name, suffix, value); +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + fwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { case S_OTHER: case S_UNKNOWN: break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); } } +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + /* * Write out a minimal config. * All values that has default values are skipped as this is redundant. @@ -531,7 +643,7 @@ int conf_write_defconfig(const char *filename) goto next_menu; } } - conf_write_symbol(sym, out, true); + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next_menu: if (menu->list != NULL) { @@ -596,11 +708,7 @@ int conf_write(const char *name) if (!out) return 1; - fprintf(out, _("#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "#\n"), - rootmenu.prompt->text); + conf_write_heading(out, &kconfig_printer_cb, NULL); if (!conf_get_changed()) sym_clear_all_valid(); @@ -621,8 +729,8 @@ int conf_write(const char *name) if (!(sym->flags & SYMBOL_WRITE)) goto next; sym->flags &= ~SYMBOL_WRITE; - /* Write config symbol to file */ - conf_write_symbol(sym, out, true); + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next: @@ -771,7 +879,6 @@ out: int conf_write_autoconf(void) { struct symbol *sym; - const char *str; const char *name; FILE *out, *tristate, *out_h; int i; @@ -800,68 +907,23 @@ int conf_write_autoconf(void) return 1; } - fprintf(out, "#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "#\n", - rootmenu.prompt->text); - fprintf(tristate, "#\n" - "# Automatically generated - do not edit\n" - "\n"); - fprintf(out_h, "/*\n" - " * Automatically generated C config: don't edit\n" - " * %s\n" - " */\n", - rootmenu.prompt->text); + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; - /* write symbol to config file */ - conf_write_symbol(sym, out, false); + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); - /* update autoconf and tristate files */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - break; - case mod: - fprintf(tristate, "%s%s=M\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s_MODULE 1\n", - CONFIG_, sym->name); - break; - case yes: - if (sym->type == S_TRISTATE) - fprintf(tristate,"%s%s=Y\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s 1\n", - CONFIG_, sym->name); - break; - } - break; - case S_STRING: - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); - break; - case S_HEX: - str = sym_get_string_value(sym); - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out_h, "#define %s%s 0x%s\n", - CONFIG_, sym->name, str); - break; - } - case S_INT: - str = sym_get_string_value(sym); - fprintf(out_h, "#define %s%s %s\n", - CONFIG_, sym->name, str); - break; - default: - break; - } + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); } fclose(out); fclose(tristate); diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index febf0c9..7b0db22 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -92,6 +92,11 @@ void sym_set_change_count(int count); void sym_add_change_count(int count); void conf_set_all_new_symbols(enum conf_def_mode mode); +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + /* confdata.c and expr.c */ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) { diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 17342fe..47fe9c3 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); P(sym_lookup,struct symbol *,(const char *name, int flags)); P(sym_find,struct symbol *,(const char *name)); P(sym_expand_string_value,const char *,(const char *in)); +P(sym_escape_string_value, const char *,(const char *in)); P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_type_name,const char *,(enum symbol_type type)); P(sym_calc_value,void,(struct symbol *sym)); diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index a796c95..11417a2 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -751,7 +751,8 @@ const char *sym_get_string_value(struct symbol *sym) case no: return "n"; case mod: - return "m"; + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; case yes: return "y"; } @@ -893,6 +894,49 @@ const char *sym_expand_string_value(const char *in) return res; } +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = malloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + struct symbol **sym_re_search(const char *pattern) { struct symbol *sym, **sym_arr = NULL; -- 1.7.3.4.574.g608b.dirty ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer 2011-05-16 3:42 ` [PATCHv2] " Arnaud Lacombe @ 2011-05-31 1:26 ` Arnaud Lacombe 2011-06-08 5:08 ` Arnaud Lacombe 2011-06-09 13:01 ` Michal Marek 1 sibling, 1 reply; 17+ messages in thread From: Arnaud Lacombe @ 2011-05-31 1:26 UTC (permalink / raw) To: linux-kbuild; +Cc: Michal Marek, linux-kernel Hi, On Sun, May 15, 2011 at 11:42 PM, Arnaud Lacombe <lacombar@gmail.com> wrote: > 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 > ping ? - Arnaud > Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> > --- > scripts/kconfig/confdata.c | 268 +++++++++++++++++++++++++++---------------- > scripts/kconfig/lkc.h | 5 + > scripts/kconfig/lkc_proto.h | 1 + > scripts/kconfig/symbol.c | 46 +++++++- > 4 files changed, 219 insertions(+), 101 deletions(-) > > History: > v2: Address Michal's comment in msg-id <4D10D7DF.7040903@suse.cz>: > - add brief comment before each printer > - introduce a `skip_unset' variable in kconfig printer > - merge inner switch in an if() statement > - annotate fallthrough > - fix tristate printer behavior > > v1: cf. https://patchwork.kernel.org/patch/380631/ > > diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c > index 2bafd9a..46e92e9 100644 > --- a/scripts/kconfig/confdata.c > +++ b/scripts/kconfig/confdata.c > @@ -417,64 +417,176 @@ int conf_read(const char *name) > return 0; > } > > -/* Write a S_STRING */ > -static void conf_write_string(bool headerfile, const char *name, > - const char *str, FILE *out) > +/* > + * Kconfig configuration printer > + * > + * This printer is used when generating the resulting configuration after > + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by > + * passing a non-NULL argument to the printer. > + * > + */ > +static void > +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > { > - int l; > - if (headerfile) > - fprintf(out, "#define %s%s \"", CONFIG_, name); > - else > - fprintf(out, "%s%s=\"", CONFIG_, name); > - > - while (1) { > - l = strcspn(str, "\"\\"); > + > + switch (sym->type) { > + case S_BOOLEAN: > + case S_TRISTATE: > + if (*value == 'n') { > + bool skip_unset = (arg != NULL); > + > + if (!skip_unset) > + fprintf(fp, "# %s%s is not set\n", > + CONFIG_, sym->name); > + return; > + } > + break; > + default: > + break; > + } > + > + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); > +} > + > +static void > +kconfig_print_comment(FILE *fp, const char *value, void *arg) > +{ > + const char *p = value; > + size_t l; > + > + for (;;) { > + l = strcspn(p, "\n"); > + fprintf(fp, "#"); > if (l) { > - xfwrite(str, l, 1, out); > - str += l; > + fprintf(fp, " "); > + fwrite(p, l, 1, fp); > + p += l; > } > - if (!*str) > + fprintf(fp, "\n"); > + if (*p++ == '\0') > break; > - fprintf(out, "\\%c", *str++); > } > - fputs("\"\n", out); > } > > -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) > +static struct conf_printer kconfig_printer_cb = > { > - const char *str; > + .print_symbol = kconfig_print_symbol, > + .print_comment = kconfig_print_comment, > +}; > + > +/* > + * Header printer > + * > + * This printer is used when generating the `include/generated/autoconf.h' file. > + */ > +static void > +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > +{ > + const char *suffix = ""; > > switch (sym->type) { > case S_BOOLEAN: > case S_TRISTATE: > - switch (sym_get_tristate_value(sym)) { > - case no: > - if (write_no) > - fprintf(out, "# %s%s is not set\n", > - CONFIG_, sym->name); > - break; > - case mod: > - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); > - break; > - case yes: > - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); > - break; > + switch (*value) { > + case 'n': > + return; > + case 'm': > + suffix = "_MODULE"; > + /* FALLTHROUGH */ > + default: > + value = "1"; > } > break; > - case S_STRING: > - conf_write_string(false, sym->name, sym_get_string_value(sym), out); > - break; > - case S_HEX: > - case S_INT: > - str = sym_get_string_value(sym); > - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); > + default: > break; > + } > + > + fprintf(fp, "#define %s%s%s %s\n", > + CONFIG_, sym->name, suffix, value); > +} > + > +static void > +header_print_comment(FILE *fp, const char *value, void *arg) > +{ > + const char *p = value; > + size_t l; > + > + fprintf(fp, "/*\n"); > + for (;;) { > + l = strcspn(p, "\n"); > + fprintf(fp, " *"); > + if (l) { > + fprintf(fp, " "); > + fwrite(p, l, 1, fp); > + p += l; > + } > + fprintf(fp, "\n"); > + if (*p++ == '\0') > + break; > + } > + fprintf(fp, " */\n"); > +} > + > +static struct conf_printer header_printer_cb = > +{ > + .print_symbol = header_print_symbol, > + .print_comment = header_print_comment, > +}; > + > +/* > + * Tristate printer > + * > + * This printer is used when generating the `include/config/tristate.conf' file. > + */ > +static void > +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) > +{ > + > + if (sym->type == S_TRISTATE && *value != 'n') > + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); > +} > + > +static struct conf_printer tristate_printer_cb = > +{ > + .print_symbol = tristate_print_symbol, > + .print_comment = kconfig_print_comment, > +}; > + > +static void conf_write_symbol(FILE *fp, struct symbol *sym, > + struct conf_printer *printer, void *printer_arg) > +{ > + const char *str; > + > + switch (sym->type) { > case S_OTHER: > case S_UNKNOWN: > break; > + case S_STRING: > + str = sym_get_string_value(sym); > + str = sym_escape_string_value(str); > + printer->print_symbol(fp, sym, str, printer_arg); > + free((void *)str); > + break; > + default: > + str = sym_get_string_value(sym); > + printer->print_symbol(fp, sym, str, printer_arg); > } > } > > +static void > +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) > +{ > + char buf[256]; > + > + snprintf(buf, sizeof(buf), > + "\n" > + "Automatically generated file; DO NOT EDIT.\n" > + "%s\n", > + rootmenu.prompt->text); > + > + printer->print_comment(fp, buf, printer_arg); > +} > + > /* > * Write out a minimal config. > * All values that has default values are skipped as this is redundant. > @@ -531,7 +643,7 @@ int conf_write_defconfig(const char *filename) > goto next_menu; > } > } > - conf_write_symbol(sym, out, true); > + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); > } > next_menu: > if (menu->list != NULL) { > @@ -596,11 +708,7 @@ int conf_write(const char *name) > if (!out) > return 1; > > - fprintf(out, _("#\n" > - "# Automatically generated make config: don't edit\n" > - "# %s\n" > - "#\n"), > - rootmenu.prompt->text); > + conf_write_heading(out, &kconfig_printer_cb, NULL); > > if (!conf_get_changed()) > sym_clear_all_valid(); > @@ -621,8 +729,8 @@ int conf_write(const char *name) > if (!(sym->flags & SYMBOL_WRITE)) > goto next; > sym->flags &= ~SYMBOL_WRITE; > - /* Write config symbol to file */ > - conf_write_symbol(sym, out, true); > + > + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); > } > > next: > @@ -771,7 +879,6 @@ out: > int conf_write_autoconf(void) > { > struct symbol *sym; > - const char *str; > const char *name; > FILE *out, *tristate, *out_h; > int i; > @@ -800,68 +907,23 @@ int conf_write_autoconf(void) > return 1; > } > > - fprintf(out, "#\n" > - "# Automatically generated make config: don't edit\n" > - "# %s\n" > - "#\n", > - rootmenu.prompt->text); > - fprintf(tristate, "#\n" > - "# Automatically generated - do not edit\n" > - "\n"); > - fprintf(out_h, "/*\n" > - " * Automatically generated C config: don't edit\n" > - " * %s\n" > - " */\n", > - rootmenu.prompt->text); > + conf_write_heading(out, &kconfig_printer_cb, NULL); > + > + conf_write_heading(tristate, &tristate_printer_cb, NULL); > + > + conf_write_heading(out_h, &header_printer_cb, NULL); > > for_all_symbols(i, sym) { > sym_calc_value(sym); > if (!(sym->flags & SYMBOL_WRITE) || !sym->name) > continue; > > - /* write symbol to config file */ > - conf_write_symbol(sym, out, false); > + /* write symbol to auto.conf, tristate and header files */ > + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); > > - /* update autoconf and tristate files */ > - switch (sym->type) { > - case S_BOOLEAN: > - case S_TRISTATE: > - switch (sym_get_tristate_value(sym)) { > - case no: > - break; > - case mod: > - fprintf(tristate, "%s%s=M\n", > - CONFIG_, sym->name); > - fprintf(out_h, "#define %s%s_MODULE 1\n", > - CONFIG_, sym->name); > - break; > - case yes: > - if (sym->type == S_TRISTATE) > - fprintf(tristate,"%s%s=Y\n", > - CONFIG_, sym->name); > - fprintf(out_h, "#define %s%s 1\n", > - CONFIG_, sym->name); > - break; > - } > - break; > - case S_STRING: > - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); > - break; > - case S_HEX: > - str = sym_get_string_value(sym); > - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { > - fprintf(out_h, "#define %s%s 0x%s\n", > - CONFIG_, sym->name, str); > - break; > - } > - case S_INT: > - str = sym_get_string_value(sym); > - fprintf(out_h, "#define %s%s %s\n", > - CONFIG_, sym->name, str); > - break; > - default: > - break; > - } > + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); > + > + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); > } > fclose(out); > fclose(tristate); > diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h > index febf0c9..7b0db22 100644 > --- a/scripts/kconfig/lkc.h > +++ b/scripts/kconfig/lkc.h > @@ -92,6 +92,11 @@ void sym_set_change_count(int count); > void sym_add_change_count(int count); > void conf_set_all_new_symbols(enum conf_def_mode mode); > > +struct conf_printer { > + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); > + void (*print_comment)(FILE *, const char *, void *); > +}; > + > /* confdata.c and expr.c */ > static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) > { > diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h > index 17342fe..47fe9c3 100644 > --- a/scripts/kconfig/lkc_proto.h > +++ b/scripts/kconfig/lkc_proto.h > @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); > P(sym_lookup,struct symbol *,(const char *name, int flags)); > P(sym_find,struct symbol *,(const char *name)); > P(sym_expand_string_value,const char *,(const char *in)); > +P(sym_escape_string_value, const char *,(const char *in)); > P(sym_re_search,struct symbol **,(const char *pattern)); > P(sym_type_name,const char *,(enum symbol_type type)); > P(sym_calc_value,void,(struct symbol *sym)); > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c > index a796c95..11417a2 100644 > --- a/scripts/kconfig/symbol.c > +++ b/scripts/kconfig/symbol.c > @@ -751,7 +751,8 @@ const char *sym_get_string_value(struct symbol *sym) > case no: > return "n"; > case mod: > - return "m"; > + sym_calc_value(modules_sym); > + return (modules_sym->curr.tri == no) ? "n" : "m"; > case yes: > return "y"; > } > @@ -893,6 +894,49 @@ const char *sym_expand_string_value(const char *in) > return res; > } > > +const char *sym_escape_string_value(const char *in) > +{ > + const char *p; > + size_t reslen; > + char *res; > + size_t l; > + > + reslen = strlen(in) + strlen("\"\"") + 1; > + > + p = in; > + for (;;) { > + l = strcspn(p, "\"\\"); > + p += l; > + > + if (p[0] == '\0') > + break; > + > + reslen++; > + p++; > + } > + > + res = malloc(reslen); > + res[0] = '\0'; > + > + strcat(res, "\""); > + > + p = in; > + for (;;) { > + l = strcspn(p, "\"\\"); > + strncat(res, p, l); > + p += l; > + > + if (p[0] == '\0') > + break; > + > + strcat(res, "\\"); > + strncat(res, p++, 1); > + } > + > + strcat(res, "\""); > + return res; > +} > + > struct symbol **sym_re_search(const char *pattern) > { > struct symbol *sym, **sym_arr = NULL; > -- > 1.7.3.4.574.g608b.dirty > > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer 2011-05-31 1:26 ` Arnaud Lacombe @ 2011-06-08 5:08 ` Arnaud Lacombe 0 siblings, 0 replies; 17+ messages in thread From: Arnaud Lacombe @ 2011-06-08 5:08 UTC (permalink / raw) To: linux-kbuild; +Cc: Michal Marek, linux-kernel Hi, On Mon, May 30, 2011 at 9:26 PM, Arnaud Lacombe <lacombar@gmail.com> wrote: > Hi, > > On Sun, May 15, 2011 at 11:42 PM, Arnaud Lacombe <lacombar@gmail.com> wrote: >> 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 >> > ping ? > ping^2 ? - Arnaud > - Arnaud > >> Signed-off-by: Arnaud Lacombe <lacombar@gmail.com> >> --- >> scripts/kconfig/confdata.c | 268 +++++++++++++++++++++++++++---------------- >> scripts/kconfig/lkc.h | 5 + >> scripts/kconfig/lkc_proto.h | 1 + >> scripts/kconfig/symbol.c | 46 +++++++- >> 4 files changed, 219 insertions(+), 101 deletions(-) >> >> History: >> v2: Address Michal's comment in msg-id <4D10D7DF.7040903@suse.cz>: >> - add brief comment before each printer >> - introduce a `skip_unset' variable in kconfig printer >> - merge inner switch in an if() statement >> - annotate fallthrough >> - fix tristate printer behavior >> >> v1: cf. https://patchwork.kernel.org/patch/380631/ >> >> diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c >> index 2bafd9a..46e92e9 100644 >> --- a/scripts/kconfig/confdata.c >> +++ b/scripts/kconfig/confdata.c >> @@ -417,64 +417,176 @@ int conf_read(const char *name) >> return 0; >> } >> >> -/* Write a S_STRING */ >> -static void conf_write_string(bool headerfile, const char *name, >> - const char *str, FILE *out) >> +/* >> + * Kconfig configuration printer >> + * >> + * This printer is used when generating the resulting configuration after >> + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by >> + * passing a non-NULL argument to the printer. >> + * >> + */ >> +static void >> +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) >> { >> - int l; >> - if (headerfile) >> - fprintf(out, "#define %s%s \"", CONFIG_, name); >> - else >> - fprintf(out, "%s%s=\"", CONFIG_, name); >> - >> - while (1) { >> - l = strcspn(str, "\"\\"); >> + >> + switch (sym->type) { >> + case S_BOOLEAN: >> + case S_TRISTATE: >> + if (*value == 'n') { >> + bool skip_unset = (arg != NULL); >> + >> + if (!skip_unset) >> + fprintf(fp, "# %s%s is not set\n", >> + CONFIG_, sym->name); >> + return; >> + } >> + break; >> + default: >> + break; >> + } >> + >> + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); >> +} >> + >> +static void >> +kconfig_print_comment(FILE *fp, const char *value, void *arg) >> +{ >> + const char *p = value; >> + size_t l; >> + >> + for (;;) { >> + l = strcspn(p, "\n"); >> + fprintf(fp, "#"); >> if (l) { >> - xfwrite(str, l, 1, out); >> - str += l; >> + fprintf(fp, " "); >> + fwrite(p, l, 1, fp); >> + p += l; >> } >> - if (!*str) >> + fprintf(fp, "\n"); >> + if (*p++ == '\0') >> break; >> - fprintf(out, "\\%c", *str++); >> } >> - fputs("\"\n", out); >> } >> >> -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) >> +static struct conf_printer kconfig_printer_cb = >> { >> - const char *str; >> + .print_symbol = kconfig_print_symbol, >> + .print_comment = kconfig_print_comment, >> +}; >> + >> +/* >> + * Header printer >> + * >> + * This printer is used when generating the `include/generated/autoconf.h' file. >> + */ >> +static void >> +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) >> +{ >> + const char *suffix = ""; >> >> switch (sym->type) { >> case S_BOOLEAN: >> case S_TRISTATE: >> - switch (sym_get_tristate_value(sym)) { >> - case no: >> - if (write_no) >> - fprintf(out, "# %s%s is not set\n", >> - CONFIG_, sym->name); >> - break; >> - case mod: >> - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); >> - break; >> - case yes: >> - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); >> - break; >> + switch (*value) { >> + case 'n': >> + return; >> + case 'm': >> + suffix = "_MODULE"; >> + /* FALLTHROUGH */ >> + default: >> + value = "1"; >> } >> break; >> - case S_STRING: >> - conf_write_string(false, sym->name, sym_get_string_value(sym), out); >> - break; >> - case S_HEX: >> - case S_INT: >> - str = sym_get_string_value(sym); >> - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); >> + default: >> break; >> + } >> + >> + fprintf(fp, "#define %s%s%s %s\n", >> + CONFIG_, sym->name, suffix, value); >> +} >> + >> +static void >> +header_print_comment(FILE *fp, const char *value, void *arg) >> +{ >> + const char *p = value; >> + size_t l; >> + >> + fprintf(fp, "/*\n"); >> + for (;;) { >> + l = strcspn(p, "\n"); >> + fprintf(fp, " *"); >> + if (l) { >> + fprintf(fp, " "); >> + fwrite(p, l, 1, fp); >> + p += l; >> + } >> + fprintf(fp, "\n"); >> + if (*p++ == '\0') >> + break; >> + } >> + fprintf(fp, " */\n"); >> +} >> + >> +static struct conf_printer header_printer_cb = >> +{ >> + .print_symbol = header_print_symbol, >> + .print_comment = header_print_comment, >> +}; >> + >> +/* >> + * Tristate printer >> + * >> + * This printer is used when generating the `include/config/tristate.conf' file. >> + */ >> +static void >> +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) >> +{ >> + >> + if (sym->type == S_TRISTATE && *value != 'n') >> + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); >> +} >> + >> +static struct conf_printer tristate_printer_cb = >> +{ >> + .print_symbol = tristate_print_symbol, >> + .print_comment = kconfig_print_comment, >> +}; >> + >> +static void conf_write_symbol(FILE *fp, struct symbol *sym, >> + struct conf_printer *printer, void *printer_arg) >> +{ >> + const char *str; >> + >> + switch (sym->type) { >> case S_OTHER: >> case S_UNKNOWN: >> break; >> + case S_STRING: >> + str = sym_get_string_value(sym); >> + str = sym_escape_string_value(str); >> + printer->print_symbol(fp, sym, str, printer_arg); >> + free((void *)str); >> + break; >> + default: >> + str = sym_get_string_value(sym); >> + printer->print_symbol(fp, sym, str, printer_arg); >> } >> } >> >> +static void >> +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) >> +{ >> + char buf[256]; >> + >> + snprintf(buf, sizeof(buf), >> + "\n" >> + "Automatically generated file; DO NOT EDIT.\n" >> + "%s\n", >> + rootmenu.prompt->text); >> + >> + printer->print_comment(fp, buf, printer_arg); >> +} >> + >> /* >> * Write out a minimal config. >> * All values that has default values are skipped as this is redundant. >> @@ -531,7 +643,7 @@ int conf_write_defconfig(const char *filename) >> goto next_menu; >> } >> } >> - conf_write_symbol(sym, out, true); >> + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); >> } >> next_menu: >> if (menu->list != NULL) { >> @@ -596,11 +708,7 @@ int conf_write(const char *name) >> if (!out) >> return 1; >> >> - fprintf(out, _("#\n" >> - "# Automatically generated make config: don't edit\n" >> - "# %s\n" >> - "#\n"), >> - rootmenu.prompt->text); >> + conf_write_heading(out, &kconfig_printer_cb, NULL); >> >> if (!conf_get_changed()) >> sym_clear_all_valid(); >> @@ -621,8 +729,8 @@ int conf_write(const char *name) >> if (!(sym->flags & SYMBOL_WRITE)) >> goto next; >> sym->flags &= ~SYMBOL_WRITE; >> - /* Write config symbol to file */ >> - conf_write_symbol(sym, out, true); >> + >> + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); >> } >> >> next: >> @@ -771,7 +879,6 @@ out: >> int conf_write_autoconf(void) >> { >> struct symbol *sym; >> - const char *str; >> const char *name; >> FILE *out, *tristate, *out_h; >> int i; >> @@ -800,68 +907,23 @@ int conf_write_autoconf(void) >> return 1; >> } >> >> - fprintf(out, "#\n" >> - "# Automatically generated make config: don't edit\n" >> - "# %s\n" >> - "#\n", >> - rootmenu.prompt->text); >> - fprintf(tristate, "#\n" >> - "# Automatically generated - do not edit\n" >> - "\n"); >> - fprintf(out_h, "/*\n" >> - " * Automatically generated C config: don't edit\n" >> - " * %s\n" >> - " */\n", >> - rootmenu.prompt->text); >> + conf_write_heading(out, &kconfig_printer_cb, NULL); >> + >> + conf_write_heading(tristate, &tristate_printer_cb, NULL); >> + >> + conf_write_heading(out_h, &header_printer_cb, NULL); >> >> for_all_symbols(i, sym) { >> sym_calc_value(sym); >> if (!(sym->flags & SYMBOL_WRITE) || !sym->name) >> continue; >> >> - /* write symbol to config file */ >> - conf_write_symbol(sym, out, false); >> + /* write symbol to auto.conf, tristate and header files */ >> + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); >> >> - /* update autoconf and tristate files */ >> - switch (sym->type) { >> - case S_BOOLEAN: >> - case S_TRISTATE: >> - switch (sym_get_tristate_value(sym)) { >> - case no: >> - break; >> - case mod: >> - fprintf(tristate, "%s%s=M\n", >> - CONFIG_, sym->name); >> - fprintf(out_h, "#define %s%s_MODULE 1\n", >> - CONFIG_, sym->name); >> - break; >> - case yes: >> - if (sym->type == S_TRISTATE) >> - fprintf(tristate,"%s%s=Y\n", >> - CONFIG_, sym->name); >> - fprintf(out_h, "#define %s%s 1\n", >> - CONFIG_, sym->name); >> - break; >> - } >> - break; >> - case S_STRING: >> - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); >> - break; >> - case S_HEX: >> - str = sym_get_string_value(sym); >> - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { >> - fprintf(out_h, "#define %s%s 0x%s\n", >> - CONFIG_, sym->name, str); >> - break; >> - } >> - case S_INT: >> - str = sym_get_string_value(sym); >> - fprintf(out_h, "#define %s%s %s\n", >> - CONFIG_, sym->name, str); >> - break; >> - default: >> - break; >> - } >> + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); >> + >> + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); >> } >> fclose(out); >> fclose(tristate); >> diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h >> index febf0c9..7b0db22 100644 >> --- a/scripts/kconfig/lkc.h >> +++ b/scripts/kconfig/lkc.h >> @@ -92,6 +92,11 @@ void sym_set_change_count(int count); >> void sym_add_change_count(int count); >> void conf_set_all_new_symbols(enum conf_def_mode mode); >> >> +struct conf_printer { >> + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); >> + void (*print_comment)(FILE *, const char *, void *); >> +}; >> + >> /* confdata.c and expr.c */ >> static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) >> { >> diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h >> index 17342fe..47fe9c3 100644 >> --- a/scripts/kconfig/lkc_proto.h >> +++ b/scripts/kconfig/lkc_proto.h >> @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); >> P(sym_lookup,struct symbol *,(const char *name, int flags)); >> P(sym_find,struct symbol *,(const char *name)); >> P(sym_expand_string_value,const char *,(const char *in)); >> +P(sym_escape_string_value, const char *,(const char *in)); >> P(sym_re_search,struct symbol **,(const char *pattern)); >> P(sym_type_name,const char *,(enum symbol_type type)); >> P(sym_calc_value,void,(struct symbol *sym)); >> diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c >> index a796c95..11417a2 100644 >> --- a/scripts/kconfig/symbol.c >> +++ b/scripts/kconfig/symbol.c >> @@ -751,7 +751,8 @@ const char *sym_get_string_value(struct symbol *sym) >> case no: >> return "n"; >> case mod: >> - return "m"; >> + sym_calc_value(modules_sym); >> + return (modules_sym->curr.tri == no) ? "n" : "m"; >> case yes: >> return "y"; >> } >> @@ -893,6 +894,49 @@ const char *sym_expand_string_value(const char *in) >> return res; >> } >> >> +const char *sym_escape_string_value(const char *in) >> +{ >> + const char *p; >> + size_t reslen; >> + char *res; >> + size_t l; >> + >> + reslen = strlen(in) + strlen("\"\"") + 1; >> + >> + p = in; >> + for (;;) { >> + l = strcspn(p, "\"\\"); >> + p += l; >> + >> + if (p[0] == '\0') >> + break; >> + >> + reslen++; >> + p++; >> + } >> + >> + res = malloc(reslen); >> + res[0] = '\0'; >> + >> + strcat(res, "\""); >> + >> + p = in; >> + for (;;) { >> + l = strcspn(p, "\"\\"); >> + strncat(res, p, l); >> + p += l; >> + >> + if (p[0] == '\0') >> + break; >> + >> + strcat(res, "\\"); >> + strncat(res, p++, 1); >> + } >> + >> + strcat(res, "\""); >> + return res; >> +} >> + >> struct symbol **sym_re_search(const char *pattern) >> { >> struct symbol *sym, **sym_arr = NULL; >> -- >> 1.7.3.4.574.g608b.dirty >> >> > ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer 2011-05-16 3:42 ` [PATCHv2] " Arnaud Lacombe 2011-05-31 1:26 ` Arnaud Lacombe @ 2011-06-09 13:01 ` Michal Marek 2011-07-01 14:51 ` Michal Marek 2011-07-07 1:34 ` Arnaud Lacombe 1 sibling, 2 replies; 17+ messages in thread From: Michal Marek @ 2011-06-09 13:01 UTC (permalink / raw) To: Arnaud Lacombe Cc: linux-kbuild, linux-kernel, Jean-Christophe PLAGNIOL-VILLARD On Sun, May 15, 2011 at 11:42:09PM -0400, Arnaud Lacombe wrote: > 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> > --- > scripts/kconfig/confdata.c | 268 +++++++++++++++++++++++++++---------------- > scripts/kconfig/lkc.h | 5 + > scripts/kconfig/lkc_proto.h | 1 + > scripts/kconfig/symbol.c | 46 +++++++- > 4 files changed, 219 insertions(+), 101 deletions(-) > > History: > v2: Address Michal's comment in msg-id <4D10D7DF.7040903@suse.cz>: > - add brief comment before each printer > - introduce a `skip_unset' variable in kconfig printer > - merge inner switch in an if() statement > - annotate fallthrough > - fix tristate printer behavior Hi, below is my merge with current kbuild-2.6.git#kconfig, notably with the config_is_xxx() stuff (which we should finalize somehow, but that's not the point here). Please review, thanks. Subject: [PATCH] kconfig: introduce specialized printer Rebase of Arnaud's patch on top of "kconfig: autogenerated config_is_xxx macro". diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index a49cf4f..be6952c 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -422,64 +422,228 @@ int conf_read(const char *name) return 0; } -/* Write a S_STRING */ -static void conf_write_string(bool headerfile, const char *name, - const char *str, FILE *out) +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) { - int l; - if (headerfile) - fprintf(out, "#define %s%s \"", CONFIG_, name); - else - fprintf(out, "%s%s=\"", CONFIG_, name); - - while (1) { - l = strcspn(str, "\"\\"); + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); if (l) { - xfwrite(str, l, 1, out); - str += l; + fprintf(fp, " "); + fwrite(p, l, 1, fp); + p += l; } - if (!*str) + fprintf(fp, "\n"); + if (*p++ == '\0') break; - fprintf(out, "\\%c", *str++); } - fputs("\"\n", out); } -static void conf_write_symbol(struct symbol *sym, FILE *out, bool write_no) +static struct conf_printer kconfig_printer_cb = { - const char *str; + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + const char *suffix = ""; switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - if (write_no) - fprintf(out, "# %s%s is not set\n", - CONFIG_, sym->name); - break; - case mod: - fprintf(out, "%s%s=m\n", CONFIG_, sym->name); - break; - case yes: - fprintf(out, "%s%s=y\n", CONFIG_, sym->name); - break; + switch (*value) { + case 'n': + return; + case 'm': + suffix = "_MODULE"; + /* FALLTHROUGH */ + default: + value = "1"; } break; - case S_STRING: - conf_write_string(false, sym->name, sym_get_string_value(sym), out); + default: break; - case S_HEX: - case S_INT: - str = sym_get_string_value(sym); - fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str); + } + + fprintf(fp, "#define %s%s%s %s\n", + CONFIG_, sym->name, suffix, value); +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + fwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Function-style header printer + * + * This printer is used to generate the config_is_xxx() function-style macros + * in `include/generated/autoconf.h' + */ +static void +header_function_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + int val = 0; + char c; + char *tmp, *d; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: break; + default: + return; + } + if (*value == 'm') + val = 2; + else if (*value == 'y') + val = 1; + + d = strdup(CONFIG_); + tmp = d; + while ((c = *d)) { + *d = tolower(c); + d++; + } + + fprintf(fp, "#define %sis_", tmp); + free(tmp); + + d = strdup(sym->name); + tmp = d; + while ((c = *d)) { + *d = tolower(c); + d++; + } + fprintf(fp, "%s%s() %d\n", tmp, (val > 1) ? "_module" : "", + val ? 1 : 0); + free(tmp); +} + +static struct conf_printer header_function_printer_cb = +{ + .print_symbol = header_function_print_symbol, +}; + + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { case S_OTHER: case S_UNKNOWN: break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); } } +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + /* * Write out a minimal config. * All values that has default values are skipped as this is redundant. @@ -536,7 +700,7 @@ int conf_write_defconfig(const char *filename) goto next_menu; } } - conf_write_symbol(sym, out, true); + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next_menu: if (menu->list != NULL) { @@ -601,11 +765,7 @@ int conf_write(const char *name) if (!out) return 1; - fprintf(out, _("#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "#\n"), - rootmenu.prompt->text); + conf_write_heading(out, &kconfig_printer_cb, NULL); if (!conf_get_changed()) sym_clear_all_valid(); @@ -626,8 +786,8 @@ int conf_write(const char *name) if (!(sym->flags & SYMBOL_WRITE)) goto next; sym->flags &= ~SYMBOL_WRITE; - /* Write config symbol to file */ - conf_write_symbol(sym, out, true); + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); } next: @@ -773,33 +933,9 @@ out: return res; } -static void conf_write_function_autoconf(FILE *out, char* conf, char* name, - int val) -{ - char c; - char *tmp, *d; - - d = strdup(conf); - tmp = d; - while ((c = *conf++)) - *d++ = tolower(c); - - fprintf(out, "#define %sis_", tmp); - free(tmp); - - d = strdup(name); - tmp = d; - while ((c = *name++)) - *d++ = tolower(c); - fprintf(out, "%s%s() %d\n", tmp, (val > 1) ? "_module" : "", - val ? 1 : 0); - free(tmp); -} - int conf_write_autoconf(void) { struct symbol *sym; - const char *str; const char *name; FILE *out, *tristate, *out_h; int i; @@ -828,72 +964,24 @@ int conf_write_autoconf(void) return 1; } - fprintf(out, "#\n" - "# Automatically generated make config: don't edit\n" - "# %s\n" - "#\n", - rootmenu.prompt->text); - fprintf(tristate, "#\n" - "# Automatically generated - do not edit\n" - "\n"); - fprintf(out_h, "/*\n" - " * Automatically generated C config: don't edit\n" - " * %s\n" - " */\n", - rootmenu.prompt->text); + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); for_all_symbols(i, sym) { - int fct_val = 0; sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE) || !sym->name) continue; - /* write symbol to config file */ - conf_write_symbol(sym, out, false); + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); - /* update autoconf and tristate files */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - break; - case mod: - fprintf(tristate, "%s%s=M\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s_MODULE 1\n", - CONFIG_, sym->name); - fct_val = 2; - break; - case yes: - if (sym->type == S_TRISTATE) - fprintf(tristate,"%s%s=Y\n", - CONFIG_, sym->name); - fprintf(out_h, "#define %s%s 1\n", - CONFIG_, sym->name); - fct_val = 1; - break; - } - conf_write_function_autoconf(out_h, CONFIG_, sym->name, fct_val); - break; - case S_STRING: - conf_write_string(true, sym->name, sym_get_string_value(sym), out_h); - break; - case S_HEX: - str = sym_get_string_value(sym); - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out_h, "#define %s%s 0x%s\n", - CONFIG_, sym->name, str); - break; - } - case S_INT: - str = sym_get_string_value(sym); - fprintf(out_h, "#define %s%s %s\n", - CONFIG_, sym->name, str); - break; - default: - break; - } + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); + conf_write_symbol(out_h, sym, &header_function_printer_cb, NULL); } fclose(out); fclose(tristate); diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 625ec69..306c5a5 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -87,6 +87,11 @@ void sym_set_change_count(int count); void sym_add_change_count(int count); void conf_set_all_new_symbols(enum conf_def_mode mode); +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + /* confdata.c and expr.c */ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) { diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 17342fe..47fe9c3 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -31,6 +31,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); P(sym_lookup,struct symbol *,(const char *name, int flags)); P(sym_find,struct symbol *,(const char *name)); P(sym_expand_string_value,const char *,(const char *in)); +P(sym_escape_string_value, const char *,(const char *in)); P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_type_name,const char *,(enum symbol_type type)); P(sym_calc_value,void,(struct symbol *sym)); diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index cf8edf4..071f00c 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -750,7 +750,8 @@ const char *sym_get_string_value(struct symbol *sym) case no: return "n"; case mod: - return "m"; + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; case yes: return "y"; } @@ -892,6 +893,49 @@ const char *sym_expand_string_value(const char *in) return res; } +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = malloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + struct symbol **sym_re_search(const char *pattern) { struct symbol *sym, **sym_arr = NULL; ^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer 2011-06-09 13:01 ` Michal Marek @ 2011-07-01 14:51 ` Michal Marek 2011-07-07 1:34 ` Arnaud Lacombe 1 sibling, 0 replies; 17+ messages in thread From: Michal Marek @ 2011-07-01 14:51 UTC (permalink / raw) To: Arnaud Lacombe Cc: linux-kbuild, linux-kernel, Jean-Christophe PLAGNIOL-VILLARD On 9.6.2011 15:01, Michal Marek wrote: > On Sun, May 15, 2011 at 11:42:09PM -0400, Arnaud Lacombe wrote: >> 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> >> --- >> scripts/kconfig/confdata.c | 268 +++++++++++++++++++++++++++---------------- >> scripts/kconfig/lkc.h | 5 + >> scripts/kconfig/lkc_proto.h | 1 + >> scripts/kconfig/symbol.c | 46 +++++++- >> 4 files changed, 219 insertions(+), 101 deletions(-) >> >> History: >> v2: Address Michal's comment in msg-id<4D10D7DF.7040903@suse.cz>: >> - add brief comment before each printer >> - introduce a `skip_unset' variable in kconfig printer >> - merge inner switch in an if() statement >> - annotate fallthrough >> - fix tristate printer behavior > > Hi, > > below is my merge with current kbuild-2.6.git#kconfig, notably with the > config_is_xxx() stuff (which we should finalize somehow, but that's not > the point here). Please review, thanks. > > > Subject: [PATCH] kconfig: introduce specialized printer > > Rebase of Arnaud's patch on top of "kconfig: autogenerated config_is_xxx > macro". Pushed to kbuild-2.6.git#kconfig. Michal ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer 2011-06-09 13:01 ` Michal Marek 2011-07-01 14:51 ` Michal Marek @ 2011-07-07 1:34 ` Arnaud Lacombe 2011-07-08 17:01 ` Sam Ravnborg 1 sibling, 1 reply; 17+ messages in thread From: Arnaud Lacombe @ 2011-07-07 1:34 UTC (permalink / raw) To: Michal Marek; +Cc: linux-kbuild, linux-kernel, Jean-Christophe PLAGNIOL-VILLARD Hi, On Thu, Jun 9, 2011 at 9:01 AM, Michal Marek <mmarek@suse.cz> wrote: > On Sun, May 15, 2011 at 11:42:09PM -0400, Arnaud Lacombe wrote: >> 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> >> --- >> scripts/kconfig/confdata.c | 268 +++++++++++++++++++++++++++---------------- >> scripts/kconfig/lkc.h | 5 + >> scripts/kconfig/lkc_proto.h | 1 + >> scripts/kconfig/symbol.c | 46 +++++++- >> 4 files changed, 219 insertions(+), 101 deletions(-) >> >> History: >> v2: Address Michal's comment in msg-id <4D10D7DF.7040903@suse.cz>: >> - add brief comment before each printer >> - introduce a `skip_unset' variable in kconfig printer >> - merge inner switch in an if() statement >> - annotate fallthrough >> - fix tristate printer behavior > > Hi, > > below is my merge with current kbuild-2.6.git#kconfig, notably with the > config_is_xxx() stuff (which we should finalize somehow, but that's not > the point here). Please review, thanks. > > > Subject: [PATCH] kconfig: introduce specialized printer > > Rebase of Arnaud's patch on top of "kconfig: autogenerated config_is_xxx > macro". > Unless error of my part, there has not been much discussion over this config_is_xxx() syntax and the issue raised by you, Sam, and I, as you mentioned in the last merge window pull-request. Regards, - Arnaud ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer 2011-07-07 1:34 ` Arnaud Lacombe @ 2011-07-08 17:01 ` Sam Ravnborg 0 siblings, 0 replies; 17+ messages in thread From: Sam Ravnborg @ 2011-07-08 17:01 UTC (permalink / raw) To: Arnaud Lacombe Cc: Michal Marek, linux-kbuild, linux-kernel, Jean-Christophe PLAGNIOL-VILLARD > > > > Subject: [PATCH] kconfig: introduce specialized printer > > > > Rebase of Arnaud's patch on top of "kconfig: autogenerated config_is_xxx > > macro". > > > Unless error of my part, there has not been much discussion over this > config_is_xxx() syntax and the issue raised by you, Sam, and I, as you > mentioned in the last merge window pull-request. I have been offline for a couple of weeks now. What is the current status? Sam ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2011-07-08 17:08 UTC | newest] Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-12-05 6:35 [PATCH 1/2] [RFC] kconfig: introduce specialized printer Arnaud Lacombe 2010-12-05 6:35 ` [PATCH 2/2] [RFC] kconfig/listnewconfig: show default value of new symbel Arnaud Lacombe 2010-12-15 6:28 ` Arnaud Lacombe 2010-12-21 16:47 ` Michal Marek 2010-12-21 17:54 ` Arnaud Lacombe 2010-12-22 4:44 ` Ben Hutchings 2010-12-22 5:39 ` Arnaud Lacombe 2010-12-15 6:27 ` [PATCH 1/2] [RFC] kconfig: introduce specialized printer Arnaud Lacombe 2010-12-21 16:37 ` Michal Marek 2010-12-21 16:42 ` Arnaud Lacombe 2011-05-16 3:42 ` [PATCHv2] " Arnaud Lacombe 2011-05-31 1:26 ` Arnaud Lacombe 2011-06-08 5:08 ` Arnaud Lacombe 2011-06-09 13:01 ` Michal Marek 2011-07-01 14:51 ` Michal Marek 2011-07-07 1:34 ` Arnaud Lacombe 2011-07-08 17:01 ` Sam Ravnborg
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.