aboutsummaryrefslogtreecommitdiffstats
path: root/tools/bison
Commit message (Expand)AuthorAgeFilesLines
* tools/bison: update to 3.7.4Hannu Nyman2020-11-212-6/+6
* tools/bison: update to 3.7.1Hannu Nyman2020-08-232-3/+3
* tools/bison: Update to 3.5.1Daniel Engberg2020-02-191-3/+3
* tools/bison: update to 3.5Hannu Nyman2020-01-212-3/+3
* tools/bison: Update to 3.4.1Daniel Engberg2019-06-223-16/+3
* tools/bison: Update to 3.3.2Daniel Engberg2019-02-102-14/+14
* bison: update to 3.2.4Egor Mikhaylov2019-01-071-2/+2
* tools/bison: Update to 3.2.2Daniel Engberg2018-11-271-2/+2
* bison: update to 3.2.1Hans Dedecker2018-11-151-2/+2
* tools/bison: update to version 3.2Hannu Nyman2018-11-051-2/+2
* tools/bison: Update to 3.1Daniel Engberg2018-10-073-6/+4
* tools/bison: Update to 3.0.5Daniel Engberg2018-06-133-32/+10
* tools: patch various gnu tools for macOS 10.13Ryan Mounce2017-08-231-0/+25
* treewide: clean up download hashesFelix Fietkau2016-12-161-1/+1
* tools/bison: update to 3.0.4Felix Fietkau2015-11-032-5/+4
* bison: replace the yacc script with one that does not hardcode the path (fixe...Felix Fietkau2015-09-262-0/+7
* tools: remove static linking supportJo-Philipp Wich2015-02-061-2/+0
* bison: update to 3.0.2Luka Perkov2013-12-153-4/+4
* bison: update to 3.0Luka Perkov2013-09-243-23/+3
* bison: upgrade to version 2.7Luka Perkov2013-02-284-26/+27
* tools/bison: enable parallel buildsFelix Fietkau2012-09-151-0/+2
* use HOST_STATIC_LINKING instead of hardcoding -staticJo-Philipp Wich2012-08-121-1/+1
* bison: link staticallyJo-Philipp Wich2012-08-101-0/+2
* bison: fix errors in shipped stdio.in.hJo-Philipp Wich2012-07-081-0/+15
* bison: update to 2.5Florian Fainelli2012-04-023-7/+7
* bison: make yacc wrapper relocatableJo-Philipp Wich2012-01-201-0/+20
* tools: clean up Makefiles / make ccache workJohn Crispin2012-01-151-8/+0
* bison: fix compilation with stub intl headerJo-Philipp Wich2011-03-041-0/+15
* tools/bison: update to version 2.4.3Alexandros C. Couloumbis2010-12-061-4/+4
* fix download urlRalph Hempel2009-05-311-1/+1
* clean up / fix various Host/Clean templates in tools/Felix Fietkau2009-05-081-2/+1
* build system refactoring in preparation for allowing packages to do host-buil...Felix Fietkau2009-02-221-8/+8
* Device Tree Compiler require more recent bison ...Ralph Hempel2008-02-051-0/+33
href='#n359'>359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
/*
 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
 * Released under the terms of the GNU GPL v2.0.
 */

#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define LKC_DIRECT_LINK
#include "lkc.h"

const char conf_def_filename[] = ".config";

const char conf_defname[] = "sysdeps/linux/defconfig";

const char *conf_confnames[] = {
	".config",
	conf_defname,
	NULL,
};

static char *conf_expand_value(const char *in)
{
	struct symbol *sym;
	const char *src;
	static char res_value[SYMBOL_MAXLENGTH];
	char *dst, name[SYMBOL_MAXLENGTH];

	res_value[0] = 0;
	dst = name;
	while ((src = strchr(in, '$'))) {
		strncat(res_value, in, src - in);
		src++;
		dst = name;
		while (isalnum(*src) || *src == '_')
			*dst++ = *src++;
		*dst = 0;
		sym = sym_lookup(name, 0);
		sym_calc_value(sym);
		strcat(res_value, sym_get_string_value(sym));
		in = src;
	}
	strcat(res_value, in);

	return res_value;
}

char *conf_get_default_confname(void)
{
	struct stat buf;
	static char fullname[PATH_MAX+1];
	char *env, *name;

	name = conf_expand_value(conf_defname);
	env = getenv(SRCTREE);
	if (env) {
		sprintf(fullname, "%s/%s", env, name);
		if (!stat(fullname, &buf))
			return fullname;
	}
	return name;
}

int conf_read(const char *name)
{
	FILE *in = NULL;
	char line[1024];
	char *p, *p2;
	int lineno = 0;
	struct symbol *sym;
	struct property *prop;
	struct expr *e;
	int i;

	if (name) {
		in = zconf_fopen(name);
	} else {
		const char **names = conf_confnames;
		while ((name = *names++)) {
			name = conf_expand_value(name);
			in = zconf_fopen(name);
			if (in) {
				printf("#\n"
				       "# using defaults found in %s\n"
				       "#\n", name);
				break;
			}
		}
	}

	if (!in)
		return 1;

	for_all_symbols(i, sym) {
		sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
		sym->flags &= ~SYMBOL_VALID;
		switch (sym->type) {
		case S_INT:
		case S_HEX:
		case S_STRING:
			if (sym->user.val)
				free(sym->user.val);
		default:
			sym->user.val = NULL;
			sym->user.tri = no;
		}
	}

	while (fgets(line, sizeof(line), in)) {
		lineno++;
		sym = NULL;
		switch (line[0]) {
		case '#':
			if (line[1]!=' ')
				continue;
			p = strchr(line + 2, ' ');
			if (!p)
				continue;
			*p++ = 0;
			if (strncmp(p, "is not set", 10))
				continue;
			sym = sym_find(line + 2);
			if (!sym) {
				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
				break;
			}
			switch (sym->type) {
			case S_BOOLEAN:
			case S_TRISTATE:
				sym->user.tri = no;
				sym->flags &= ~SYMBOL_NEW;
				break;
			default:
				;
			}
			break;

		case 'A' ... 'Z':
			p = strchr(line, '=');
			if (!p)
				continue;
			*p++ = 0;
			p2 = strchr(p, '\n');
			if (p2)
				*p2 = 0;
			sym = sym_find(line);
			if (!sym) {
				fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
				break;
			}
			switch (sym->type) {
			case S_TRISTATE:
				if (p[0] == 'm') {
					sym->user.tri = mod;
					sym->flags &= ~SYMBOL_NEW;
					break;
				}
			case S_BOOLEAN:
				if (p[0] == 'y') {
					sym->user.tri = yes;
					sym->flags &= ~SYMBOL_NEW;
					break;
				}
				if (p[0] == 'n') {
					sym->user.tri = no;
					sym->flags &= ~SYMBOL_NEW;
					break;
				}
				break;
			case S_STRING:
				if (*p++ != '"')
					break;
				for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
					if (*p2 == '"') {
						*p2 = 0;
						break;
					}
					memmove(p2, p2 + 1, strlen(p2));
				}
				if (!p2) {
					fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
					exit(1);
				}
			case S_INT:
			case S_HEX:
				if (sym_string_valid(sym, p)) {
					sym->user.val = strdup(p);
					sym->flags &= ~SYMBOL_NEW;
				} else {
					fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
					exit(1);
				}
				break;
			default:
				;
			}
			break;
		case '\n':
			break;
		default:
			continue;
		}
		if (sym && sym_is_choice_value(sym)) {
			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
			switch (sym->user.tri) {
			case no:
				break;
			case mod:
				if (cs->user.tri == yes)
					/* warn? */;
				break;
			case yes:
				if (cs->user.tri != no)
					/* warn? */;
				cs->user.val = sym;
				break;
			}
			cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
			cs->flags &= ~SYMBOL_NEW;
		}
	}
	fclose(in);

	if (modules_sym)
		sym_calc_value(modules_sym);
	for_all_symbols(i, sym) {
		sym_calc_value(sym);
		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
			if (sym->visible == no)
				sym->flags |= SYMBOL_NEW;
			switch (sym->type) {
			case S_STRING:
			case S_INT:
			case S_HEX:
				if (!sym_string_within_range(sym, sym->user.val))
					sym->flags |= SYMBOL_NEW;
			default:
				break;
			}
		}
		if (!sym_is_choice(sym))
			continue;
		prop = sym_get_choice_prop(sym);
		for (e = prop->expr; e; e = e->left.expr)
			if (e->right.sym->visible != no)
				sym->flags |= e->right.sym->flags & SYMBOL_NEW;
	}

	sym_change_count = 1;

	return 0;
}

