All of lore.kernel.org
 help / color / mirror / Atom feed
* [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 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 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 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

* 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

* [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.