diff options
Diffstat (limited to 'scripts/kconfig/confdata.c')
| -rw-r--r-- | scripts/kconfig/confdata.c | 293 | 
1 files changed, 193 insertions, 100 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 2bafd9a7c8d..59b667cae5f 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -7,13 +7,13 @@  #include <ctype.h>  #include <errno.h>  #include <fcntl.h> +#include <stdarg.h>  #include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <time.h>  #include <unistd.h> -#define LKC_DIRECT_LINK  #include "lkc.h"  static void conf_warning(const char *fmt, ...) @@ -128,6 +128,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)  			sym->flags |= def_flags;  			break;  		} +		/* fall through */  	case S_BOOLEAN:  		if (p[0] == 'y') {  			sym->def[def].tri = yes; @@ -140,7 +141,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)  			break;  		}  		conf_warning("symbol value '%s' invalid for %s", p, sym->name); -		break; +		return 1;  	case S_OTHER:  		if (*p != '"') {  			for (p2 = p; *p2 && !isspace(*p2); p2++) @@ -148,6 +149,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)  			sym->type = S_STRING;  			goto done;  		} +		/* fall through */  	case S_STRING:  		if (*p++ != '"')  			break; @@ -162,6 +164,7 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)  			conf_warning("invalid string found");  			return 1;  		} +		/* fall through */  	case S_INT:  	case S_HEX:  	done: @@ -237,6 +240,7 @@ load:  		case S_STRING:  			if (sym->def[def].val)  				free(sym->def[def].val); +			/* fall through */  		default:  			sym->def[def].val = NULL;  			sym->def[def].tri = no; @@ -363,6 +367,7 @@ int conf_read(const char *name)  					break;  				if (!sym_is_choice(sym))  					goto sym_ok; +				/* fall through */  			default:  				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))  					goto sym_ok; @@ -417,64 +422,202 @@ 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 = +{ +	.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 *str;  	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); +	case S_TRISTATE: { +		const char *suffix = ""; + +		switch (*value) { +		case 'n':  			break; +		case 'm': +			suffix = "_MODULE"; +			/* fall through */ +		default: +			fprintf(fp, "#define %s%s%s 1\n", +			    CONFIG_, sym->name, suffix);  		} +		/* +		 * Generate the __enabled_CONFIG_* and +		 * __enabled_CONFIG_*_MODULE macros for use by the +		 * IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is +		 * generated even for booleans so that the IS_ENABLED() macro +		 * works. +		 */ +		fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n", +				sym->name, (*value == 'y')); +		fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n", +				sym->name, (*value == 'm'));  		break; -	case S_STRING: -		conf_write_string(false, sym->name, sym_get_string_value(sym), out); +	} +	case S_HEX: { +		const char *prefix = ""; + +		if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) +			prefix = "0x"; +		fprintf(fp, "#define %s%s %s%s\n", +		    CONFIG_, sym->name, prefix, value);  		break; -	case S_HEX: +	} +	case S_STRING:  	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\n", +		    CONFIG_, sym->name, value); +		break; +	default:  		break; +	} + +} + +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 +674,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 +739,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 +760,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 +910,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 +938,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);  |