1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
4 */
5
6#include <sys/stat.h>
7#include <ctype.h>
8#include <fcntl.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <time.h>
13#include <unistd.h>
14
15#define LKC_DIRECT_LINK
16#include "lkc.h"
17
18static void conf_warning(const char *fmt, ...)
19	__attribute__ ((format (printf, 1, 2)));
20
21static const char *conf_filename;
22static int conf_lineno, conf_warnings, conf_unsaved;
23
24const char conf_defname[] = "arch/$ARCH/defconfig";
25
26static void conf_warning(const char *fmt, ...)
27{
28	va_list ap;
29	va_start(ap, fmt);
30	fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
31	vfprintf(stderr, fmt, ap);
32	fprintf(stderr, "\n");
33	va_end(ap);
34	conf_warnings++;
35}
36
37const char *conf_get_configname(void)
38{
39	char *name = getenv("KCONFIG_CONFIG");
40
41	return name ? name : ".config";
42}
43
44static char *conf_expand_value(const char *in)
45{
46	struct symbol *sym;
47	const char *src;
48	static char res_value[SYMBOL_MAXLENGTH];
49	char *dst, name[SYMBOL_MAXLENGTH];
50
51	res_value[0] = 0;
52	dst = name;
53	while ((src = strchr(in, '$'))) {
54		strncat(res_value, in, src - in);
55		src++;
56		dst = name;
57		while (isalnum(*src) || *src == '_')
58			*dst++ = *src++;
59		*dst = 0;
60		sym = sym_lookup(name, 0);
61		sym_calc_value(sym);
62		strcat(res_value, sym_get_string_value(sym));
63		in = src;
64	}
65	strcat(res_value, in);
66
67	return res_value;
68}
69
70char *conf_get_default_confname(void)
71{
72	struct stat buf;
73	static char fullname[PATH_MAX+1];
74	char *env, *name;
75
76	name = conf_expand_value(conf_defname);
77	env = getenv(SRCTREE);
78	if (env) {
79		sprintf(fullname, "%s/%s", env, name);
80		if (!stat(fullname, &buf))
81			return fullname;
82	}
83	return name;
84}
85
86int conf_read_simple(const char *name, int def)
87{
88	FILE *in = NULL;
89	char line[1024];
90	char *p, *p2;
91	struct symbol *sym;
92	int i, def_flags;
93
94	if (name) {
95		in = zconf_fopen(name);
96	} else {
97		struct property *prop;
98
99		name = conf_get_configname();
100		in = zconf_fopen(name);
101		if (in)
102			goto load;
103		sym_add_change_count(1);
104		if (!sym_defconfig_list)
105			return 1;
106
107		for_all_defaults(sym_defconfig_list, prop) {
108			if (expr_calc_value(prop->visible.expr) == no ||
109			    prop->expr->type != E_SYMBOL)
110				continue;
111			name = conf_expand_value(prop->expr->left.sym->name);
112			in = zconf_fopen(name);
113			if (in) {
114				printf(_("#\n"
115					 "# using defaults found in %s\n"
116					 "#\n"), name);
117				goto load;
118			}
119		}
120	}
121	if (!in)
122		return 1;
123
124load:
125	conf_filename = name;
126	conf_lineno = 0;
127	conf_warnings = 0;
128	conf_unsaved = 0;
129
130	def_flags = SYMBOL_DEF << def;
131	for_all_symbols(i, sym) {
132		sym->flags |= SYMBOL_CHANGED;
133		sym->flags &= ~(def_flags|SYMBOL_VALID);
134		if (sym_is_choice(sym))
135			sym->flags |= def_flags;
136		switch (sym->type) {
137		case S_INT:
138		case S_HEX:
139		case S_STRING:
140			if (sym->def[def].val)
141				free(sym->def[def].val);
142		default:
143			sym->def[def].val = NULL;
144			sym->def[def].tri = no;
145		}
146	}
147
148	while (fgets(line, sizeof(line), in)) {
149		conf_lineno++;
150		sym = NULL;
151		switch (line[0]) {
152		case '#':
153			if (memcmp(line + 2, "CONFIG_", 7))
154				continue;
155			p = strchr(line + 9, ' ');
156			if (!p)
157				continue;
158			*p++ = 0;
159			if (strncmp(p, "is not set", 10))
160				continue;
161			if (def == S_DEF_USER) {
162				sym = sym_find(line + 9);
163				if (!sym) {
164					conf_warning("trying to assign nonexistent symbol %s", line + 9);
165					break;
166				}
167			} else {
168				sym = sym_lookup(line + 9, 0);
169				if (sym->type == S_UNKNOWN)
170					sym->type = S_BOOLEAN;
171			}
172			if (sym->flags & def_flags) {
173				conf_warning("trying to reassign symbol %s", sym->name);
174				break;
175			}
176			switch (sym->type) {
177			case S_BOOLEAN:
178			case S_TRISTATE:
179				sym->def[def].tri = no;
180				sym->flags |= def_flags;
181				break;
182			default:
183				;
184			}
185			break;
186		case 'C':
187			if (memcmp(line, "CONFIG_", 7)) {
188				conf_warning("unexpected data");
189				continue;
190			}
191			p = strchr(line + 7, '=');
192			if (!p)
193				continue;
194			*p++ = 0;
195			p2 = strchr(p, '\n');
196			if (p2) {
197				*p2-- = 0;
198				if (*p2 == '\r')
199					*p2 = 0;
200			}
201			if (def == S_DEF_USER) {
202				sym = sym_find(line + 7);
203				if (!sym) {
204					conf_warning("trying to assign nonexistent symbol %s", line + 7);
205					break;
206				}
207			} else {
208				sym = sym_lookup(line + 7, 0);
209				if (sym->type == S_UNKNOWN)
210					sym->type = S_OTHER;
211			}
212			if (sym->flags & def_flags) {
213				conf_warning("trying to reassign symbol %s", sym->name);
214				break;
215			}
216			switch (sym->type) {
217			case S_TRISTATE:
218				if (p[0] == 'm') {
219					sym->def[def].tri = mod;
220					sym->flags |= def_flags;
221					break;
222				}
223			case S_BOOLEAN:
224				if (p[0] == 'y') {
225					sym->def[def].tri = yes;
226					sym->flags |= def_flags;
227					break;
228				}
229				if (p[0] == 'n') {
230					sym->def[def].tri = no;
231					sym->flags |= def_flags;
232					break;
233				}
234				conf_warning("symbol value '%s' invalid for %s", p, sym->name);
235				break;
236			case S_OTHER:
237				if (*p != '"') {
238					for (p2 = p; *p2 && !isspace(*p2); p2++)
239						;
240					sym->type = S_STRING;
241					goto done;
242				}
243			case S_STRING:
244				if (*p++ != '"')
245					break;
246				for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
247					if (*p2 == '"') {
248						*p2 = 0;
249						break;
250					}
251					memmove(p2, p2 + 1, strlen(p2));
252				}
253				if (!p2) {
254					conf_warning("invalid string found");
255					continue;
256				}
257			case S_INT:
258			case S_HEX:
259			done:
260				if (sym_string_valid(sym, p)) {
261					sym->def[def].val = strdup(p);
262					sym->flags |= def_flags;
263				} else {
264					conf_warning("symbol value '%s' invalid for %s", p, sym->name);
265					continue;
266				}
267				break;
268			default:
269				;
270			}
271			break;
272		case '\r':
273		case '\n':
274			break;
275		default:
276			conf_warning("unexpected data");
277			continue;
278		}
279		if (sym && sym_is_choice_value(sym)) {
280			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
281			switch (sym->def[def].tri) {
282			case no:
283				break;
284			case mod:
285				if (cs->def[def].tri == yes) {
286					conf_warning("%s creates inconsistent choice state", sym->name);
287					cs->flags &= ~def_flags;
288				}
289				break;
290			case yes:
291				if (cs->def[def].tri != no) {
292					conf_warning("%s creates inconsistent choice state", sym->name);
293					cs->flags &= ~def_flags;
294				} else
295					cs->def[def].val = sym;
296				break;
297			}
298			cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
299		}
300	}
301	fclose(in);
302
303	if (modules_sym)
304		sym_calc_value(modules_sym);
305	return 0;
306}
307
308int conf_read(const char *name)
309{
310	struct symbol *sym;
311	struct property *prop;
312	struct expr *e;
313	int i, flags;
314
315	sym_set_change_count(0);
316
317	if (conf_read_simple(name, S_DEF_USER))
318		return 1;
319
320	for_all_symbols(i, sym) {
321		sym_calc_value(sym);
322		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
323			goto sym_ok;
324		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
325			/* check that calculated value agrees with saved value */
326			switch (sym->type) {
327			case S_BOOLEAN:
328			case S_TRISTATE:
329				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
330					break;
331				if (!sym_is_choice(sym))
332					goto sym_ok;
333			default:
334				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
335					goto sym_ok;
336				break;
337			}
338		} else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
339			/* no previous value and not saved */
340			goto sym_ok;
341		conf_unsaved++;
342		/* maybe print value in verbose mode... */
343	sym_ok:
344		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
345			if (sym->visible == no)
346				sym->flags &= ~SYMBOL_DEF_USER;
347			switch (sym->type) {
348			case S_STRING:
349			case S_INT:
350			case S_HEX:
351				if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val))
352					sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
353			default:
354				break;
355			}
356		}
357		if (!sym_is_choice(sym))
358			continue;
359		prop = sym_get_choice_prop(sym);
360		flags = sym->flags;
361		for (e = prop->expr; e; e = e->left.expr)
362			if (e->right.sym->visible != no)
363				flags &= e->right.sym->flags;
364		sym->flags &= flags | ~SYMBOL_DEF_USER;
365	}
366
367	sym_add_change_count(conf_warnings || conf_unsaved);
368
369	return 0;
370}
371
372int conf_write(const char *name)
373{
374	FILE *out;
375	struct symbol *sym;
376	struct menu *menu;
377	const char *basename;
378	char dirname[128], tmpname[128], newname[128];
379	int type, l;
380	const char *str;
381	time_t now;
382	int use_timestamp = 1;
383	char *env;
384
385	dirname[0] = 0;
386	if (name && name[0]) {
387		struct stat st;
388		char *slash;
389
390		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
391			strcpy(dirname, name);
392			strcat(dirname, "/");
393			basename = conf_get_configname();
394		} else if ((slash = strrchr(name, '/'))) {
395			int size = slash - name + 1;
396			memcpy(dirname, name, size);
397			dirname[size] = 0;
398			if (slash[1])
399				basename = slash + 1;
400			else
401				basename = conf_get_configname();
402		} else
403			basename = name;
404	} else
405		basename = conf_get_configname();
406
407	sprintf(newname, "%s%s", dirname, basename);
408	env = getenv("KCONFIG_OVERWRITECONFIG");
409	if (!env || !*env) {
410		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
411		out = fopen(tmpname, "w");
412	} else {
413		*tmpname = 0;
414		out = fopen(newname, "w");
415	}
416	if (!out)
417		return 1;
418
419	sym = sym_lookup("KERNELVERSION", 0);
420	sym_calc_value(sym);
421	time(&now);
422	env = getenv("KCONFIG_NOTIMESTAMP");
423	if (env && *env)
424		use_timestamp = 0;
425
426	fprintf(out, _("#\n"
427		       "# Automatically generated make config: don't edit\n"
428		       "# Linux kernel version: %s\n"
429		       "%s%s"
430		       "#\n"),
431		     sym_get_string_value(sym),
432		     use_timestamp ? "# " : "",
433		     use_timestamp ? ctime(&now) : "");
434
435	if (!conf_get_changed())
436		sym_clear_all_valid();
437
438	menu = rootmenu.list;
439	while (menu) {
440		sym = menu->sym;
441		if (!sym) {
442			if (!menu_is_visible(menu))
443				goto next;
444			str = menu_get_prompt(menu);
445			fprintf(out, "\n"
446				     "#\n"
447				     "# %s\n"
448				     "#\n", str);
449		} else if (!(sym->flags & SYMBOL_CHOICE)) {
450			sym_calc_value(sym);
451			if (!(sym->flags & SYMBOL_WRITE))
452				goto next;
453			sym->flags &= ~SYMBOL_WRITE;
454			type = sym->type;
455			if (type == S_TRISTATE) {
456				sym_calc_value(modules_sym);
457				if (modules_sym->curr.tri == no)
458					type = S_BOOLEAN;
459			}
460			switch (type) {
461			case S_BOOLEAN:
462			case S_TRISTATE:
463				switch (sym_get_tristate_value(sym)) {
464				case no:
465					fprintf(out, "# CONFIG_%s is not set\n", sym->name);
466					break;
467				case mod:
468					fprintf(out, "CONFIG_%s=m\n", sym->name);
469					break;
470				case yes:
471					fprintf(out, "CONFIG_%s=y\n", sym->name);
472					break;
473				}
474				break;
475			case S_STRING:
476				str = sym_get_string_value(sym);
477				fprintf(out, "CONFIG_%s=\"", sym->name);
478				while (1) {
479					l = strcspn(str, "\"\\");
480					if (l) {
481						fwrite(str, l, 1, out);
482						str += l;
483					}
484					if (!*str)
485						break;
486					fprintf(out, "\\%c", *str++);
487				}
488				fputs("\"\n", out);
489				break;
490			case S_HEX:
491				str = sym_get_string_value(sym);
492				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
493					fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
494					break;
495				}
496			case S_INT:
497				str = sym_get_string_value(sym);
498				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
499				break;
500			}
501		}
502
503	next:
504		if (menu->list) {
505			menu = menu->list;
506			continue;
507		}
508		if (menu->next)
509			menu = menu->next;
510		else while ((menu = menu->parent)) {
511			if (menu->next) {
512				menu = menu->next;
513				break;
514			}
515		}
516	}
517	fclose(out);
518
519	if (*tmpname) {
520		strcat(dirname, basename);
521		strcat(dirname, ".old");
522		rename(newname, dirname);
523		if (rename(tmpname, newname))
524			return 1;
525	}
526
527	printf(_("#\n"
528		 "# configuration written to %s\n"
529		 "#\n"), newname);
530
531	sym_set_change_count(0);
532
533	return 0;
534}
535
536int conf_split_config(void)
537{
538	char *name, path[128];
539	char *s, *d, c;
540	struct symbol *sym;
541	struct stat sb;
542	int res, i, fd;
543
544	name = getenv("KCONFIG_AUTOCONFIG");
545	if (!name)
546		name = "include/config/auto.conf";
547	conf_read_simple(name, S_DEF_AUTO);
548
549	if (chdir("include/config"))
550		return 1;
551
552	res = 0;
553	for_all_symbols(i, sym) {
554		sym_calc_value(sym);
555		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
556			continue;
557		if (sym->flags & SYMBOL_WRITE) {
558			if (sym->flags & SYMBOL_DEF_AUTO) {
559				/*
560				 * symbol has old and new value,
561				 * so compare them...
562				 */
563				switch (sym->type) {
564				case S_BOOLEAN:
565				case S_TRISTATE:
566					if (sym_get_tristate_value(sym) ==
567					    sym->def[S_DEF_AUTO].tri)
568						continue;
569					break;
570				case S_STRING:
571				case S_HEX:
572				case S_INT:
573					if (!strcmp(sym_get_string_value(sym),
574						    sym->def[S_DEF_AUTO].val))
575						continue;
576					break;
577				default:
578					break;
579				}
580			} else {
581				/*
582				 * If there is no old value, only 'no' (unset)
583				 * is allowed as new value.
584				 */
585				switch (sym->type) {
586				case S_BOOLEAN:
587				case S_TRISTATE:
588					if (sym_get_tristate_value(sym) == no)
589						continue;
590					break;
591				default:
592					break;
593				}
594			}
595		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
596			/* There is neither an old nor a new value. */
597			continue;
598		/* else
599		 *	There is an old value, but no new value ('no' (unset)
600		 *	isn't saved in auto.conf, so the old value is always
601		 *	different from 'no').
602		 */
603
604		/* Replace all '_' and append ".h" */
605		s = sym->name;
606		d = path;
607		while ((c = *s++)) {
608			c = tolower(c);
609			*d++ = (c == '_') ? '/' : c;
610		}
611		strcpy(d, ".h");
612
613		/* Assume directory path already exists. */
614		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
615		if (fd == -1) {
616			if (errno != ENOENT) {
617				res = 1;
618				break;
619			}
620			/*
621			 * Create directory components,
622			 * unless they exist already.
623			 */
624			d = path;
625			while ((d = strchr(d, '/'))) {
626				*d = 0;
627				if (stat(path, &sb) && mkdir(path, 0755)) {
628					res = 1;
629					goto out;
630				}
631				*d++ = '/';
632			}
633			/* Try it again. */
634			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
635			if (fd == -1) {
636				res = 1;
637				break;
638			}
639		}
640		close(fd);
641	}
642out:
643	if (chdir("../.."))
644		return 1;
645
646	return res;
647}
648
649int conf_write_autoconf(void)
650{
651	struct symbol *sym;
652	const char *str;
653	char *name;
654	FILE *out, *out_h;
655	time_t now;
656	int i, l;
657
658	sym_clear_all_valid();
659
660	file_write_dep("include/config/auto.conf.cmd");
661
662	if (conf_split_config())
663		return 1;
664
665	out = fopen(".tmpconfig", "w");
666	if (!out)
667		return 1;
668
669	out_h = fopen(".tmpconfig.h", "w");
670	if (!out_h) {
671		fclose(out);
672		return 1;
673	}
674
675	sym = sym_lookup("KERNELVERSION", 0);
676	sym_calc_value(sym);
677	time(&now);
678	fprintf(out, "#\n"
679		     "# Automatically generated make config: don't edit\n"
680		     "# Linux kernel version: %s\n"
681		     "# %s"
682		     "#\n",
683		     sym_get_string_value(sym), ctime(&now));
684	fprintf(out_h, "/*\n"
685		       " * Automatically generated C config: don't edit\n"
686		       " * Linux kernel version: %s\n"
687		       " * %s"
688		       " */\n"
689		       "#define AUTOCONF_INCLUDED\n",
690		       sym_get_string_value(sym), ctime(&now));
691
692	for_all_symbols(i, sym) {
693		sym_calc_value(sym);
694		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
695			continue;
696		switch (sym->type) {
697		case S_BOOLEAN:
698		case S_TRISTATE:
699			switch (sym_get_tristate_value(sym)) {
700			case no:
701				break;
702			case mod:
703				fprintf(out, "CONFIG_%s=m\n", sym->name);
704				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
705				break;
706			case yes:
707				fprintf(out, "CONFIG_%s=y\n", sym->name);
708				fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
709				break;
710			}
711			break;
712		case S_STRING:
713			str = sym_get_string_value(sym);
714			fprintf(out, "CONFIG_%s=\"", sym->name);
715			fprintf(out_h, "#define CONFIG_%s \"", sym->name);
716			while (1) {
717				l = strcspn(str, "\"\\");
718				if (l) {
719					fwrite(str, l, 1, out);
720					fwrite(str, l, 1, out_h);
721					str += l;
722				}
723				if (!*str)
724					break;
725				fprintf(out, "\\%c", *str);
726				fprintf(out_h, "\\%c", *str);
727				str++;
728			}
729			fputs("\"\n", out);
730			fputs("\"\n", out_h);
731			break;
732		case S_HEX:
733			str = sym_get_string_value(sym);
734			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
735				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
736				fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
737				break;
738			}
739		case S_INT:
740			str = sym_get_string_value(sym);
741			fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
742			fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
743			break;
744		default:
745			break;
746		}
747	}
748	fclose(out);
749	fclose(out_h);
750
751	name = getenv("KCONFIG_AUTOHEADER");
752	if (!name)
753		name = "include/linux/autoconf.h";
754	if (rename(".tmpconfig.h", name))
755		return 1;
756	name = getenv("KCONFIG_AUTOCONFIG");
757	if (!name)
758		name = "include/config/auto.conf";
759	/*
760	 * This must be the last step, kbuild has a dependency on auto.conf
761	 * and this marks the successful completion of the previous steps.
762	 */
763	if (rename(".tmpconfig", name))
764		return 1;
765
766	return 0;
767}
768
769static int sym_change_count;
770static void (*conf_changed_callback)(void);
771
772void sym_set_change_count(int count)
773{
774	int _sym_change_count = sym_change_count;
775	sym_change_count = count;
776	if (conf_changed_callback &&
777	    (bool)_sym_change_count != (bool)count)
778		conf_changed_callback();
779}
780
781void sym_add_change_count(int count)
782{
783	sym_set_change_count(count + sym_change_count);
784}
785
786bool conf_get_changed(void)
787{
788	return sym_change_count;
789}
790
791void conf_set_changed_callback(void (*fn)(void))
792{
793	conf_changed_callback = fn;
794}
795