* [PATCHv2] kconfig: introduce specialized printer
[not found] <4D10D7DF.7040903@suse.cz>
@ 2011-05-16 3:42 ` Arnaud Lacombe
2011-05-31 1:26 ` Arnaud Lacombe
2011-06-09 13:01 ` Michal Marek
0 siblings, 2 replies; 7+ 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] 7+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer
2011-05-16 3:42 ` [PATCHv2] kconfig: introduce specialized printer 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; 7+ 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] 7+ 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; 7+ 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] 7+ messages in thread
* Re: [PATCHv2] kconfig: introduce specialized printer
2011-05-16 3:42 ` [PATCHv2] kconfig: introduce specialized printer 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; 7+ 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] 7+ 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; 7+ 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] 7+ 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; 7+ 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] 7+ 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; 7+ 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] 7+ messages in thread
end of thread, other threads:[~2011-07-08 17:08 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <4D10D7DF.7040903@suse.cz>
2011-05-16 3:42 ` [PATCHv2] kconfig: introduce specialized printer 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).