From: Michal Marek <mmarek@suse.cz>
To: Arnaud Lacombe <lacombar@gmail.com>
Cc: linux-kbuild@vger.kernel.org, Ben Hutchings <ben@decadent.org.uk>
Subject: Re: [PATCH 1/2] [RFC] kconfig: introduce specialized printer
Date: Tue, 21 Dec 2010 17:37:51 +0100 [thread overview]
Message-ID: <4D10D7DF.7040903@suse.cz> (raw)
In-Reply-To: <1291530919-5601-1-git-send-email-lacombar@gmail.com>
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;
next prev parent reply other threads:[~2010-12-21 16:37 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D10D7DF.7040903@suse.cz \
--to=mmarek@suse.cz \
--cc=ben@decadent.org.uk \
--cc=lacombar@gmail.com \
--cc=linux-kbuild@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox