162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef EXPR_H
762306a36Sopenharmony_ci#define EXPR_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifdef __cplusplus
1062306a36Sopenharmony_ciextern "C" {
1162306a36Sopenharmony_ci#endif
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <assert.h>
1462306a36Sopenharmony_ci#include <stdio.h>
1562306a36Sopenharmony_ci#include "list.h"
1662306a36Sopenharmony_ci#ifndef __cplusplus
1762306a36Sopenharmony_ci#include <stdbool.h>
1862306a36Sopenharmony_ci#endif
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct file {
2162306a36Sopenharmony_ci	struct file *next;
2262306a36Sopenharmony_ci	struct file *parent;
2362306a36Sopenharmony_ci	const char *name;
2462306a36Sopenharmony_ci	int lineno;
2562306a36Sopenharmony_ci};
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_citypedef enum tristate {
2862306a36Sopenharmony_ci	no, mod, yes
2962306a36Sopenharmony_ci} tristate;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cienum expr_type {
3262306a36Sopenharmony_ci	E_NONE, E_OR, E_AND, E_NOT,
3362306a36Sopenharmony_ci	E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ,
3462306a36Sopenharmony_ci	E_LIST, E_SYMBOL, E_RANGE
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ciunion expr_data {
3862306a36Sopenharmony_ci	struct expr *expr;
3962306a36Sopenharmony_ci	struct symbol *sym;
4062306a36Sopenharmony_ci};
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistruct expr {
4362306a36Sopenharmony_ci	enum expr_type type;
4462306a36Sopenharmony_ci	union expr_data left, right;
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define EXPR_OR(dep1, dep2)	(((dep1)>(dep2))?(dep1):(dep2))
4862306a36Sopenharmony_ci#define EXPR_AND(dep1, dep2)	(((dep1)<(dep2))?(dep1):(dep2))
4962306a36Sopenharmony_ci#define EXPR_NOT(dep)		(2-(dep))
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci#define expr_list_for_each_sym(l, e, s) \
5262306a36Sopenharmony_ci	for (e = (l); e && (s = e->right.sym); e = e->left.expr)
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistruct expr_value {
5562306a36Sopenharmony_ci	struct expr *expr;
5662306a36Sopenharmony_ci	tristate tri;
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct symbol_value {
6062306a36Sopenharmony_ci	void *val;
6162306a36Sopenharmony_ci	tristate tri;
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cienum symbol_type {
6562306a36Sopenharmony_ci	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* enum values are used as index to symbol.def[] */
6962306a36Sopenharmony_cienum {
7062306a36Sopenharmony_ci	S_DEF_USER,		/* main user value */
7162306a36Sopenharmony_ci	S_DEF_AUTO,		/* values read from auto.conf */
7262306a36Sopenharmony_ci	S_DEF_DEF3,		/* Reserved for UI usage */
7362306a36Sopenharmony_ci	S_DEF_DEF4,		/* Reserved for UI usage */
7462306a36Sopenharmony_ci	S_DEF_COUNT
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/*
7862306a36Sopenharmony_ci * Represents a configuration symbol.
7962306a36Sopenharmony_ci *
8062306a36Sopenharmony_ci * Choices are represented as a special kind of symbol and have the
8162306a36Sopenharmony_ci * SYMBOL_CHOICE bit set in 'flags'.
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_cistruct symbol {
8462306a36Sopenharmony_ci	/* The next symbol in the same bucket in the symbol hash table */
8562306a36Sopenharmony_ci	struct symbol *next;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	/* The name of the symbol, e.g. "FOO" for 'config FOO' */
8862306a36Sopenharmony_ci	char *name;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/* S_BOOLEAN, S_TRISTATE, ... */
9162306a36Sopenharmony_ci	enum symbol_type type;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	/*
9462306a36Sopenharmony_ci	 * The calculated value of the symbol. The SYMBOL_VALID bit is set in
9562306a36Sopenharmony_ci	 * 'flags' when this is up to date. Note that this value might differ
9662306a36Sopenharmony_ci	 * from the user value set in e.g. a .config file, due to visibility.
9762306a36Sopenharmony_ci	 */
9862306a36Sopenharmony_ci	struct symbol_value curr;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	/*
10162306a36Sopenharmony_ci	 * Values for the symbol provided from outside. def[S_DEF_USER] holds
10262306a36Sopenharmony_ci	 * the .config value.
10362306a36Sopenharmony_ci	 */
10462306a36Sopenharmony_ci	struct symbol_value def[S_DEF_COUNT];
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	/*
10762306a36Sopenharmony_ci	 * An upper bound on the tristate value the user can set for the symbol
10862306a36Sopenharmony_ci	 * if it is a boolean or tristate. Calculated from prompt dependencies,
10962306a36Sopenharmony_ci	 * which also inherit dependencies from enclosing menus, choices, and
11062306a36Sopenharmony_ci	 * ifs. If 'n', the user value will be ignored.
11162306a36Sopenharmony_ci	 *
11262306a36Sopenharmony_ci	 * Symbols lacking prompts always have visibility 'n'.
11362306a36Sopenharmony_ci	 */
11462306a36Sopenharmony_ci	tristate visible;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	/* SYMBOL_* flags */
11762306a36Sopenharmony_ci	int flags;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	/* List of properties. See prop_type. */
12062306a36Sopenharmony_ci	struct property *prop;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	/* Dependencies from enclosing menus, choices, and ifs */
12362306a36Sopenharmony_ci	struct expr_value dir_dep;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* Reverse dependencies through being selected by other symbols */
12662306a36Sopenharmony_ci	struct expr_value rev_dep;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	/*
12962306a36Sopenharmony_ci	 * "Weak" reverse dependencies through being implied by other symbols
13062306a36Sopenharmony_ci	 */
13162306a36Sopenharmony_ci	struct expr_value implied;
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next)
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci#define SYMBOL_CONST      0x0001  /* symbol is const */
13762306a36Sopenharmony_ci#define SYMBOL_CHECK      0x0008  /* used during dependency checking */
13862306a36Sopenharmony_ci#define SYMBOL_CHOICE     0x0010  /* start of a choice block (null name) */
13962306a36Sopenharmony_ci#define SYMBOL_CHOICEVAL  0x0020  /* used as a value in a choice block */
14062306a36Sopenharmony_ci#define SYMBOL_VALID      0x0080  /* set when symbol.curr is calculated */
14162306a36Sopenharmony_ci#define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */
14262306a36Sopenharmony_ci#define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */
14362306a36Sopenharmony_ci#define SYMBOL_CHANGED    0x0400  /* ? */
14462306a36Sopenharmony_ci#define SYMBOL_WRITTEN    0x0800  /* track info to avoid double-write to .config */
14562306a36Sopenharmony_ci#define SYMBOL_NO_WRITE   0x1000  /* Symbol for internal use only; it will not be written */
14662306a36Sopenharmony_ci#define SYMBOL_CHECKED    0x2000  /* used during dependency checking */
14762306a36Sopenharmony_ci#define SYMBOL_WARNED     0x8000  /* warning has been issued */
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/* Set when symbol.def[] is used */
15062306a36Sopenharmony_ci#define SYMBOL_DEF        0x10000  /* First bit of SYMBOL_DEF */
15162306a36Sopenharmony_ci#define SYMBOL_DEF_USER   0x10000  /* symbol.def[S_DEF_USER] is valid */
15262306a36Sopenharmony_ci#define SYMBOL_DEF_AUTO   0x20000  /* symbol.def[S_DEF_AUTO] is valid */
15362306a36Sopenharmony_ci#define SYMBOL_DEF3       0x40000  /* symbol.def[S_DEF_3] is valid */
15462306a36Sopenharmony_ci#define SYMBOL_DEF4       0x80000  /* symbol.def[S_DEF_4] is valid */
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci/* choice values need to be set before calculating this symbol value */
15762306a36Sopenharmony_ci#define SYMBOL_NEED_SET_CHOICE_VALUES  0x100000
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci#define SYMBOL_MAXLENGTH	256
16062306a36Sopenharmony_ci#define SYMBOL_HASHSIZE		9973
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/* A property represent the config options that can be associated
16362306a36Sopenharmony_ci * with a config "symbol".
16462306a36Sopenharmony_ci * Sample:
16562306a36Sopenharmony_ci * config FOO
16662306a36Sopenharmony_ci *         default y
16762306a36Sopenharmony_ci *         prompt "foo prompt"
16862306a36Sopenharmony_ci *         select BAR
16962306a36Sopenharmony_ci * config BAZ
17062306a36Sopenharmony_ci *         int "BAZ Value"
17162306a36Sopenharmony_ci *         range 1..255
17262306a36Sopenharmony_ci *
17362306a36Sopenharmony_ci * Please, also check parser.y:print_symbol() when modifying the
17462306a36Sopenharmony_ci * list of property types!
17562306a36Sopenharmony_ci */
17662306a36Sopenharmony_cienum prop_type {
17762306a36Sopenharmony_ci	P_UNKNOWN,
17862306a36Sopenharmony_ci	P_PROMPT,   /* prompt "foo prompt" or "BAZ Value" */
17962306a36Sopenharmony_ci	P_COMMENT,  /* text associated with a comment */
18062306a36Sopenharmony_ci	P_MENU,     /* prompt associated with a menu or menuconfig symbol */
18162306a36Sopenharmony_ci	P_DEFAULT,  /* default y */
18262306a36Sopenharmony_ci	P_CHOICE,   /* choice value */
18362306a36Sopenharmony_ci	P_SELECT,   /* select BAR */
18462306a36Sopenharmony_ci	P_IMPLY,    /* imply BAR */
18562306a36Sopenharmony_ci	P_RANGE,    /* range 7..100 (for a symbol) */
18662306a36Sopenharmony_ci	P_SYMBOL,   /* where a symbol is defined */
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistruct property {
19062306a36Sopenharmony_ci	struct property *next;     /* next property - null if last */
19162306a36Sopenharmony_ci	enum prop_type type;       /* type of property */
19262306a36Sopenharmony_ci	const char *text;          /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
19362306a36Sopenharmony_ci	struct expr_value visible;
19462306a36Sopenharmony_ci	struct expr *expr;         /* the optional conditional part of the property */
19562306a36Sopenharmony_ci	struct menu *menu;         /* the menu the property are associated with
19662306a36Sopenharmony_ci	                            * valid for: P_SELECT, P_RANGE, P_CHOICE,
19762306a36Sopenharmony_ci	                            * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
19862306a36Sopenharmony_ci	struct file *file;         /* what file was this property defined */
19962306a36Sopenharmony_ci	int lineno;                /* what lineno was this property defined */
20062306a36Sopenharmony_ci};
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci#define for_all_properties(sym, st, tok) \
20362306a36Sopenharmony_ci	for (st = sym->prop; st; st = st->next) \
20462306a36Sopenharmony_ci		if (st->type == (tok))
20562306a36Sopenharmony_ci#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT)
20662306a36Sopenharmony_ci#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE)
20762306a36Sopenharmony_ci#define for_all_prompts(sym, st) \
20862306a36Sopenharmony_ci	for (st = sym->prop; st; st = st->next) \
20962306a36Sopenharmony_ci		if (st->text)
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci/*
21262306a36Sopenharmony_ci * Represents a node in the menu tree, as seen in e.g. menuconfig (though used
21362306a36Sopenharmony_ci * for all front ends). Each symbol, menu, etc. defined in the Kconfig files
21462306a36Sopenharmony_ci * gets a node. A symbol defined in multiple locations gets one node at each
21562306a36Sopenharmony_ci * location.
21662306a36Sopenharmony_ci */
21762306a36Sopenharmony_cistruct menu {
21862306a36Sopenharmony_ci	/* The next menu node at the same level */
21962306a36Sopenharmony_ci	struct menu *next;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	/* The parent menu node, corresponding to e.g. a menu or choice */
22262306a36Sopenharmony_ci	struct menu *parent;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	/* The first child menu node, for e.g. menus and choices */
22562306a36Sopenharmony_ci	struct menu *list;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	/*
22862306a36Sopenharmony_ci	 * The symbol associated with the menu node. Choices are implemented as
22962306a36Sopenharmony_ci	 * a special kind of symbol. NULL for menus, comments, and ifs.
23062306a36Sopenharmony_ci	 */
23162306a36Sopenharmony_ci	struct symbol *sym;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	/*
23462306a36Sopenharmony_ci	 * The prompt associated with the node. This holds the prompt for a
23562306a36Sopenharmony_ci	 * symbol as well as the text for a menu or comment, along with the
23662306a36Sopenharmony_ci	 * type (P_PROMPT, P_MENU, etc.)
23762306a36Sopenharmony_ci	 */
23862306a36Sopenharmony_ci	struct property *prompt;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	/*
24162306a36Sopenharmony_ci	 * 'visible if' dependencies. If more than one is given, they will be
24262306a36Sopenharmony_ci	 * ANDed together.
24362306a36Sopenharmony_ci	 */
24462306a36Sopenharmony_ci	struct expr *visibility;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	/*
24762306a36Sopenharmony_ci	 * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed
24862306a36Sopenharmony_ci	 * together
24962306a36Sopenharmony_ci	 */
25062306a36Sopenharmony_ci	struct expr *dep;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	/* MENU_* flags */
25362306a36Sopenharmony_ci	unsigned int flags;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	/* Any help text associated with the node */
25662306a36Sopenharmony_ci	char *help;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/* The location where the menu node appears in the Kconfig files */
25962306a36Sopenharmony_ci	struct file *file;
26062306a36Sopenharmony_ci	int lineno;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	/* For use by front ends that need to store auxiliary data */
26362306a36Sopenharmony_ci	void *data;
26462306a36Sopenharmony_ci};
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci/*
26762306a36Sopenharmony_ci * Set on a menu node when the corresponding symbol changes state in some way.
26862306a36Sopenharmony_ci * Can be checked by front ends.
26962306a36Sopenharmony_ci */
27062306a36Sopenharmony_ci#define MENU_CHANGED		0x0001
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci#define MENU_ROOT		0x0002
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_cistruct jump_key {
27562306a36Sopenharmony_ci	struct list_head entries;
27662306a36Sopenharmony_ci	size_t offset;
27762306a36Sopenharmony_ci	struct menu *target;
27862306a36Sopenharmony_ci};
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ciextern struct file *file_list;
28162306a36Sopenharmony_ciextern struct file *current_file;
28262306a36Sopenharmony_cistruct file *lookup_file(const char *name);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ciextern struct symbol symbol_yes, symbol_no, symbol_mod;
28562306a36Sopenharmony_ciextern struct symbol *modules_sym;
28662306a36Sopenharmony_ciextern int cdebug;
28762306a36Sopenharmony_cistruct expr *expr_alloc_symbol(struct symbol *sym);
28862306a36Sopenharmony_cistruct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
28962306a36Sopenharmony_cistruct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2);
29062306a36Sopenharmony_cistruct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2);
29162306a36Sopenharmony_cistruct expr *expr_alloc_and(struct expr *e1, struct expr *e2);
29262306a36Sopenharmony_cistruct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
29362306a36Sopenharmony_cistruct expr *expr_copy(const struct expr *org);
29462306a36Sopenharmony_civoid expr_free(struct expr *e);
29562306a36Sopenharmony_civoid expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
29662306a36Sopenharmony_ciint expr_eq(struct expr *e1, struct expr *e2);
29762306a36Sopenharmony_citristate expr_calc_value(struct expr *e);
29862306a36Sopenharmony_cistruct expr *expr_trans_bool(struct expr *e);
29962306a36Sopenharmony_cistruct expr *expr_eliminate_dups(struct expr *e);
30062306a36Sopenharmony_cistruct expr *expr_transform(struct expr *e);
30162306a36Sopenharmony_ciint expr_contains_symbol(struct expr *dep, struct symbol *sym);
30262306a36Sopenharmony_cibool expr_depends_symbol(struct expr *dep, struct symbol *sym);
30362306a36Sopenharmony_cistruct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_civoid expr_fprint(struct expr *e, FILE *out);
30662306a36Sopenharmony_cistruct gstr; /* forward */
30762306a36Sopenharmony_civoid expr_gstr_print(struct expr *e, struct gstr *gs);
30862306a36Sopenharmony_civoid expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
30962306a36Sopenharmony_ci			    tristate pr_type, const char *title);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic inline int expr_is_yes(struct expr *e)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes);
31462306a36Sopenharmony_ci}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic inline int expr_is_no(struct expr *e)
31762306a36Sopenharmony_ci{
31862306a36Sopenharmony_ci	return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no);
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci#ifdef __cplusplus
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci#endif
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci#endif /* EXPR_H */
326