int conf_write(const char *name)
{
	FILE *out, *out_h;
	struct symbol *sym;
	struct menu *menu;
	const char *basename;
	char dirname[128], tmpname[128], newname[128];
	int type, l;
	const char *str;

	dirname[0] = 0;
	if (name && name[0]) {
		struct stat st;
		char *slash;

		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
			strcpy(dirname, name);
			strcat(dirname, "/");
			basename = conf_def_filename;
		} else if ((slash = strrchr(name, '/'))) {
			int size = slash - name + 1;
			memcpy(dirname, name, size);
			dirname[size] = 0;
			if (slash[1])
				basename = slash + 1;
			else
				basename = conf_def_filename;
		} else
			basename = name;
	} else
		basename = conf_def_filename;

	sprintf(newname, "%s.tmpconfig.%d", dirname, getpid());
	out = fopen(newname, "w");
	if (!out)
		return 1;
	out_h = NULL;
	if (!name) {
		out_h = fopen(".tmpconfig.h", "w");
		if (!out_h)
			return 1;
	}
	fprintf(out, "#\n"
		     "# Automatically generated make config: don't edit\n"
		     "#\n");
	if (out_h) {
		fprintf(out_h, "/*\n"
			     " * Automatically generated header file: don't edit\n"
			     " */\n\n"
			     "#define AUTOCONF_INCLUDED\n\n"
			     "/* Version Number */\n"
			     "#define BB_VER \"%s\"\n"
			     "#define BB_BT \"%s\"\n",
			     getenv("VERSION"),
			     getenv("BUILDTIME"));
		if (getenv("EXTRA_VERSION"))
			fprintf(out_h, "#define BB_EXTRA_VERSION \"%s\"\n",
				     getenv("EXTRA_VERSION"));
		fprintf(out_h, "\n");
	}

	if (!sym_change_count)
		sym_clear_all_valid();

	menu = rootmenu.list;
	while (menu) {
		sym = menu->sym;
		if (!sym) {
			if (!menu_is_visible(menu))
				goto next;
			str = menu_get_prompt(menu);
			fprintf(out, "\n"
				     "#\n"
				     "# %s\n"
				     "#\n", str);
			if (out_h)
				fprintf(out_h, "\n"
					       "/*\n"
					       " * %s\n"
					       " */\n", str);
		} else if (!(sym->flags & SYMBOL_CHOICE)) {
			sym_calc_value(sym);
			if (!(sym->flags & SYMBOL_WRITE))
				goto next;
			sym->flags &= ~SYMBOL_WRITE;
			type = sym->type;
			if (type == S_TRISTATE) {
				sym_calc_value(modules_sym);
				if (modules_sym->curr.tri == no)
					type = S_BOOLEAN;
			}
			switch (type) {
			case S_BOOLEAN:
			case S_TRISTATE:
				switch (sym_get_tristate_value(sym)) {
				case no:
					fprintf(out, "# %s is not set\n", sym->name);
					if (out_h)
						fprintf(out_h, "#undef %s\n", sym->name);
					break;
				case mod:
					fprintf(out, "%s=m\n", sym->name);
#if 0
					if (out_h)
						fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
#endif
					break;
				case yes:
					fprintf(out, "%s=y\n", sym->name);
					if (out_h)
						fprintf(out_h, "#define %s 1\n", sym->name);
					break;
				}
				break;
			case S_STRING:
				// fix me
				str = sym_get_string_value(sym);
				fprintf(out, "%s=\"", sym->name);
				if (out_h)
					fprintf(out_h, "#define %s \"", sym->name);
				do {
					l = strcspn(str, "\"\\");
					if (l) {
						fwrite(str, l, 1, out);
						if (out_h)
							fwrite(str, l, 1, out_h);
					}
					str += l;
					while (*str == '\\' || *str == '"') {
						fprintf(out, "\\%c", *str);
						if (out_h)
							fprintf(out_h, "\\%c", *str);
						str++;
					}
				} while (*str);
				fputs("\"\n", out);
				if (out_h)
					fputs("\"\n", out_h);
				break;
			case S_HEX:
				str = sym_get_string_value(sym);
				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
					fprintf(out, "%s=%s\n", sym->name, str);
					if (out_h)
						fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
					break;
				}
			case S_INT:
				str = sym_get_string_value(sym);
				fprintf(out, "%s=%s\n", sym->name, str);
				if (out_h)
					fprintf(out_h, "#define %s %s\n", sym->name, str);
				break;
			}
		}

	next:
		if (menu->list) {
			menu = menu->list;
			continue;
		}
		if (menu->next)
			menu = menu->next;
		else while ((menu = menu->parent)) {
			if (menu->next) {
				menu = menu->next;
				break;
			}
		}
	}
	fclose(out);
	if (out_h) {
		fclose(out_h);
		rename(".tmpconfig.h", "include/config.h");
		file_write_dep(NULL);
	}
	if (!name || basename != conf_def_filename) {
		if (!name)
			name = conf_def_filename;
		sprintf(tmpname, "%s.old", name);
		rename(name, tmpname);
	}
	sprintf(tmpname, "%s%s", dirname, basename);
	if (rename(newname, tmpname))
		return 1;

	sym_change_count = 0;

	return 0;
}