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@xxxxxxxxxxxxxxx> > Signed-off-by: Arnaud Lacombe <lacombar@xxxxxxxxx> > --- > 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; -- To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html