xref: /optee_os/scripts/kconfig/kconfiglib/kconfiglib.py (revision c689edbb2550c76ae81dcecab717d82a564b2d7b)
1*c689edbbSJens Wiklander# Copyright (c) 2011-2019, Ulf Magnusson
2*c689edbbSJens Wiklander# SPDX-License-Identifier: ISC
3*c689edbbSJens Wiklander
4*c689edbbSJens Wiklander"""
5*c689edbbSJens WiklanderOverview
6*c689edbbSJens Wiklander========
7*c689edbbSJens Wiklander
8*c689edbbSJens WiklanderKconfiglib is a Python 2/3 library for scripting and extracting information
9*c689edbbSJens Wiklanderfrom Kconfig (https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt)
10*c689edbbSJens Wiklanderconfiguration systems.
11*c689edbbSJens Wiklander
12*c689edbbSJens WiklanderSee the homepage at https://github.com/zephyrproject-rtos/Kconfiglib for a longer
13*c689edbbSJens Wiklanderoverview.
14*c689edbbSJens Wiklander
15*c689edbbSJens WiklanderSince Kconfiglib 12.0.0, the library version is available in
16*c689edbbSJens Wiklanderkconfiglib.VERSION, which is a (<major>, <minor>, <patch>) tuple, e.g.
17*c689edbbSJens Wiklander(12, 0, 0).
18*c689edbbSJens Wiklander
19*c689edbbSJens Wiklander
20*c689edbbSJens WiklanderUsing Kconfiglib on the Linux kernel with the Makefile targets
21*c689edbbSJens Wiklander==============================================================
22*c689edbbSJens Wiklander
23*c689edbbSJens WiklanderFor the Linux kernel, a handy interface is provided by the
24*c689edbbSJens Wiklanderscripts/kconfig/Makefile patch, which can be applied with either 'git am' or
25*c689edbbSJens Wiklanderthe 'patch' utility:
26*c689edbbSJens Wiklander
27*c689edbbSJens Wiklander  $ wget -qO- https://raw.githubusercontent.com/zephyrproject-rtos/Kconfiglib/master/makefile.patch | git am
28*c689edbbSJens Wiklander  $ wget -qO- https://raw.githubusercontent.com/zephyrproject-rtos/Kconfiglib/master/makefile.patch | patch -p1
29*c689edbbSJens Wiklander
30*c689edbbSJens WiklanderWarning: Not passing -p1 to patch will cause the wrong file to be patched.
31*c689edbbSJens Wiklander
32*c689edbbSJens WiklanderPlease tell me if the patch does not apply. It should be trivial to apply
33*c689edbbSJens Wiklandermanually, as it's just a block of text that needs to be inserted near the other
34*c689edbbSJens Wiklander*conf: targets in scripts/kconfig/Makefile.
35*c689edbbSJens Wiklander
36*c689edbbSJens WiklanderLook further down for a motivation for the Makefile patch and for instructions
37*c689edbbSJens Wiklanderon how you can use Kconfiglib without it.
38*c689edbbSJens Wiklander
39*c689edbbSJens WiklanderIf you do not wish to install Kconfiglib via pip, the Makefile patch is set up
40*c689edbbSJens Wiklanderso that you can also just clone Kconfiglib into the kernel root:
41*c689edbbSJens Wiklander
42*c689edbbSJens Wiklander  $ git clone git://github.com/zephyrproject-rtos/Kconfiglib.git
43*c689edbbSJens Wiklander  $ git am Kconfiglib/makefile.patch  (or 'patch -p1 < Kconfiglib/makefile.patch')
44*c689edbbSJens Wiklander
45*c689edbbSJens WiklanderWarning: The directory name Kconfiglib/ is significant in this case, because
46*c689edbbSJens Wiklanderit's added to PYTHONPATH by the new targets in makefile.patch.
47*c689edbbSJens Wiklander
48*c689edbbSJens WiklanderThe targets added by the Makefile patch are described in the following
49*c689edbbSJens Wiklandersections.
50*c689edbbSJens Wiklander
51*c689edbbSJens Wiklander
52*c689edbbSJens Wiklandermake kmenuconfig
53*c689edbbSJens Wiklander----------------
54*c689edbbSJens Wiklander
55*c689edbbSJens WiklanderThis target runs the curses menuconfig interface with Python 3. As of
56*c689edbbSJens WiklanderKconfiglib 12.2.0, both Python 2 and Python 3 are supported (previously, only
57*c689edbbSJens WiklanderPython 3 was supported, so this was a backport).
58*c689edbbSJens Wiklander
59*c689edbbSJens Wiklander
60*c689edbbSJens Wiklandermake guiconfig
61*c689edbbSJens Wiklander--------------
62*c689edbbSJens Wiklander
63*c689edbbSJens WiklanderThis target runs the Tkinter menuconfig interface. Both Python 2 and Python 3
64*c689edbbSJens Wiklanderare supported. To change the Python interpreter used, pass
65*c689edbbSJens WiklanderPYTHONCMD=<executable> to 'make'. The default is 'python'.
66*c689edbbSJens Wiklander
67*c689edbbSJens Wiklander
68*c689edbbSJens Wiklandermake [ARCH=<arch>] iscriptconfig
69*c689edbbSJens Wiklander--------------------------------
70*c689edbbSJens Wiklander
71*c689edbbSJens WiklanderThis target gives an interactive Python prompt where a Kconfig instance has
72*c689edbbSJens Wiklanderbeen preloaded and is available in 'kconf'. To change the Python interpreter
73*c689edbbSJens Wiklanderused, pass PYTHONCMD=<executable> to 'make'. The default is 'python'.
74*c689edbbSJens Wiklander
75*c689edbbSJens WiklanderTo get a feel for the API, try evaluating and printing the symbols in
76*c689edbbSJens Wiklanderkconf.defined_syms, and explore the MenuNode menu tree starting at
77*c689edbbSJens Wiklanderkconf.top_node by following 'next' and 'list' pointers.
78*c689edbbSJens Wiklander
79*c689edbbSJens WiklanderThe item contained in a menu node is found in MenuNode.item (note that this can
80*c689edbbSJens Wiklanderbe one of the constants kconfiglib.MENU and kconfiglib.COMMENT), and all
81*c689edbbSJens Wiklandersymbols and choices have a 'nodes' attribute containing their menu nodes
82*c689edbbSJens Wiklander(usually only one). Printing a menu node will print its item, in Kconfig
83*c689edbbSJens Wiklanderformat.
84*c689edbbSJens Wiklander
85*c689edbbSJens WiklanderIf you want to look up a symbol by name, use the kconf.syms dictionary.
86*c689edbbSJens Wiklander
87*c689edbbSJens Wiklander
88*c689edbbSJens Wiklandermake scriptconfig SCRIPT=<script> [SCRIPT_ARG=<arg>]
89*c689edbbSJens Wiklander----------------------------------------------------
90*c689edbbSJens Wiklander
91*c689edbbSJens WiklanderThis target runs the Python script given by the SCRIPT parameter on the
92*c689edbbSJens Wiklanderconfiguration. sys.argv[1] holds the name of the top-level Kconfig file
93*c689edbbSJens Wiklander(currently always "Kconfig" in practice), and sys.argv[2] holds the SCRIPT_ARG
94*c689edbbSJens Wiklanderargument, if given.
95*c689edbbSJens Wiklander
96*c689edbbSJens WiklanderSee the examples/ subdirectory for example scripts.
97*c689edbbSJens Wiklander
98*c689edbbSJens Wiklander
99*c689edbbSJens Wiklandermake dumpvarsconfig
100*c689edbbSJens Wiklander-------------------
101*c689edbbSJens Wiklander
102*c689edbbSJens WiklanderThis target prints a list of all environment variables referenced from the
103*c689edbbSJens WiklanderKconfig files, together with their values. See the
104*c689edbbSJens WiklanderKconfiglib/examples/dumpvars.py script.
105*c689edbbSJens Wiklander
106*c689edbbSJens WiklanderOnly environment variables that are referenced via the Kconfig preprocessor
107*c689edbbSJens Wiklander$(FOO) syntax are included. The preprocessor was added in Linux 4.18.
108*c689edbbSJens Wiklander
109*c689edbbSJens Wiklander
110*c689edbbSJens WiklanderUsing Kconfiglib without the Makefile targets
111*c689edbbSJens Wiklander=============================================
112*c689edbbSJens Wiklander
113*c689edbbSJens WiklanderThe make targets are only needed to pick up environment variables exported from
114*c689edbbSJens Wiklanderthe Kbuild makefiles and referenced inside Kconfig files, via e.g.
115*c689edbbSJens Wiklander'source "arch/$(SRCARCH)/Kconfig" and commands run via '$(shell,...)'.
116*c689edbbSJens Wiklander
117*c689edbbSJens WiklanderThese variables are referenced as of writing (Linux 4.18), together with sample
118*c689edbbSJens Wiklandervalues:
119*c689edbbSJens Wiklander
120*c689edbbSJens Wiklander  srctree          (.)
121*c689edbbSJens Wiklander  ARCH             (x86)
122*c689edbbSJens Wiklander  SRCARCH          (x86)
123*c689edbbSJens Wiklander  KERNELVERSION    (4.18.0)
124*c689edbbSJens Wiklander  CC               (gcc)
125*c689edbbSJens Wiklander  HOSTCC           (gcc)
126*c689edbbSJens Wiklander  HOSTCXX          (g++)
127*c689edbbSJens Wiklander  CC_VERSION_TEXT  (gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0)
128*c689edbbSJens Wiklander
129*c689edbbSJens WiklanderOlder kernels only reference ARCH, SRCARCH, and KERNELVERSION.
130*c689edbbSJens Wiklander
131*c689edbbSJens WiklanderIf your kernel is recent enough (4.18+), you can get a list of referenced
132*c689edbbSJens Wiklanderenvironment variables via 'make dumpvarsconfig' (see above). Note that this
133*c689edbbSJens Wiklandercommand is added by the Makefile patch.
134*c689edbbSJens Wiklander
135*c689edbbSJens WiklanderTo run Kconfiglib without the Makefile patch, set the environment variables
136*c689edbbSJens Wiklandermanually:
137*c689edbbSJens Wiklander
138*c689edbbSJens Wiklander  $ srctree=. ARCH=x86 SRCARCH=x86 KERNELVERSION=`make kernelversion` ... python(3)
139*c689edbbSJens Wiklander  >>> import kconfiglib
140*c689edbbSJens Wiklander  >>> kconf = kconfiglib.Kconfig()  # filename defaults to "Kconfig"
141*c689edbbSJens Wiklander
142*c689edbbSJens WiklanderSearch the top-level Makefile for "Additional ARCH settings" to see other
143*c689edbbSJens Wiklanderpossibilities for ARCH and SRCARCH.
144*c689edbbSJens Wiklander
145*c689edbbSJens Wiklander
146*c689edbbSJens WiklanderIntro to symbol values
147*c689edbbSJens Wiklander======================
148*c689edbbSJens Wiklander
149*c689edbbSJens WiklanderKconfiglib has the same assignment semantics as the C implementation.
150*c689edbbSJens Wiklander
151*c689edbbSJens WiklanderAny symbol can be assigned a value by the user (via Kconfig.load_config() or
152*c689edbbSJens WiklanderSymbol.set_value()), but this user value is only respected if the symbol is
153*c689edbbSJens Wiklandervisible, which corresponds to it (currently) being visible in the menuconfig
154*c689edbbSJens Wiklanderinterface.
155*c689edbbSJens Wiklander
156*c689edbbSJens WiklanderFor symbols with prompts, the visibility of the symbol is determined by the
157*c689edbbSJens Wiklandercondition on the prompt. Symbols without prompts are never visible, so setting
158*c689edbbSJens Wiklandera user value on them is pointless. A warning will be printed by default if
159*c689edbbSJens WiklanderSymbol.set_value() is called on a promptless symbol. Assignments to promptless
160*c689edbbSJens Wiklandersymbols are normal within a .config file, so no similar warning will be printed
161*c689edbbSJens Wiklanderby load_config().
162*c689edbbSJens Wiklander
163*c689edbbSJens WiklanderDependencies from parents and 'if'/'depends on' are propagated to properties,
164*c689edbbSJens Wiklanderincluding prompts, so these two configurations are logically equivalent:
165*c689edbbSJens Wiklander
166*c689edbbSJens Wiklander(1)
167*c689edbbSJens Wiklander
168*c689edbbSJens Wiklander  menu "menu"
169*c689edbbSJens Wiklander      depends on A
170*c689edbbSJens Wiklander
171*c689edbbSJens Wiklander  if B
172*c689edbbSJens Wiklander
173*c689edbbSJens Wiklander  config FOO
174*c689edbbSJens Wiklander      tristate "foo" if D
175*c689edbbSJens Wiklander      default y
176*c689edbbSJens Wiklander      depends on C
177*c689edbbSJens Wiklander
178*c689edbbSJens Wiklander  endif
179*c689edbbSJens Wiklander
180*c689edbbSJens Wiklander  endmenu
181*c689edbbSJens Wiklander
182*c689edbbSJens Wiklander(2)
183*c689edbbSJens Wiklander
184*c689edbbSJens Wiklander  menu "menu"
185*c689edbbSJens Wiklander      depends on A
186*c689edbbSJens Wiklander
187*c689edbbSJens Wiklander  config FOO
188*c689edbbSJens Wiklander      tristate "foo" if A && B && C && D
189*c689edbbSJens Wiklander      default y if A && B && C
190*c689edbbSJens Wiklander
191*c689edbbSJens Wiklander  endmenu
192*c689edbbSJens Wiklander
193*c689edbbSJens WiklanderIn this example, A && B && C && D (the prompt condition) needs to be non-n for
194*c689edbbSJens WiklanderFOO to be visible (assignable). If its value is m, the symbol can only be
195*c689edbbSJens Wiklanderassigned the value m: The visibility sets an upper bound on the value that can
196*c689edbbSJens Wiklanderbe assigned by the user, and any higher user value will be truncated down.
197*c689edbbSJens Wiklander
198*c689edbbSJens Wiklander'default' properties are independent of the visibility, though a 'default' will
199*c689edbbSJens Wiklanderoften get the same condition as the prompt due to dependency propagation.
200*c689edbbSJens Wiklander'default' properties are used if the symbol is not visible or has no user
201*c689edbbSJens Wiklandervalue.
202*c689edbbSJens Wiklander
203*c689edbbSJens WiklanderSymbols with no user value (or that have a user value but are not visible) and
204*c689edbbSJens Wiklanderno (active) 'default' default to n for bool/tristate symbols, and to the empty
205*c689edbbSJens Wiklanderstring for other symbol types.
206*c689edbbSJens Wiklander
207*c689edbbSJens Wiklander'select' works similarly to symbol visibility, but sets a lower bound on the
208*c689edbbSJens Wiklandervalue of the symbol. The lower bound is determined by the value of the
209*c689edbbSJens Wiklanderselect*ing* symbol. 'select' does not respect visibility, so non-visible
210*c689edbbSJens Wiklandersymbols can be forced to a particular (minimum) value by a select as well.
211*c689edbbSJens Wiklander
212*c689edbbSJens WiklanderFor non-bool/tristate symbols, it only matters whether the visibility is n or
213*c689edbbSJens Wiklandernon-n: m visibility acts the same as y visibility.
214*c689edbbSJens Wiklander
215*c689edbbSJens WiklanderConditions on 'default' and 'select' work in mostly intuitive ways. If the
216*c689edbbSJens Wiklandercondition is n, the 'default' or 'select' is disabled. If it is m, the
217*c689edbbSJens Wiklander'default' or 'select' value (the value of the selecting symbol) is truncated
218*c689edbbSJens Wiklanderdown to m.
219*c689edbbSJens Wiklander
220*c689edbbSJens WiklanderWhen writing a configuration with Kconfig.write_config(), only symbols that are
221*c689edbbSJens Wiklandervisible, have an (active) default, or are selected will get written out (note
222*c689edbbSJens Wiklanderthat this includes all symbols that would accept user values). Kconfiglib
223*c689edbbSJens Wiklandermatches the .config format produced by the C implementations down to the
224*c689edbbSJens Wiklandercharacter. This eases testing.
225*c689edbbSJens Wiklander
226*c689edbbSJens WiklanderFor a visible bool/tristate symbol FOO with value n, this line is written to
227*c689edbbSJens Wiklander.config:
228*c689edbbSJens Wiklander
229*c689edbbSJens Wiklander    # CONFIG_FOO is not set
230*c689edbbSJens Wiklander
231*c689edbbSJens WiklanderThe point is to remember the user n selection (which might differ from the
232*c689edbbSJens Wiklanderdefault value the symbol would get), while at the same sticking to the rule
233*c689edbbSJens Wiklanderthat undefined corresponds to n (.config uses Makefile format, making the line
234*c689edbbSJens Wiklanderabove a comment). When the .config file is read back in, this line will be
235*c689edbbSJens Wiklandertreated the same as the following assignment:
236*c689edbbSJens Wiklander
237*c689edbbSJens Wiklander    CONFIG_FOO=n
238*c689edbbSJens Wiklander
239*c689edbbSJens WiklanderIn Kconfiglib, the set of (currently) assignable values for a bool/tristate
240*c689edbbSJens Wiklandersymbol appear in Symbol.assignable. For other symbol types, just check if
241*c689edbbSJens Wiklandersym.visibility is non-0 (non-n) to see whether the user value will have an
242*c689edbbSJens Wiklandereffect.
243*c689edbbSJens Wiklander
244*c689edbbSJens Wiklander
245*c689edbbSJens WiklanderIntro to the menu tree
246*c689edbbSJens Wiklander======================
247*c689edbbSJens Wiklander
248*c689edbbSJens WiklanderThe menu structure, as seen in e.g. menuconfig, is represented by a tree of
249*c689edbbSJens WiklanderMenuNode objects. The top node of the configuration corresponds to an implicit
250*c689edbbSJens Wiklandertop-level menu, the title of which is shown at the top in the standard
251*c689edbbSJens Wiklandermenuconfig interface. (The title is also available in Kconfig.mainmenu_text in
252*c689edbbSJens WiklanderKconfiglib.)
253*c689edbbSJens Wiklander
254*c689edbbSJens WiklanderThe top node is found in Kconfig.top_node. From there, you can visit child menu
255*c689edbbSJens Wiklandernodes by following the 'list' pointer, and any following menu nodes by
256*c689edbbSJens Wiklanderfollowing the 'next' pointer. Usually, a non-None 'list' pointer indicates a
257*c689edbbSJens Wiklandermenu or Choice, but menu nodes for symbols can sometimes have a non-None 'list'
258*c689edbbSJens Wiklanderpointer too due to submenus created implicitly from dependencies.
259*c689edbbSJens Wiklander
260*c689edbbSJens WiklanderMenuNode.item is either a Symbol or a Choice object, or one of the constants
261*c689edbbSJens WiklanderMENU and COMMENT. The prompt of the menu node can be found in MenuNode.prompt,
262*c689edbbSJens Wiklanderwhich also holds the title for menus and comments. For Symbol and Choice,
263*c689edbbSJens WiklanderMenuNode.help holds the help text (if any, otherwise None).
264*c689edbbSJens Wiklander
265*c689edbbSJens WiklanderMost symbols will only have a single menu node. A symbol defined in multiple
266*c689edbbSJens Wiklanderlocations will have one menu node for each location. The list of menu nodes for
267*c689edbbSJens Wiklandera Symbol or Choice can be found in the Symbol/Choice.nodes attribute.
268*c689edbbSJens Wiklander
269*c689edbbSJens WiklanderNote that prompts and help texts for symbols and choices are stored in their
270*c689edbbSJens Wiklandermenu node(s) rather than in the Symbol or Choice objects themselves. This makes
271*c689edbbSJens Wiklanderit possible to define a symbol in multiple locations with a different prompt or
272*c689edbbSJens Wiklanderhelp text in each location. To get the help text or prompt for a symbol with a
273*c689edbbSJens Wiklandersingle menu node, do sym.nodes[0].help and sym.nodes[0].prompt, respectively.
274*c689edbbSJens WiklanderThe prompt is a (text, condition) tuple, where condition determines the
275*c689edbbSJens Wiklandervisibility (see 'Intro to expressions' below).
276*c689edbbSJens Wiklander
277*c689edbbSJens WiklanderThis organization mirrors the C implementation. MenuNode is called
278*c689edbbSJens Wiklander'struct menu' there, but I thought "menu" was a confusing name.
279*c689edbbSJens Wiklander
280*c689edbbSJens WiklanderIt is possible to give a Choice a name and define it in multiple locations,
281*c689edbbSJens Wiklanderhence why Choice.nodes is also a list.
282*c689edbbSJens Wiklander
283*c689edbbSJens WiklanderAs a convenience, the properties added at a particular definition location are
284*c689edbbSJens Wiklanderavailable on the MenuNode itself, in e.g. MenuNode.defaults. This is helpful
285*c689edbbSJens Wiklanderwhen generating documentation, so that symbols/choices defined in multiple
286*c689edbbSJens Wiklanderlocations can be shown with the correct properties at each location.
287*c689edbbSJens Wiklander
288*c689edbbSJens Wiklander
289*c689edbbSJens WiklanderIntro to expressions
290*c689edbbSJens Wiklander====================
291*c689edbbSJens Wiklander
292*c689edbbSJens WiklanderExpressions can be evaluated with the expr_value() function and printed with
293*c689edbbSJens Wiklanderthe expr_str() function (these are used internally as well). Evaluating an
294*c689edbbSJens Wiklanderexpression always yields a tristate value, where n, m, and y are represented as
295*c689edbbSJens Wiklander0, 1, and 2, respectively.
296*c689edbbSJens Wiklander
297*c689edbbSJens WiklanderThe following table should help you figure out how expressions are represented.
298*c689edbbSJens WiklanderA, B, C, ... are symbols (Symbol instances), NOT is the kconfiglib.NOT
299*c689edbbSJens Wiklanderconstant, etc.
300*c689edbbSJens Wiklander
301*c689edbbSJens WiklanderExpression            Representation
302*c689edbbSJens Wiklander----------            --------------
303*c689edbbSJens WiklanderA                     A
304*c689edbbSJens Wiklander"A"                   A (constant symbol)
305*c689edbbSJens Wiklander!A                    (NOT, A)
306*c689edbbSJens WiklanderA && B                (AND, A, B)
307*c689edbbSJens WiklanderA && B && C           (AND, A, (AND, B, C))
308*c689edbbSJens WiklanderA || B                (OR, A, B)
309*c689edbbSJens WiklanderA || (B && C && D)    (OR, A, (AND, B, (AND, C, D)))
310*c689edbbSJens WiklanderA = B                 (EQUAL, A, B)
311*c689edbbSJens WiklanderA != "foo"            (UNEQUAL, A, foo (constant symbol))
312*c689edbbSJens WiklanderA && B = C && D       (AND, A, (AND, (EQUAL, B, C), D))
313*c689edbbSJens Wiklandern                     Kconfig.n (constant symbol)
314*c689edbbSJens Wiklanderm                     Kconfig.m (constant symbol)
315*c689edbbSJens Wiklandery                     Kconfig.y (constant symbol)
316*c689edbbSJens Wiklander"y"                   Kconfig.y (constant symbol)
317*c689edbbSJens Wiklander
318*c689edbbSJens WiklanderStrings like "foo" in 'default "foo"' or 'depends on SYM = "foo"' are
319*c689edbbSJens Wiklanderrepresented as constant symbols, so the only values that appear in expressions
320*c689edbbSJens Wiklanderare symbols***. This mirrors the C implementation.
321*c689edbbSJens Wiklander
322*c689edbbSJens Wiklander***For choice symbols, the parent Choice will appear in expressions as well,
323*c689edbbSJens Wiklanderbut it's usually invisible as the value interfaces of Symbol and Choice are
324*c689edbbSJens Wiklanderidentical. This mirrors the C implementation and makes different choice modes
325*c689edbbSJens Wiklander"just work".
326*c689edbbSJens Wiklander
327*c689edbbSJens WiklanderManual evaluation examples:
328*c689edbbSJens Wiklander
329*c689edbbSJens Wiklander  - The value of A && B is min(A.tri_value, B.tri_value)
330*c689edbbSJens Wiklander
331*c689edbbSJens Wiklander  - The value of A || B is max(A.tri_value, B.tri_value)
332*c689edbbSJens Wiklander
333*c689edbbSJens Wiklander  - The value of !A is 2 - A.tri_value
334*c689edbbSJens Wiklander
335*c689edbbSJens Wiklander  - The value of A = B is 2 (y) if A.str_value == B.str_value, and 0 (n)
336*c689edbbSJens Wiklander    otherwise. Note that str_value is used here instead of tri_value.
337*c689edbbSJens Wiklander
338*c689edbbSJens Wiklander    For constant (as well as undefined) symbols, str_value matches the name of
339*c689edbbSJens Wiklander    the symbol. This mirrors the C implementation and explains why
340*c689edbbSJens Wiklander    'depends on SYM = "foo"' above works as expected.
341*c689edbbSJens Wiklander
342*c689edbbSJens Wiklandern/m/y are automatically converted to the corresponding constant symbols
343*c689edbbSJens Wiklander"n"/"m"/"y" (Kconfig.n/m/y) during parsing.
344*c689edbbSJens Wiklander
345*c689edbbSJens WiklanderKconfig.const_syms is a dictionary like Kconfig.syms but for constant symbols.
346*c689edbbSJens Wiklander
347*c689edbbSJens WiklanderIf a condition is missing (e.g., <cond> when the 'if <cond>' is removed from
348*c689edbbSJens Wiklander'default A if <cond>'), it is actually Kconfig.y. The standard __str__()
349*c689edbbSJens Wiklanderfunctions just avoid printing 'if y' conditions to give cleaner output.
350*c689edbbSJens Wiklander
351*c689edbbSJens Wiklander
352*c689edbbSJens WiklanderKconfig extensions
353*c689edbbSJens Wiklander==================
354*c689edbbSJens Wiklander
355*c689edbbSJens WiklanderKconfiglib includes a couple of Kconfig extensions:
356*c689edbbSJens Wiklander
357*c689edbbSJens Wiklander'source' with relative path
358*c689edbbSJens Wiklander---------------------------
359*c689edbbSJens Wiklander
360*c689edbbSJens WiklanderThe 'rsource' statement sources Kconfig files with a path relative to directory
361*c689edbbSJens Wiklanderof the Kconfig file containing the 'rsource' statement, instead of relative to
362*c689edbbSJens Wiklanderthe project root.
363*c689edbbSJens Wiklander
364*c689edbbSJens WiklanderConsider following directory tree:
365*c689edbbSJens Wiklander
366*c689edbbSJens Wiklander  Project
367*c689edbbSJens Wiklander  +--Kconfig
368*c689edbbSJens Wiklander  |
369*c689edbbSJens Wiklander  +--src
370*c689edbbSJens Wiklander     +--Kconfig
371*c689edbbSJens Wiklander     |
372*c689edbbSJens Wiklander     +--SubSystem1
373*c689edbbSJens Wiklander        +--Kconfig
374*c689edbbSJens Wiklander        |
375*c689edbbSJens Wiklander        +--ModuleA
376*c689edbbSJens Wiklander           +--Kconfig
377*c689edbbSJens Wiklander
378*c689edbbSJens WiklanderIn this example, assume that src/SubSystem1/Kconfig wants to source
379*c689edbbSJens Wiklandersrc/SubSystem1/ModuleA/Kconfig.
380*c689edbbSJens Wiklander
381*c689edbbSJens WiklanderWith 'source', this statement would be used:
382*c689edbbSJens Wiklander
383*c689edbbSJens Wiklander  source "src/SubSystem1/ModuleA/Kconfig"
384*c689edbbSJens Wiklander
385*c689edbbSJens WiklanderWith 'rsource', this turns into
386*c689edbbSJens Wiklander
387*c689edbbSJens Wiklander  rsource "ModuleA/Kconfig"
388*c689edbbSJens Wiklander
389*c689edbbSJens WiklanderIf an absolute path is given to 'rsource', it acts the same as 'source'.
390*c689edbbSJens Wiklander
391*c689edbbSJens Wiklander'rsource' can be used to create "position-independent" Kconfig trees that can
392*c689edbbSJens Wiklanderbe moved around freely.
393*c689edbbSJens Wiklander
394*c689edbbSJens Wiklander
395*c689edbbSJens WiklanderGlobbing 'source'
396*c689edbbSJens Wiklander-----------------
397*c689edbbSJens Wiklander
398*c689edbbSJens Wiklander'source' and 'rsource' accept glob patterns, sourcing all matching Kconfig
399*c689edbbSJens Wiklanderfiles. They require at least one matching file, raising a KconfigError
400*c689edbbSJens Wiklanderotherwise.
401*c689edbbSJens Wiklander
402*c689edbbSJens WiklanderFor example, the following statement might source sub1/foofoofoo and
403*c689edbbSJens Wiklandersub2/foobarfoo:
404*c689edbbSJens Wiklander
405*c689edbbSJens Wiklander  source "sub[12]/foo*foo"
406*c689edbbSJens Wiklander
407*c689edbbSJens WiklanderThe glob patterns accepted are the same as for the standard glob.glob()
408*c689edbbSJens Wiklanderfunction.
409*c689edbbSJens Wiklander
410*c689edbbSJens WiklanderTwo additional statements are provided for cases where it's acceptable for a
411*c689edbbSJens Wiklanderpattern to match no files: 'osource' and 'orsource' (the o is for "optional").
412*c689edbbSJens Wiklander
413*c689edbbSJens WiklanderFor example, the following statements will be no-ops if neither "foo" nor any
414*c689edbbSJens Wiklanderfiles matching "bar*" exist:
415*c689edbbSJens Wiklander
416*c689edbbSJens Wiklander  osource "foo"
417*c689edbbSJens Wiklander  osource "bar*"
418*c689edbbSJens Wiklander
419*c689edbbSJens Wiklander'orsource' does a relative optional source.
420*c689edbbSJens Wiklander
421*c689edbbSJens Wiklander'source' and 'osource' are analogous to 'include' and '-include' in Make.
422*c689edbbSJens Wiklander
423*c689edbbSJens Wiklander
424*c689edbbSJens WiklanderGeneralized def_* keywords
425*c689edbbSJens Wiklander--------------------------
426*c689edbbSJens Wiklander
427*c689edbbSJens Wiklanderdef_int, def_hex, and def_string are available in addition to def_bool and
428*c689edbbSJens Wiklanderdef_tristate, allowing int, hex, and string symbols to be given a type and a
429*c689edbbSJens Wiklanderdefault at the same time.
430*c689edbbSJens Wiklander
431*c689edbbSJens Wiklander
432*c689edbbSJens WiklanderExtra optional warnings
433*c689edbbSJens Wiklander-----------------------
434*c689edbbSJens Wiklander
435*c689edbbSJens WiklanderSome optional warnings can be controlled via environment variables:
436*c689edbbSJens Wiklander
437*c689edbbSJens Wiklander  - KCONFIG_WARN_UNDEF: If set to 'y', warnings will be generated for all
438*c689edbbSJens Wiklander    references to undefined symbols within Kconfig files. The only gotcha is
439*c689edbbSJens Wiklander    that all hex literals must be prefixed with "0x" or "0X", to make it
440*c689edbbSJens Wiklander    possible to distinguish them from symbol references.
441*c689edbbSJens Wiklander
442*c689edbbSJens Wiklander    Some projects (e.g. the Linux kernel) use multiple Kconfig trees with many
443*c689edbbSJens Wiklander    shared Kconfig files, leading to some safe undefined symbol references.
444*c689edbbSJens Wiklander    KCONFIG_WARN_UNDEF is useful in projects that only have a single Kconfig
445*c689edbbSJens Wiklander    tree though.
446*c689edbbSJens Wiklander
447*c689edbbSJens Wiklander    KCONFIG_STRICT is an older alias for this environment variable, supported
448*c689edbbSJens Wiklander    for backwards compatibility.
449*c689edbbSJens Wiklander
450*c689edbbSJens Wiklander  - KCONFIG_WARN_UNDEF_ASSIGN: If set to 'y', warnings will be generated for
451*c689edbbSJens Wiklander    all assignments to undefined symbols within .config files. By default, no
452*c689edbbSJens Wiklander    such warnings are generated.
453*c689edbbSJens Wiklander
454*c689edbbSJens Wiklander    This warning can also be enabled/disabled via the Kconfig.warn_assign_undef
455*c689edbbSJens Wiklander    variable.
456*c689edbbSJens Wiklander
457*c689edbbSJens Wiklander
458*c689edbbSJens WiklanderPreprocessor user functions defined in Python
459*c689edbbSJens Wiklander---------------------------------------------
460*c689edbbSJens Wiklander
461*c689edbbSJens WiklanderPreprocessor functions can be defined in Python, which makes it simple to
462*c689edbbSJens Wiklanderintegrate information from existing Python tools into Kconfig (e.g. to have
463*c689edbbSJens WiklanderKconfig symbols depend on hardware information stored in some other format).
464*c689edbbSJens Wiklander
465*c689edbbSJens WiklanderPutting a Python module named kconfigfunctions(.py) anywhere in sys.path will
466*c689edbbSJens Wiklandercause it to be imported by Kconfiglib (in Kconfig.__init__()). Note that
467*c689edbbSJens Wiklandersys.path can be customized via PYTHONPATH, and includes the directory of the
468*c689edbbSJens Wiklandermodule being run by default, as well as installation directories.
469*c689edbbSJens Wiklander
470*c689edbbSJens WiklanderIf the KCONFIG_FUNCTIONS environment variable is set, it gives a different
471*c689edbbSJens Wiklandermodule name to use instead of 'kconfigfunctions'.
472*c689edbbSJens Wiklander
473*c689edbbSJens WiklanderThe imported module is expected to define a global dictionary named 'functions'
474*c689edbbSJens Wiklanderthat maps function names to Python functions, as follows:
475*c689edbbSJens Wiklander
476*c689edbbSJens Wiklander  def my_fn(kconf, name, arg_1, arg_2, ...):
477*c689edbbSJens Wiklander      # kconf:
478*c689edbbSJens Wiklander      #   Kconfig instance
479*c689edbbSJens Wiklander      #
480*c689edbbSJens Wiklander      # name:
481*c689edbbSJens Wiklander      #   Name of the user-defined function ("my-fn"). Think argv[0].
482*c689edbbSJens Wiklander      #
483*c689edbbSJens Wiklander      # arg_1, arg_2, ...:
484*c689edbbSJens Wiklander      #   Arguments passed to the function from Kconfig (strings)
485*c689edbbSJens Wiklander      #
486*c689edbbSJens Wiklander      # Returns a string to be substituted as the result of calling the
487*c689edbbSJens Wiklander      # function
488*c689edbbSJens Wiklander      ...
489*c689edbbSJens Wiklander
490*c689edbbSJens Wiklander  def my_other_fn(kconf, name, arg_1, arg_2, ...):
491*c689edbbSJens Wiklander      ...
492*c689edbbSJens Wiklander
493*c689edbbSJens Wiklander  functions = {
494*c689edbbSJens Wiklander      "my-fn":       (my_fn,       <min.args>, <max.args>/None),
495*c689edbbSJens Wiklander      "my-other-fn": (my_other_fn, <min.args>, <max.args>/None),
496*c689edbbSJens Wiklander      ...
497*c689edbbSJens Wiklander  }
498*c689edbbSJens Wiklander
499*c689edbbSJens Wiklander  ...
500*c689edbbSJens Wiklander
501*c689edbbSJens Wiklander<min.args> and <max.args> are the minimum and maximum number of arguments
502*c689edbbSJens Wiklanderexpected by the function (excluding the implicit 'name' argument). If
503*c689edbbSJens Wiklander<max.args> is None, there is no upper limit to the number of arguments. Passing
504*c689edbbSJens Wiklanderan invalid number of arguments will generate a KconfigError exception.
505*c689edbbSJens Wiklander
506*c689edbbSJens WiklanderFunctions can access the current parsing location as kconf.filename/linenr.
507*c689edbbSJens WiklanderAccessing other fields of the Kconfig object is not safe. See the warning
508*c689edbbSJens Wiklanderbelow.
509*c689edbbSJens Wiklander
510*c689edbbSJens WiklanderKeep in mind that for a variable defined like 'foo = $(fn)', 'fn' will be
511*c689edbbSJens Wiklandercalled only when 'foo' is expanded. If 'fn' uses the parsing location and the
512*c689edbbSJens Wiklanderintent is to use the location of the assignment, you want 'foo := $(fn)'
513*c689edbbSJens Wiklanderinstead, which calls the function immediately.
514*c689edbbSJens Wiklander
515*c689edbbSJens WiklanderOnce defined, user functions can be called from Kconfig in the same way as
516*c689edbbSJens Wiklanderother preprocessor functions:
517*c689edbbSJens Wiklander
518*c689edbbSJens Wiklander    config FOO
519*c689edbbSJens Wiklander        ...
520*c689edbbSJens Wiklander        depends on $(my-fn,arg1,arg2)
521*c689edbbSJens Wiklander
522*c689edbbSJens WiklanderIf my_fn() returns "n", this will result in
523*c689edbbSJens Wiklander
524*c689edbbSJens Wiklander    config FOO
525*c689edbbSJens Wiklander        ...
526*c689edbbSJens Wiklander        depends on n
527*c689edbbSJens Wiklander
528*c689edbbSJens WiklanderWarning
529*c689edbbSJens Wiklander*******
530*c689edbbSJens Wiklander
531*c689edbbSJens WiklanderUser-defined preprocessor functions are called as they're encountered at parse
532*c689edbbSJens Wiklandertime, before all Kconfig files have been processed, and before the menu tree
533*c689edbbSJens Wiklanderhas been finalized. There are no guarantees that accessing Kconfig symbols or
534*c689edbbSJens Wiklanderthe menu tree via the 'kconf' parameter will work, and it could potentially
535*c689edbbSJens Wiklanderlead to a crash.
536*c689edbbSJens Wiklander
537*c689edbbSJens WiklanderPreferably, user-defined functions should be stateless.
538*c689edbbSJens Wiklander
539*c689edbbSJens Wiklander
540*c689edbbSJens WiklanderFeedback
541*c689edbbSJens Wiklander========
542*c689edbbSJens Wiklander
543*c689edbbSJens WiklanderFor bug reports, suggestions, and questions, please open a ticket on the GitHub
544*c689edbbSJens Wiklanderpage.
545*c689edbbSJens Wiklander"""
546*c689edbbSJens Wiklanderimport errno
547*c689edbbSJens Wiklanderimport importlib
548*c689edbbSJens Wiklanderimport os
549*c689edbbSJens Wiklanderimport re
550*c689edbbSJens Wiklanderimport sys
551*c689edbbSJens Wiklander
552*c689edbbSJens Wiklander# Get rid of some attribute lookups. These are obvious in context.
553*c689edbbSJens Wiklanderfrom glob import iglob
554*c689edbbSJens Wiklanderfrom os.path import dirname, exists, expandvars, islink, join, realpath
555*c689edbbSJens Wiklander
556*c689edbbSJens Wiklander
557*c689edbbSJens WiklanderVERSION = (14, 1, 0)
558*c689edbbSJens Wiklander
559*c689edbbSJens Wiklander
560*c689edbbSJens Wiklander# File layout:
561*c689edbbSJens Wiklander#
562*c689edbbSJens Wiklander# Public classes
563*c689edbbSJens Wiklander# Public functions
564*c689edbbSJens Wiklander# Internal functions
565*c689edbbSJens Wiklander# Global constants
566*c689edbbSJens Wiklander
567*c689edbbSJens Wiklander# Line length: 79 columns
568*c689edbbSJens Wiklander
569*c689edbbSJens Wiklander
570*c689edbbSJens Wiklander#
571*c689edbbSJens Wiklander# Public classes
572*c689edbbSJens Wiklander#
573*c689edbbSJens Wiklander
574*c689edbbSJens Wiklander
575*c689edbbSJens Wiklanderclass Kconfig(object):
576*c689edbbSJens Wiklander    """
577*c689edbbSJens Wiklander    Represents a Kconfig configuration, e.g. for x86 or ARM. This is the set of
578*c689edbbSJens Wiklander    symbols, choices, and menu nodes appearing in the configuration. Creating
579*c689edbbSJens Wiklander    any number of Kconfig objects (including for different architectures) is
580*c689edbbSJens Wiklander    safe. Kconfiglib doesn't keep any global state.
581*c689edbbSJens Wiklander
582*c689edbbSJens Wiklander    The following attributes are available. They should be treated as
583*c689edbbSJens Wiklander    read-only, and some are implemented through @property magic.
584*c689edbbSJens Wiklander
585*c689edbbSJens Wiklander    syms:
586*c689edbbSJens Wiklander      A dictionary with all symbols in the configuration, indexed by name. Also
587*c689edbbSJens Wiklander      includes all symbols that are referenced in expressions but never
588*c689edbbSJens Wiklander      defined, except for constant (quoted) symbols.
589*c689edbbSJens Wiklander
590*c689edbbSJens Wiklander      Undefined symbols can be recognized by Symbol.nodes being empty -- see
591*c689edbbSJens Wiklander      the 'Intro to the menu tree' section in the module docstring.
592*c689edbbSJens Wiklander
593*c689edbbSJens Wiklander    const_syms:
594*c689edbbSJens Wiklander      A dictionary like 'syms' for constant (quoted) symbols
595*c689edbbSJens Wiklander
596*c689edbbSJens Wiklander    named_choices:
597*c689edbbSJens Wiklander      A dictionary like 'syms' for named choices (choice FOO)
598*c689edbbSJens Wiklander
599*c689edbbSJens Wiklander    defined_syms:
600*c689edbbSJens Wiklander      A list with all defined symbols, in the same order as they appear in the
601*c689edbbSJens Wiklander      Kconfig files. Symbols defined in multiple locations appear multiple
602*c689edbbSJens Wiklander      times.
603*c689edbbSJens Wiklander
604*c689edbbSJens Wiklander      Note: You probably want to use 'unique_defined_syms' instead. This
605*c689edbbSJens Wiklander      attribute is mostly maintained for backwards compatibility.
606*c689edbbSJens Wiklander
607*c689edbbSJens Wiklander    unique_defined_syms:
608*c689edbbSJens Wiklander      A list like 'defined_syms', but with duplicates removed. Just the first
609*c689edbbSJens Wiklander      instance is kept for symbols defined in multiple locations. Kconfig order
610*c689edbbSJens Wiklander      is preserved otherwise.
611*c689edbbSJens Wiklander
612*c689edbbSJens Wiklander      Using this attribute instead of 'defined_syms' can save work, and
613*c689edbbSJens Wiklander      automatically gives reasonable behavior when writing configuration output
614*c689edbbSJens Wiklander      (symbols defined in multiple locations only generate output once, while
615*c689edbbSJens Wiklander      still preserving Kconfig order for readability).
616*c689edbbSJens Wiklander
617*c689edbbSJens Wiklander    choices:
618*c689edbbSJens Wiklander      A list with all choices, in the same order as they appear in the Kconfig
619*c689edbbSJens Wiklander      files.
620*c689edbbSJens Wiklander
621*c689edbbSJens Wiklander      Note: You probably want to use 'unique_choices' instead. This attribute
622*c689edbbSJens Wiklander      is mostly maintained for backwards compatibility.
623*c689edbbSJens Wiklander
624*c689edbbSJens Wiklander    unique_choices:
625*c689edbbSJens Wiklander      Analogous to 'unique_defined_syms', for choices. Named choices can have
626*c689edbbSJens Wiklander      multiple definition locations.
627*c689edbbSJens Wiklander
628*c689edbbSJens Wiklander    menus:
629*c689edbbSJens Wiklander      A list with all menus, in the same order as they appear in the Kconfig
630*c689edbbSJens Wiklander      files
631*c689edbbSJens Wiklander
632*c689edbbSJens Wiklander    comments:
633*c689edbbSJens Wiklander      A list with all comments, in the same order as they appear in the Kconfig
634*c689edbbSJens Wiklander      files
635*c689edbbSJens Wiklander
636*c689edbbSJens Wiklander    kconfig_filenames:
637*c689edbbSJens Wiklander      A list with the filenames of all Kconfig files included in the
638*c689edbbSJens Wiklander      configuration, relative to $srctree (or relative to the current directory
639*c689edbbSJens Wiklander      if $srctree isn't set), except absolute paths (e.g.
640*c689edbbSJens Wiklander      'source "/foo/Kconfig"') are kept as-is.
641*c689edbbSJens Wiklander
642*c689edbbSJens Wiklander      The files are listed in the order they are source'd, starting with the
643*c689edbbSJens Wiklander      top-level Kconfig file. If a file is source'd multiple times, it will
644*c689edbbSJens Wiklander      appear multiple times. Use set() to get unique filenames.
645*c689edbbSJens Wiklander
646*c689edbbSJens Wiklander      Note that Kconfig.sync_deps() already indirectly catches any file
647*c689edbbSJens Wiklander      modifications that change configuration output.
648*c689edbbSJens Wiklander
649*c689edbbSJens Wiklander    env_vars:
650*c689edbbSJens Wiklander      A set() with the names of all environment variables referenced in the
651*c689edbbSJens Wiklander      Kconfig files.
652*c689edbbSJens Wiklander
653*c689edbbSJens Wiklander      Only environment variables referenced with the preprocessor $(FOO) syntax
654*c689edbbSJens Wiklander      will be registered. The older $FOO syntax is only supported for backwards
655*c689edbbSJens Wiklander      compatibility.
656*c689edbbSJens Wiklander
657*c689edbbSJens Wiklander      Also note that $(FOO) won't be registered unless the environment variable
658*c689edbbSJens Wiklander      $FOO is actually set. If it isn't, $(FOO) is an expansion of an unset
659*c689edbbSJens Wiklander      preprocessor variable (which gives the empty string).
660*c689edbbSJens Wiklander
661*c689edbbSJens Wiklander      Another gotcha is that environment variables referenced in the values of
662*c689edbbSJens Wiklander      recursively expanded preprocessor variables (those defined with =) will
663*c689edbbSJens Wiklander      only be registered if the variable is actually used (expanded) somewhere.
664*c689edbbSJens Wiklander
665*c689edbbSJens Wiklander      The note from the 'kconfig_filenames' documentation applies here too.
666*c689edbbSJens Wiklander
667*c689edbbSJens Wiklander    n/m/y:
668*c689edbbSJens Wiklander      The predefined constant symbols n/m/y. Also available in const_syms.
669*c689edbbSJens Wiklander
670*c689edbbSJens Wiklander    modules:
671*c689edbbSJens Wiklander      The Symbol instance for the modules symbol. Currently hardcoded to
672*c689edbbSJens Wiklander      MODULES, which is backwards compatible. Kconfiglib will warn if
673*c689edbbSJens Wiklander      'option modules' is set on some other symbol. Tell me if you need proper
674*c689edbbSJens Wiklander      'option modules' support.
675*c689edbbSJens Wiklander
676*c689edbbSJens Wiklander      'modules' is never None. If the MODULES symbol is not explicitly defined,
677*c689edbbSJens Wiklander      its tri_value will be 0 (n), as expected.
678*c689edbbSJens Wiklander
679*c689edbbSJens Wiklander      A simple way to enable modules is to do 'kconf.modules.set_value(2)'
680*c689edbbSJens Wiklander      (provided the MODULES symbol is defined and visible). Modules are
681*c689edbbSJens Wiklander      disabled by default in the kernel Kconfig files as of writing, though
682*c689edbbSJens Wiklander      nearly all defconfig files enable them (with 'CONFIG_MODULES=y').
683*c689edbbSJens Wiklander
684*c689edbbSJens Wiklander    defconfig_list:
685*c689edbbSJens Wiklander      The Symbol instance for the 'option defconfig_list' symbol, or None if no
686*c689edbbSJens Wiklander      defconfig_list symbol exists. The defconfig filename derived from this
687*c689edbbSJens Wiklander      symbol can be found in Kconfig.defconfig_filename.
688*c689edbbSJens Wiklander
689*c689edbbSJens Wiklander    defconfig_filename:
690*c689edbbSJens Wiklander      The filename given by the defconfig_list symbol. This is taken from the
691*c689edbbSJens Wiklander      first 'default' with a satisfied condition where the specified file
692*c689edbbSJens Wiklander      exists (can be opened for reading). If a defconfig file foo/defconfig is
693*c689edbbSJens Wiklander      not found and $srctree was set when the Kconfig was created,
694*c689edbbSJens Wiklander      $srctree/foo/defconfig is looked up as well.
695*c689edbbSJens Wiklander
696*c689edbbSJens Wiklander      'defconfig_filename' is None if either no defconfig_list symbol exists,
697*c689edbbSJens Wiklander      or if the defconfig_list symbol has no 'default' with a satisfied
698*c689edbbSJens Wiklander      condition that specifies a file that exists.
699*c689edbbSJens Wiklander
700*c689edbbSJens Wiklander      Gotcha: scripts/kconfig/Makefile might pass --defconfig=<defconfig> to
701*c689edbbSJens Wiklander      scripts/kconfig/conf when running e.g. 'make defconfig'. This option
702*c689edbbSJens Wiklander      overrides the defconfig_list symbol, meaning defconfig_filename might not
703*c689edbbSJens Wiklander      always match what 'make defconfig' would use.
704*c689edbbSJens Wiklander
705*c689edbbSJens Wiklander    top_node:
706*c689edbbSJens Wiklander      The menu node (see the MenuNode class) of the implicit top-level menu.
707*c689edbbSJens Wiklander      Acts as the root of the menu tree.
708*c689edbbSJens Wiklander
709*c689edbbSJens Wiklander    mainmenu_text:
710*c689edbbSJens Wiklander      The prompt (title) of the top menu (top_node). Defaults to "Main menu".
711*c689edbbSJens Wiklander      Can be changed with the 'mainmenu' statement (see kconfig-language.txt).
712*c689edbbSJens Wiklander
713*c689edbbSJens Wiklander    variables:
714*c689edbbSJens Wiklander      A dictionary with all preprocessor variables, indexed by name. See the
715*c689edbbSJens Wiklander      Variable class.
716*c689edbbSJens Wiklander
717*c689edbbSJens Wiklander    warn:
718*c689edbbSJens Wiklander      Set this variable to True/False to enable/disable warnings. See
719*c689edbbSJens Wiklander      Kconfig.__init__().
720*c689edbbSJens Wiklander
721*c689edbbSJens Wiklander      When 'warn' is False, the values of the other warning-related variables
722*c689edbbSJens Wiklander      are ignored.
723*c689edbbSJens Wiklander
724*c689edbbSJens Wiklander      This variable as well as the other warn* variables can be read to check
725*c689edbbSJens Wiklander      the current warning settings.
726*c689edbbSJens Wiklander
727*c689edbbSJens Wiklander    warn_to_stderr:
728*c689edbbSJens Wiklander      Set this variable to True/False to enable/disable warnings on stderr. See
729*c689edbbSJens Wiklander      Kconfig.__init__().
730*c689edbbSJens Wiklander
731*c689edbbSJens Wiklander    warn_assign_undef:
732*c689edbbSJens Wiklander      Set this variable to True to generate warnings for assignments to
733*c689edbbSJens Wiklander      undefined symbols in configuration files.
734*c689edbbSJens Wiklander
735*c689edbbSJens Wiklander      This variable is False by default unless the KCONFIG_WARN_UNDEF_ASSIGN
736*c689edbbSJens Wiklander      environment variable was set to 'y' when the Kconfig instance was
737*c689edbbSJens Wiklander      created.
738*c689edbbSJens Wiklander
739*c689edbbSJens Wiklander    warn_assign_override:
740*c689edbbSJens Wiklander      Set this variable to True to generate warnings for multiple assignments
741*c689edbbSJens Wiklander      to the same symbol in configuration files, where the assignments set
742*c689edbbSJens Wiklander      different values (e.g. CONFIG_FOO=m followed by CONFIG_FOO=y, where the
743*c689edbbSJens Wiklander      last value would get used).
744*c689edbbSJens Wiklander
745*c689edbbSJens Wiklander      This variable is True by default. Disabling it might be useful when
746*c689edbbSJens Wiklander      merging configurations.
747*c689edbbSJens Wiklander
748*c689edbbSJens Wiklander    warn_assign_redun:
749*c689edbbSJens Wiklander      Like warn_assign_override, but for multiple assignments setting a symbol
750*c689edbbSJens Wiklander      to the same value.
751*c689edbbSJens Wiklander
752*c689edbbSJens Wiklander      This variable is True by default. Disabling it might be useful when
753*c689edbbSJens Wiklander      merging configurations.
754*c689edbbSJens Wiklander
755*c689edbbSJens Wiklander    warnings:
756*c689edbbSJens Wiklander      A list of strings containing all warnings that have been generated, for
757*c689edbbSJens Wiklander      cases where more flexibility is needed.
758*c689edbbSJens Wiklander
759*c689edbbSJens Wiklander      See the 'warn_to_stderr' parameter to Kconfig.__init__() and the
760*c689edbbSJens Wiklander      Kconfig.warn_to_stderr variable as well. Note that warnings still get
761*c689edbbSJens Wiklander      added to Kconfig.warnings when 'warn_to_stderr' is True.
762*c689edbbSJens Wiklander
763*c689edbbSJens Wiklander      Just as for warnings printed to stderr, only warnings that are enabled
764*c689edbbSJens Wiklander      will get added to Kconfig.warnings. See the various Kconfig.warn*
765*c689edbbSJens Wiklander      variables.
766*c689edbbSJens Wiklander
767*c689edbbSJens Wiklander    missing_syms:
768*c689edbbSJens Wiklander      A list with (name, value) tuples for all assignments to undefined symbols
769*c689edbbSJens Wiklander      within the most recently loaded .config file(s). 'name' is the symbol
770*c689edbbSJens Wiklander      name without the 'CONFIG_' prefix. 'value' is a string that gives the
771*c689edbbSJens Wiklander      right-hand side of the assignment verbatim.
772*c689edbbSJens Wiklander
773*c689edbbSJens Wiklander      See Kconfig.load_config() as well.
774*c689edbbSJens Wiklander
775*c689edbbSJens Wiklander    srctree:
776*c689edbbSJens Wiklander      The value the $srctree environment variable had when the Kconfig instance
777*c689edbbSJens Wiklander      was created, or the empty string if $srctree wasn't set. This gives nice
778*c689edbbSJens Wiklander      behavior with os.path.join(), which treats "" as the current directory,
779*c689edbbSJens Wiklander      without adding "./".
780*c689edbbSJens Wiklander
781*c689edbbSJens Wiklander      Kconfig files are looked up relative to $srctree (unless absolute paths
782*c689edbbSJens Wiklander      are used), and .config files are looked up relative to $srctree if they
783*c689edbbSJens Wiklander      are not found in the current directory. This is used to support
784*c689edbbSJens Wiklander      out-of-tree builds. The C tools use this environment variable in the same
785*c689edbbSJens Wiklander      way.
786*c689edbbSJens Wiklander
787*c689edbbSJens Wiklander      Changing $srctree after creating the Kconfig instance has no effect. Only
788*c689edbbSJens Wiklander      the value when the configuration is loaded matters. This avoids surprises
789*c689edbbSJens Wiklander      if multiple configurations are loaded with different values for $srctree.
790*c689edbbSJens Wiklander
791*c689edbbSJens Wiklander    config_prefix:
792*c689edbbSJens Wiklander      The value the CONFIG_ environment variable had when the Kconfig instance
793*c689edbbSJens Wiklander      was created, or "CONFIG_" if CONFIG_ wasn't set. This is the prefix used
794*c689edbbSJens Wiklander      (and expected) on symbol names in .config files and C headers. Used in
795*c689edbbSJens Wiklander      the same way in the C tools.
796*c689edbbSJens Wiklander
797*c689edbbSJens Wiklander    config_header:
798*c689edbbSJens Wiklander      The value the KCONFIG_CONFIG_HEADER environment variable had when the
799*c689edbbSJens Wiklander      Kconfig instance was created, or the empty string if
800*c689edbbSJens Wiklander      KCONFIG_CONFIG_HEADER wasn't set. This string is inserted verbatim at the
801*c689edbbSJens Wiklander      beginning of configuration files. See write_config().
802*c689edbbSJens Wiklander
803*c689edbbSJens Wiklander    header_header:
804*c689edbbSJens Wiklander      The value the KCONFIG_AUTOHEADER_HEADER environment variable had when the
805*c689edbbSJens Wiklander      Kconfig instance was created, or the empty string if
806*c689edbbSJens Wiklander      KCONFIG_AUTOHEADER_HEADER wasn't set. This string is inserted verbatim at
807*c689edbbSJens Wiklander      the beginning of header files. See write_autoconf().
808*c689edbbSJens Wiklander
809*c689edbbSJens Wiklander    filename/linenr:
810*c689edbbSJens Wiklander      The current parsing location, for use in Python preprocessor functions.
811*c689edbbSJens Wiklander      See the module docstring.
812*c689edbbSJens Wiklander    """
813*c689edbbSJens Wiklander    __slots__ = (
814*c689edbbSJens Wiklander        "_encoding",
815*c689edbbSJens Wiklander        "_functions",
816*c689edbbSJens Wiklander        "_set_match",
817*c689edbbSJens Wiklander        "_srctree_prefix",
818*c689edbbSJens Wiklander        "_unset_match",
819*c689edbbSJens Wiklander        "_warn_assign_no_prompt",
820*c689edbbSJens Wiklander        "choices",
821*c689edbbSJens Wiklander        "comments",
822*c689edbbSJens Wiklander        "config_header",
823*c689edbbSJens Wiklander        "config_prefix",
824*c689edbbSJens Wiklander        "const_syms",
825*c689edbbSJens Wiklander        "defconfig_list",
826*c689edbbSJens Wiklander        "defined_syms",
827*c689edbbSJens Wiklander        "env_vars",
828*c689edbbSJens Wiklander        "header_header",
829*c689edbbSJens Wiklander        "kconfig_filenames",
830*c689edbbSJens Wiklander        "m",
831*c689edbbSJens Wiklander        "menus",
832*c689edbbSJens Wiklander        "missing_syms",
833*c689edbbSJens Wiklander        "modules",
834*c689edbbSJens Wiklander        "n",
835*c689edbbSJens Wiklander        "named_choices",
836*c689edbbSJens Wiklander        "srctree",
837*c689edbbSJens Wiklander        "syms",
838*c689edbbSJens Wiklander        "top_node",
839*c689edbbSJens Wiklander        "unique_choices",
840*c689edbbSJens Wiklander        "unique_defined_syms",
841*c689edbbSJens Wiklander        "variables",
842*c689edbbSJens Wiklander        "warn",
843*c689edbbSJens Wiklander        "warn_assign_override",
844*c689edbbSJens Wiklander        "warn_assign_redun",
845*c689edbbSJens Wiklander        "warn_assign_undef",
846*c689edbbSJens Wiklander        "warn_to_stderr",
847*c689edbbSJens Wiklander        "warnings",
848*c689edbbSJens Wiklander        "y",
849*c689edbbSJens Wiklander
850*c689edbbSJens Wiklander        # Parsing-related
851*c689edbbSJens Wiklander        "_parsing_kconfigs",
852*c689edbbSJens Wiklander        "_readline",
853*c689edbbSJens Wiklander        "filename",
854*c689edbbSJens Wiklander        "linenr",
855*c689edbbSJens Wiklander        "_include_path",
856*c689edbbSJens Wiklander        "_filestack",
857*c689edbbSJens Wiklander        "_line",
858*c689edbbSJens Wiklander        "_tokens",
859*c689edbbSJens Wiklander        "_tokens_i",
860*c689edbbSJens Wiklander        "_reuse_tokens",
861*c689edbbSJens Wiklander    )
862*c689edbbSJens Wiklander
863*c689edbbSJens Wiklander    #
864*c689edbbSJens Wiklander    # Public interface
865*c689edbbSJens Wiklander    #
866*c689edbbSJens Wiklander
867*c689edbbSJens Wiklander    def __init__(self, filename="Kconfig", warn=True, warn_to_stderr=True,
868*c689edbbSJens Wiklander                 encoding="utf-8", suppress_traceback=False):
869*c689edbbSJens Wiklander        """
870*c689edbbSJens Wiklander        Creates a new Kconfig object by parsing Kconfig files.
871*c689edbbSJens Wiklander        Note that Kconfig files are not the same as .config files (which store
872*c689edbbSJens Wiklander        configuration symbol values).
873*c689edbbSJens Wiklander
874*c689edbbSJens Wiklander        See the module docstring for some environment variables that influence
875*c689edbbSJens Wiklander        default warning settings (KCONFIG_WARN_UNDEF and
876*c689edbbSJens Wiklander        KCONFIG_WARN_UNDEF_ASSIGN).
877*c689edbbSJens Wiklander
878*c689edbbSJens Wiklander        Raises KconfigError on syntax/semantic errors, and OSError or (possibly
879*c689edbbSJens Wiklander        a subclass of) IOError on IO errors ('errno', 'strerror', and
880*c689edbbSJens Wiklander        'filename' are available). Note that IOError is an alias for OSError on
881*c689edbbSJens Wiklander        Python 3, so it's enough to catch OSError there. If you need Python 2/3
882*c689edbbSJens Wiklander        compatibility, it's easiest to catch EnvironmentError, which is a
883*c689edbbSJens Wiklander        common base class of OSError/IOError on Python 2 and an alias for
884*c689edbbSJens Wiklander        OSError on Python 3.
885*c689edbbSJens Wiklander
886*c689edbbSJens Wiklander        filename (default: "Kconfig"):
887*c689edbbSJens Wiklander          The Kconfig file to load. For the Linux kernel, you'll want "Kconfig"
888*c689edbbSJens Wiklander          from the top-level directory, as environment variables will make sure
889*c689edbbSJens Wiklander          the right Kconfig is included from there (arch/$SRCARCH/Kconfig as of
890*c689edbbSJens Wiklander          writing).
891*c689edbbSJens Wiklander
892*c689edbbSJens Wiklander          If $srctree is set, 'filename' will be looked up relative to it.
893*c689edbbSJens Wiklander          $srctree is also used to look up source'd files within Kconfig files.
894*c689edbbSJens Wiklander          See the class documentation.
895*c689edbbSJens Wiklander
896*c689edbbSJens Wiklander          If you are using Kconfiglib via 'make scriptconfig', the filename of
897*c689edbbSJens Wiklander          the base base Kconfig file will be in sys.argv[1]. It's currently
898*c689edbbSJens Wiklander          always "Kconfig" in practice.
899*c689edbbSJens Wiklander
900*c689edbbSJens Wiklander        warn (default: True):
901*c689edbbSJens Wiklander          True if warnings related to this configuration should be generated.
902*c689edbbSJens Wiklander          This can be changed later by setting Kconfig.warn to True/False. It
903*c689edbbSJens Wiklander          is provided as a constructor argument since warnings might be
904*c689edbbSJens Wiklander          generated during parsing.
905*c689edbbSJens Wiklander
906*c689edbbSJens Wiklander          See the other Kconfig.warn_* variables as well, which enable or
907*c689edbbSJens Wiklander          suppress certain warnings when warnings are enabled.
908*c689edbbSJens Wiklander
909*c689edbbSJens Wiklander          All generated warnings are added to the Kconfig.warnings list. See
910*c689edbbSJens Wiklander          the class documentation.
911*c689edbbSJens Wiklander
912*c689edbbSJens Wiklander        warn_to_stderr (default: True):
913*c689edbbSJens Wiklander          True if warnings should be printed to stderr in addition to being
914*c689edbbSJens Wiklander          added to Kconfig.warnings.
915*c689edbbSJens Wiklander
916*c689edbbSJens Wiklander          This can be changed later by setting Kconfig.warn_to_stderr to
917*c689edbbSJens Wiklander          True/False.
918*c689edbbSJens Wiklander
919*c689edbbSJens Wiklander        encoding (default: "utf-8"):
920*c689edbbSJens Wiklander          The encoding to use when reading and writing files, and when decoding
921*c689edbbSJens Wiklander          output from commands run via $(shell). If None, the encoding
922*c689edbbSJens Wiklander          specified in the current locale will be used.
923*c689edbbSJens Wiklander
924*c689edbbSJens Wiklander          The "utf-8" default avoids exceptions on systems that are configured
925*c689edbbSJens Wiklander          to use the C locale, which implies an ASCII encoding.
926*c689edbbSJens Wiklander
927*c689edbbSJens Wiklander          This parameter has no effect on Python 2, due to implementation
928*c689edbbSJens Wiklander          issues (regular strings turning into Unicode strings, which are
929*c689edbbSJens Wiklander          distinct in Python 2). Python 2 doesn't decode regular strings
930*c689edbbSJens Wiklander          anyway.
931*c689edbbSJens Wiklander
932*c689edbbSJens Wiklander          Related PEP: https://www.python.org/dev/peps/pep-0538/
933*c689edbbSJens Wiklander
934*c689edbbSJens Wiklander        suppress_traceback (default: False):
935*c689edbbSJens Wiklander          Helper for tools. When True, any EnvironmentError or KconfigError
936*c689edbbSJens Wiklander          generated during parsing is caught, the exception message is printed
937*c689edbbSJens Wiklander          to stderr together with the command name, and sys.exit(1) is called
938*c689edbbSJens Wiklander          (which generates SystemExit).
939*c689edbbSJens Wiklander
940*c689edbbSJens Wiklander          This hides the Python traceback for "expected" errors like syntax
941*c689edbbSJens Wiklander          errors in Kconfig files.
942*c689edbbSJens Wiklander
943*c689edbbSJens Wiklander          Other exceptions besides EnvironmentError and KconfigError are still
944*c689edbbSJens Wiklander          propagated when suppress_traceback is True.
945*c689edbbSJens Wiklander        """
946*c689edbbSJens Wiklander        try:
947*c689edbbSJens Wiklander            self._init(filename, warn, warn_to_stderr, encoding)
948*c689edbbSJens Wiklander        except (EnvironmentError, KconfigError) as e:
949*c689edbbSJens Wiklander            if suppress_traceback:
950*c689edbbSJens Wiklander                cmd = sys.argv[0]  # Empty string if missing
951*c689edbbSJens Wiklander                if cmd:
952*c689edbbSJens Wiklander                    cmd += ": "
953*c689edbbSJens Wiklander                # Some long exception messages have extra newlines for better
954*c689edbbSJens Wiklander                # formatting when reported as an unhandled exception. Strip
955*c689edbbSJens Wiklander                # them here.
956*c689edbbSJens Wiklander                sys.exit(cmd + str(e).strip())
957*c689edbbSJens Wiklander            raise
958*c689edbbSJens Wiklander
959*c689edbbSJens Wiklander    def _init(self, filename, warn, warn_to_stderr, encoding):
960*c689edbbSJens Wiklander        # See __init__()
961*c689edbbSJens Wiklander
962*c689edbbSJens Wiklander        self._encoding = encoding
963*c689edbbSJens Wiklander
964*c689edbbSJens Wiklander        self.srctree = os.getenv("srctree", "")
965*c689edbbSJens Wiklander        # A prefix we can reliably strip from glob() results to get a filename
966*c689edbbSJens Wiklander        # relative to $srctree. relpath() can cause issues for symlinks,
967*c689edbbSJens Wiklander        # because it assumes symlink/../foo is the same as foo/.
968*c689edbbSJens Wiklander        self._srctree_prefix = realpath(self.srctree) + os.sep
969*c689edbbSJens Wiklander
970*c689edbbSJens Wiklander        self.warn = warn
971*c689edbbSJens Wiklander        self.warn_to_stderr = warn_to_stderr
972*c689edbbSJens Wiklander        self.warn_assign_undef = os.getenv("KCONFIG_WARN_UNDEF_ASSIGN") == "y"
973*c689edbbSJens Wiklander        self.warn_assign_override = True
974*c689edbbSJens Wiklander        self.warn_assign_redun = True
975*c689edbbSJens Wiklander        self._warn_assign_no_prompt = True
976*c689edbbSJens Wiklander
977*c689edbbSJens Wiklander        self.warnings = []
978*c689edbbSJens Wiklander
979*c689edbbSJens Wiklander        self.config_prefix = os.getenv("CONFIG_", "CONFIG_")
980*c689edbbSJens Wiklander        # Regular expressions for parsing .config files
981*c689edbbSJens Wiklander        self._set_match = _re_match(self.config_prefix + r"([^=]+)=(.*)")
982*c689edbbSJens Wiklander        self._unset_match = _re_match(r"# {}([^ ]+) is not set".format(
983*c689edbbSJens Wiklander            self.config_prefix))
984*c689edbbSJens Wiklander
985*c689edbbSJens Wiklander        self.config_header = os.getenv("KCONFIG_CONFIG_HEADER", "")
986*c689edbbSJens Wiklander        self.header_header = os.getenv("KCONFIG_AUTOHEADER_HEADER", "")
987*c689edbbSJens Wiklander
988*c689edbbSJens Wiklander        self.syms = {}
989*c689edbbSJens Wiklander        self.const_syms = {}
990*c689edbbSJens Wiklander        self.defined_syms = []
991*c689edbbSJens Wiklander        self.missing_syms = []
992*c689edbbSJens Wiklander        self.named_choices = {}
993*c689edbbSJens Wiklander        self.choices = []
994*c689edbbSJens Wiklander        self.menus = []
995*c689edbbSJens Wiklander        self.comments = []
996*c689edbbSJens Wiklander
997*c689edbbSJens Wiklander        for nmy in "n", "m", "y":
998*c689edbbSJens Wiklander            sym = Symbol()
999*c689edbbSJens Wiklander            sym.kconfig = self
1000*c689edbbSJens Wiklander            sym.name = nmy
1001*c689edbbSJens Wiklander            sym.is_constant = True
1002*c689edbbSJens Wiklander            sym.orig_type = TRISTATE
1003*c689edbbSJens Wiklander            sym._cached_tri_val = STR_TO_TRI[nmy]
1004*c689edbbSJens Wiklander
1005*c689edbbSJens Wiklander            self.const_syms[nmy] = sym
1006*c689edbbSJens Wiklander
1007*c689edbbSJens Wiklander        self.n = self.const_syms["n"]
1008*c689edbbSJens Wiklander        self.m = self.const_syms["m"]
1009*c689edbbSJens Wiklander        self.y = self.const_syms["y"]
1010*c689edbbSJens Wiklander
1011*c689edbbSJens Wiklander        # Make n/m/y well-formed symbols
1012*c689edbbSJens Wiklander        for nmy in "n", "m", "y":
1013*c689edbbSJens Wiklander            sym = self.const_syms[nmy]
1014*c689edbbSJens Wiklander            sym.rev_dep = sym.weak_rev_dep = sym.direct_dep = self.n
1015*c689edbbSJens Wiklander
1016*c689edbbSJens Wiklander        # Maps preprocessor variables names to Variable instances
1017*c689edbbSJens Wiklander        self.variables = {}
1018*c689edbbSJens Wiklander
1019*c689edbbSJens Wiklander        # Predefined preprocessor functions, with min/max number of arguments
1020*c689edbbSJens Wiklander        self._functions = {
1021*c689edbbSJens Wiklander            "info":       (_info_fn,       1, 1),
1022*c689edbbSJens Wiklander            "error-if":   (_error_if_fn,   2, 2),
1023*c689edbbSJens Wiklander            "filename":   (_filename_fn,   0, 0),
1024*c689edbbSJens Wiklander            "lineno":     (_lineno_fn,     0, 0),
1025*c689edbbSJens Wiklander            "shell":      (_shell_fn,      1, 1),
1026*c689edbbSJens Wiklander            "warning-if": (_warning_if_fn, 2, 2),
1027*c689edbbSJens Wiklander        }
1028*c689edbbSJens Wiklander
1029*c689edbbSJens Wiklander        # Add any user-defined preprocessor functions
1030*c689edbbSJens Wiklander        try:
1031*c689edbbSJens Wiklander            self._functions.update(
1032*c689edbbSJens Wiklander                importlib.import_module(
1033*c689edbbSJens Wiklander                    os.getenv("KCONFIG_FUNCTIONS", "kconfigfunctions")
1034*c689edbbSJens Wiklander                ).functions)
1035*c689edbbSJens Wiklander        except ImportError:
1036*c689edbbSJens Wiklander            pass
1037*c689edbbSJens Wiklander
1038*c689edbbSJens Wiklander        # This determines whether previously unseen symbols are registered.
1039*c689edbbSJens Wiklander        # They shouldn't be if we parse expressions after parsing, as part of
1040*c689edbbSJens Wiklander        # Kconfig.eval_string().
1041*c689edbbSJens Wiklander        self._parsing_kconfigs = True
1042*c689edbbSJens Wiklander
1043*c689edbbSJens Wiklander        self.modules = self._lookup_sym("MODULES")
1044*c689edbbSJens Wiklander        self.defconfig_list = None
1045*c689edbbSJens Wiklander
1046*c689edbbSJens Wiklander        self.top_node = MenuNode()
1047*c689edbbSJens Wiklander        self.top_node.kconfig = self
1048*c689edbbSJens Wiklander        self.top_node.item = MENU
1049*c689edbbSJens Wiklander        self.top_node.is_menuconfig = True
1050*c689edbbSJens Wiklander        self.top_node.visibility = self.y
1051*c689edbbSJens Wiklander        self.top_node.prompt = ("Main menu", self.y)
1052*c689edbbSJens Wiklander        self.top_node.parent = None
1053*c689edbbSJens Wiklander        self.top_node.dep = self.y
1054*c689edbbSJens Wiklander        self.top_node.filename = filename
1055*c689edbbSJens Wiklander        self.top_node.linenr = 1
1056*c689edbbSJens Wiklander        self.top_node.include_path = ()
1057*c689edbbSJens Wiklander
1058*c689edbbSJens Wiklander        # Parse the Kconfig files
1059*c689edbbSJens Wiklander
1060*c689edbbSJens Wiklander        # Not used internally. Provided as a convenience.
1061*c689edbbSJens Wiklander        self.kconfig_filenames = [filename]
1062*c689edbbSJens Wiklander        self.env_vars = set()
1063*c689edbbSJens Wiklander
1064*c689edbbSJens Wiklander        # Keeps track of the location in the parent Kconfig files. Kconfig
1065*c689edbbSJens Wiklander        # files usually source other Kconfig files. See _enter_file().
1066*c689edbbSJens Wiklander        self._filestack = []
1067*c689edbbSJens Wiklander        self._include_path = ()
1068*c689edbbSJens Wiklander
1069*c689edbbSJens Wiklander        # The current parsing location
1070*c689edbbSJens Wiklander        self.filename = filename
1071*c689edbbSJens Wiklander        self.linenr = 0
1072*c689edbbSJens Wiklander
1073*c689edbbSJens Wiklander        # Used to avoid retokenizing lines when we discover that they're not
1074*c689edbbSJens Wiklander        # part of the construct currently being parsed. This is kinda like an
1075*c689edbbSJens Wiklander        # unget operation.
1076*c689edbbSJens Wiklander        self._reuse_tokens = False
1077*c689edbbSJens Wiklander
1078*c689edbbSJens Wiklander        # Open the top-level Kconfig file. Store the readline() method directly
1079*c689edbbSJens Wiklander        # as a small optimization.
1080*c689edbbSJens Wiklander        self._readline = self._open(join(self.srctree, filename), "r").readline
1081*c689edbbSJens Wiklander
1082*c689edbbSJens Wiklander        try:
1083*c689edbbSJens Wiklander            # Parse the Kconfig files. Returns the last node, which we
1084*c689edbbSJens Wiklander            # terminate with '.next = None'.
1085*c689edbbSJens Wiklander            self._parse_block(None, self.top_node, self.top_node).next = None
1086*c689edbbSJens Wiklander            self.top_node.list = self.top_node.next
1087*c689edbbSJens Wiklander            self.top_node.next = None
1088*c689edbbSJens Wiklander        except UnicodeDecodeError as e:
1089*c689edbbSJens Wiklander            _decoding_error(e, self.filename)
1090*c689edbbSJens Wiklander
1091*c689edbbSJens Wiklander        # Close the top-level Kconfig file. __self__ fetches the 'file' object
1092*c689edbbSJens Wiklander        # for the method.
1093*c689edbbSJens Wiklander        self._readline.__self__.close()
1094*c689edbbSJens Wiklander
1095*c689edbbSJens Wiklander        self._parsing_kconfigs = False
1096*c689edbbSJens Wiklander
1097*c689edbbSJens Wiklander        # Do various menu tree post-processing
1098*c689edbbSJens Wiklander        self._finalize_node(self.top_node, self.y)
1099*c689edbbSJens Wiklander
1100*c689edbbSJens Wiklander        self.unique_defined_syms = _ordered_unique(self.defined_syms)
1101*c689edbbSJens Wiklander        self.unique_choices = _ordered_unique(self.choices)
1102*c689edbbSJens Wiklander
1103*c689edbbSJens Wiklander        # Do sanity checks. Some of these depend on everything being finalized.
1104*c689edbbSJens Wiklander        self._check_sym_sanity()
1105*c689edbbSJens Wiklander        self._check_choice_sanity()
1106*c689edbbSJens Wiklander
1107*c689edbbSJens Wiklander        # KCONFIG_STRICT is an older alias for KCONFIG_WARN_UNDEF, supported
1108*c689edbbSJens Wiklander        # for backwards compatibility
1109*c689edbbSJens Wiklander        if os.getenv("KCONFIG_WARN_UNDEF") == "y" or \
1110*c689edbbSJens Wiklander           os.getenv("KCONFIG_STRICT") == "y":
1111*c689edbbSJens Wiklander
1112*c689edbbSJens Wiklander            self._check_undef_syms()
1113*c689edbbSJens Wiklander
1114*c689edbbSJens Wiklander        # Build Symbol._dependents for all symbols and choices
1115*c689edbbSJens Wiklander        self._build_dep()
1116*c689edbbSJens Wiklander
1117*c689edbbSJens Wiklander        # Check for dependency loops
1118*c689edbbSJens Wiklander        check_dep_loop_sym = _check_dep_loop_sym  # Micro-optimization
1119*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
1120*c689edbbSJens Wiklander            check_dep_loop_sym(sym, False)
1121*c689edbbSJens Wiklander
1122*c689edbbSJens Wiklander        # Add extra dependencies from choices to choice symbols that get
1123*c689edbbSJens Wiklander        # awkward during dependency loop detection
1124*c689edbbSJens Wiklander        self._add_choice_deps()
1125*c689edbbSJens Wiklander
1126*c689edbbSJens Wiklander    @property
1127*c689edbbSJens Wiklander    def mainmenu_text(self):
1128*c689edbbSJens Wiklander        """
1129*c689edbbSJens Wiklander        See the class documentation.
1130*c689edbbSJens Wiklander        """
1131*c689edbbSJens Wiklander        return self.top_node.prompt[0]
1132*c689edbbSJens Wiklander
1133*c689edbbSJens Wiklander    @property
1134*c689edbbSJens Wiklander    def defconfig_filename(self):
1135*c689edbbSJens Wiklander        """
1136*c689edbbSJens Wiklander        See the class documentation.
1137*c689edbbSJens Wiklander        """
1138*c689edbbSJens Wiklander        if self.defconfig_list:
1139*c689edbbSJens Wiklander            for filename, cond in self.defconfig_list.defaults:
1140*c689edbbSJens Wiklander                if expr_value(cond):
1141*c689edbbSJens Wiklander                    try:
1142*c689edbbSJens Wiklander                        with self._open_config(filename.str_value) as f:
1143*c689edbbSJens Wiklander                            return f.name
1144*c689edbbSJens Wiklander                    except EnvironmentError:
1145*c689edbbSJens Wiklander                        continue
1146*c689edbbSJens Wiklander
1147*c689edbbSJens Wiklander        return None
1148*c689edbbSJens Wiklander
1149*c689edbbSJens Wiklander    def load_config(self, filename=None, replace=True, verbose=None):
1150*c689edbbSJens Wiklander        """
1151*c689edbbSJens Wiklander        Loads symbol values from a file in the .config format. Equivalent to
1152*c689edbbSJens Wiklander        calling Symbol.set_value() to set each of the values.
1153*c689edbbSJens Wiklander
1154*c689edbbSJens Wiklander        "# CONFIG_FOO is not set" within a .config file sets the user value of
1155*c689edbbSJens Wiklander        FOO to n. The C tools work the same way.
1156*c689edbbSJens Wiklander
1157*c689edbbSJens Wiklander        For each symbol, the Symbol.user_value attribute holds the value the
1158*c689edbbSJens Wiklander        symbol was assigned in the .config file (if any). The user value might
1159*c689edbbSJens Wiklander        differ from Symbol.str/tri_value if there are unsatisfied dependencies.
1160*c689edbbSJens Wiklander
1161*c689edbbSJens Wiklander        Calling this function also updates the Kconfig.missing_syms attribute
1162*c689edbbSJens Wiklander        with a list of all assignments to undefined symbols within the
1163*c689edbbSJens Wiklander        configuration file. Kconfig.missing_syms is cleared if 'replace' is
1164*c689edbbSJens Wiklander        True, and appended to otherwise. See the documentation for
1165*c689edbbSJens Wiklander        Kconfig.missing_syms as well.
1166*c689edbbSJens Wiklander
1167*c689edbbSJens Wiklander        See the Kconfig.__init__() docstring for raised exceptions
1168*c689edbbSJens Wiklander        (OSError/IOError). KconfigError is never raised here.
1169*c689edbbSJens Wiklander
1170*c689edbbSJens Wiklander        filename (default: None):
1171*c689edbbSJens Wiklander          Path to load configuration from (a string). Respects $srctree if set
1172*c689edbbSJens Wiklander          (see the class documentation).
1173*c689edbbSJens Wiklander
1174*c689edbbSJens Wiklander          If 'filename' is None (the default), the configuration file to load
1175*c689edbbSJens Wiklander          (if any) is calculated automatically, giving the behavior you'd
1176*c689edbbSJens Wiklander          usually want:
1177*c689edbbSJens Wiklander
1178*c689edbbSJens Wiklander            1. If the KCONFIG_CONFIG environment variable is set, it gives the
1179*c689edbbSJens Wiklander               path to the configuration file to load. Otherwise, ".config" is
1180*c689edbbSJens Wiklander               used. See standard_config_filename().
1181*c689edbbSJens Wiklander
1182*c689edbbSJens Wiklander            2. If the path from (1.) doesn't exist, the configuration file
1183*c689edbbSJens Wiklander               given by kconf.defconfig_filename is loaded instead, which is
1184*c689edbbSJens Wiklander               derived from the 'option defconfig_list' symbol.
1185*c689edbbSJens Wiklander
1186*c689edbbSJens Wiklander            3. If (1.) and (2.) fail to find a configuration file to load, no
1187*c689edbbSJens Wiklander               configuration file is loaded, and symbols retain their current
1188*c689edbbSJens Wiklander               values (e.g., their default values). This is not an error.
1189*c689edbbSJens Wiklander
1190*c689edbbSJens Wiklander           See the return value as well.
1191*c689edbbSJens Wiklander
1192*c689edbbSJens Wiklander        replace (default: True):
1193*c689edbbSJens Wiklander          If True, all existing user values will be cleared before loading the
1194*c689edbbSJens Wiklander          .config. Pass False to merge configurations.
1195*c689edbbSJens Wiklander
1196*c689edbbSJens Wiklander        verbose (default: None):
1197*c689edbbSJens Wiklander          Limited backwards compatibility to prevent crashes. A warning is
1198*c689edbbSJens Wiklander          printed if anything but None is passed.
1199*c689edbbSJens Wiklander
1200*c689edbbSJens Wiklander          Prior to Kconfiglib 12.0.0, this option enabled printing of messages
1201*c689edbbSJens Wiklander          to stdout when 'filename' was None. A message is (always) returned
1202*c689edbbSJens Wiklander          now instead, which is more flexible.
1203*c689edbbSJens Wiklander
1204*c689edbbSJens Wiklander          Will probably be removed in some future version.
1205*c689edbbSJens Wiklander
1206*c689edbbSJens Wiklander        Returns a string with a message saying which file got loaded (or
1207*c689edbbSJens Wiklander        possibly that no file got loaded, when 'filename' is None). This is
1208*c689edbbSJens Wiklander        meant to reduce boilerplate in tools, which can do e.g.
1209*c689edbbSJens Wiklander        print(kconf.load_config()). The returned message distinguishes between
1210*c689edbbSJens Wiklander        loading (replace == True) and merging (replace == False).
1211*c689edbbSJens Wiklander        """
1212*c689edbbSJens Wiklander        if verbose is not None:
1213*c689edbbSJens Wiklander            _warn_verbose_deprecated("load_config")
1214*c689edbbSJens Wiklander
1215*c689edbbSJens Wiklander        msg = None
1216*c689edbbSJens Wiklander        if filename is None:
1217*c689edbbSJens Wiklander            filename = standard_config_filename()
1218*c689edbbSJens Wiklander            if not exists(filename) and \
1219*c689edbbSJens Wiklander               not exists(join(self.srctree, filename)):
1220*c689edbbSJens Wiklander                defconfig = self.defconfig_filename
1221*c689edbbSJens Wiklander                if defconfig is None:
1222*c689edbbSJens Wiklander                    return "Using default symbol values (no '{}')" \
1223*c689edbbSJens Wiklander                           .format(filename)
1224*c689edbbSJens Wiklander
1225*c689edbbSJens Wiklander                msg = " default configuration '{}' (no '{}')" \
1226*c689edbbSJens Wiklander                      .format(defconfig, filename)
1227*c689edbbSJens Wiklander                filename = defconfig
1228*c689edbbSJens Wiklander
1229*c689edbbSJens Wiklander        if not msg:
1230*c689edbbSJens Wiklander            msg = " configuration '{}'".format(filename)
1231*c689edbbSJens Wiklander
1232*c689edbbSJens Wiklander        # Disable the warning about assigning to symbols without prompts. This
1233*c689edbbSJens Wiklander        # is normal and expected within a .config file.
1234*c689edbbSJens Wiklander        self._warn_assign_no_prompt = False
1235*c689edbbSJens Wiklander
1236*c689edbbSJens Wiklander        # This stub only exists to make sure _warn_assign_no_prompt gets
1237*c689edbbSJens Wiklander        # reenabled
1238*c689edbbSJens Wiklander        try:
1239*c689edbbSJens Wiklander            self._load_config(filename, replace)
1240*c689edbbSJens Wiklander        except UnicodeDecodeError as e:
1241*c689edbbSJens Wiklander            _decoding_error(e, filename)
1242*c689edbbSJens Wiklander        finally:
1243*c689edbbSJens Wiklander            self._warn_assign_no_prompt = True
1244*c689edbbSJens Wiklander
1245*c689edbbSJens Wiklander        return ("Loaded" if replace else "Merged") + msg
1246*c689edbbSJens Wiklander
1247*c689edbbSJens Wiklander    def _load_config(self, filename, replace):
1248*c689edbbSJens Wiklander        with self._open_config(filename) as f:
1249*c689edbbSJens Wiklander            if replace:
1250*c689edbbSJens Wiklander                self.missing_syms = []
1251*c689edbbSJens Wiklander
1252*c689edbbSJens Wiklander                # If we're replacing the configuration, keep track of which
1253*c689edbbSJens Wiklander                # symbols and choices got set so that we can unset the rest
1254*c689edbbSJens Wiklander                # later. This avoids invalidating everything and is faster.
1255*c689edbbSJens Wiklander                # Another benefit is that invalidation must be rock solid for
1256*c689edbbSJens Wiklander                # it to work, making it a good test.
1257*c689edbbSJens Wiklander
1258*c689edbbSJens Wiklander                for sym in self.unique_defined_syms:
1259*c689edbbSJens Wiklander                    sym._was_set = False
1260*c689edbbSJens Wiklander
1261*c689edbbSJens Wiklander                for choice in self.unique_choices:
1262*c689edbbSJens Wiklander                    choice._was_set = False
1263*c689edbbSJens Wiklander
1264*c689edbbSJens Wiklander            # Small optimizations
1265*c689edbbSJens Wiklander            set_match = self._set_match
1266*c689edbbSJens Wiklander            unset_match = self._unset_match
1267*c689edbbSJens Wiklander            get_sym = self.syms.get
1268*c689edbbSJens Wiklander
1269*c689edbbSJens Wiklander            for linenr, line in enumerate(f, 1):
1270*c689edbbSJens Wiklander                # The C tools ignore trailing whitespace
1271*c689edbbSJens Wiklander                line = line.rstrip()
1272*c689edbbSJens Wiklander
1273*c689edbbSJens Wiklander                match = set_match(line)
1274*c689edbbSJens Wiklander                if match:
1275*c689edbbSJens Wiklander                    name, val = match.groups()
1276*c689edbbSJens Wiklander                    sym = get_sym(name)
1277*c689edbbSJens Wiklander                    if not sym or not sym.nodes:
1278*c689edbbSJens Wiklander                        self._undef_assign(name, val, filename, linenr)
1279*c689edbbSJens Wiklander                        continue
1280*c689edbbSJens Wiklander
1281*c689edbbSJens Wiklander                    if sym.orig_type in _BOOL_TRISTATE:
1282*c689edbbSJens Wiklander                        # The C implementation only checks the first character
1283*c689edbbSJens Wiklander                        # to the right of '=', for whatever reason
1284*c689edbbSJens Wiklander                        if not (sym.orig_type is BOOL
1285*c689edbbSJens Wiklander                                and val.startswith(("y", "n")) or
1286*c689edbbSJens Wiklander                                sym.orig_type is TRISTATE
1287*c689edbbSJens Wiklander                                and val.startswith(("y", "m", "n"))):
1288*c689edbbSJens Wiklander                            self._warn("'{}' is not a valid value for the {} "
1289*c689edbbSJens Wiklander                                       "symbol {}. Assignment ignored."
1290*c689edbbSJens Wiklander                                       .format(val, TYPE_TO_STR[sym.orig_type],
1291*c689edbbSJens Wiklander                                               sym.name_and_loc),
1292*c689edbbSJens Wiklander                                       filename, linenr)
1293*c689edbbSJens Wiklander                            continue
1294*c689edbbSJens Wiklander
1295*c689edbbSJens Wiklander                        val = val[0]
1296*c689edbbSJens Wiklander
1297*c689edbbSJens Wiklander                        if sym.choice and val != "n":
1298*c689edbbSJens Wiklander                            # During .config loading, we infer the mode of the
1299*c689edbbSJens Wiklander                            # choice from the kind of values that are assigned
1300*c689edbbSJens Wiklander                            # to the choice symbols
1301*c689edbbSJens Wiklander
1302*c689edbbSJens Wiklander                            prev_mode = sym.choice.user_value
1303*c689edbbSJens Wiklander                            if prev_mode is not None and \
1304*c689edbbSJens Wiklander                               TRI_TO_STR[prev_mode] != val:
1305*c689edbbSJens Wiklander
1306*c689edbbSJens Wiklander                                self._warn("both m and y assigned to symbols "
1307*c689edbbSJens Wiklander                                           "within the same choice",
1308*c689edbbSJens Wiklander                                           filename, linenr)
1309*c689edbbSJens Wiklander
1310*c689edbbSJens Wiklander                            # Set the choice's mode
1311*c689edbbSJens Wiklander                            sym.choice.set_value(val)
1312*c689edbbSJens Wiklander
1313*c689edbbSJens Wiklander                    elif sym.orig_type is STRING:
1314*c689edbbSJens Wiklander                        match = _conf_string_match(val)
1315*c689edbbSJens Wiklander                        if not match:
1316*c689edbbSJens Wiklander                            self._warn("malformed string literal in "
1317*c689edbbSJens Wiklander                                       "assignment to {}. Assignment ignored."
1318*c689edbbSJens Wiklander                                       .format(sym.name_and_loc),
1319*c689edbbSJens Wiklander                                       filename, linenr)
1320*c689edbbSJens Wiklander                            continue
1321*c689edbbSJens Wiklander
1322*c689edbbSJens Wiklander                        val = unescape(match.group(1))
1323*c689edbbSJens Wiklander
1324*c689edbbSJens Wiklander                else:
1325*c689edbbSJens Wiklander                    match = unset_match(line)
1326*c689edbbSJens Wiklander                    if not match:
1327*c689edbbSJens Wiklander                        # Print a warning for lines that match neither
1328*c689edbbSJens Wiklander                        # set_match() nor unset_match() and that are not blank
1329*c689edbbSJens Wiklander                        # lines or comments. 'line' has already been
1330*c689edbbSJens Wiklander                        # rstrip()'d, so blank lines show up as "" here.
1331*c689edbbSJens Wiklander                        if line and not line.lstrip().startswith("#"):
1332*c689edbbSJens Wiklander                            self._warn("ignoring malformed line '{}'"
1333*c689edbbSJens Wiklander                                       .format(line),
1334*c689edbbSJens Wiklander                                       filename, linenr)
1335*c689edbbSJens Wiklander
1336*c689edbbSJens Wiklander                        continue
1337*c689edbbSJens Wiklander
1338*c689edbbSJens Wiklander                    name = match.group(1)
1339*c689edbbSJens Wiklander                    sym = get_sym(name)
1340*c689edbbSJens Wiklander                    if not sym or not sym.nodes:
1341*c689edbbSJens Wiklander                        self._undef_assign(name, "n", filename, linenr)
1342*c689edbbSJens Wiklander                        continue
1343*c689edbbSJens Wiklander
1344*c689edbbSJens Wiklander                    if sym.orig_type not in _BOOL_TRISTATE:
1345*c689edbbSJens Wiklander                        continue
1346*c689edbbSJens Wiklander
1347*c689edbbSJens Wiklander                    val = "n"
1348*c689edbbSJens Wiklander
1349*c689edbbSJens Wiklander                # Done parsing the assignment. Set the value.
1350*c689edbbSJens Wiklander
1351*c689edbbSJens Wiklander                if sym._was_set:
1352*c689edbbSJens Wiklander                    self._assigned_twice(sym, val, filename, linenr)
1353*c689edbbSJens Wiklander
1354*c689edbbSJens Wiklander                sym.set_value(val)
1355*c689edbbSJens Wiklander
1356*c689edbbSJens Wiklander        if replace:
1357*c689edbbSJens Wiklander            # If we're replacing the configuration, unset the symbols that
1358*c689edbbSJens Wiklander            # didn't get set
1359*c689edbbSJens Wiklander
1360*c689edbbSJens Wiklander            for sym in self.unique_defined_syms:
1361*c689edbbSJens Wiklander                if not sym._was_set:
1362*c689edbbSJens Wiklander                    sym.unset_value()
1363*c689edbbSJens Wiklander
1364*c689edbbSJens Wiklander            for choice in self.unique_choices:
1365*c689edbbSJens Wiklander                if not choice._was_set:
1366*c689edbbSJens Wiklander                    choice.unset_value()
1367*c689edbbSJens Wiklander
1368*c689edbbSJens Wiklander    def _undef_assign(self, name, val, filename, linenr):
1369*c689edbbSJens Wiklander        # Called for assignments to undefined symbols during .config loading
1370*c689edbbSJens Wiklander
1371*c689edbbSJens Wiklander        self.missing_syms.append((name, val))
1372*c689edbbSJens Wiklander        if self.warn_assign_undef:
1373*c689edbbSJens Wiklander            self._warn(
1374*c689edbbSJens Wiklander                "attempt to assign the value '{}' to the undefined symbol {}"
1375*c689edbbSJens Wiklander                .format(val, name), filename, linenr)
1376*c689edbbSJens Wiklander
1377*c689edbbSJens Wiklander    def _assigned_twice(self, sym, new_val, filename, linenr):
1378*c689edbbSJens Wiklander        # Called when a symbol is assigned more than once in a .config file
1379*c689edbbSJens Wiklander
1380*c689edbbSJens Wiklander        # Use strings for bool/tristate user values in the warning
1381*c689edbbSJens Wiklander        if sym.orig_type in _BOOL_TRISTATE:
1382*c689edbbSJens Wiklander            user_val = TRI_TO_STR[sym.user_value]
1383*c689edbbSJens Wiklander        else:
1384*c689edbbSJens Wiklander            user_val = sym.user_value
1385*c689edbbSJens Wiklander
1386*c689edbbSJens Wiklander        msg = '{} set more than once. Old value "{}", new value "{}".'.format(
1387*c689edbbSJens Wiklander            sym.name_and_loc, user_val, new_val)
1388*c689edbbSJens Wiklander
1389*c689edbbSJens Wiklander        if user_val == new_val:
1390*c689edbbSJens Wiklander            if self.warn_assign_redun:
1391*c689edbbSJens Wiklander                self._warn(msg, filename, linenr)
1392*c689edbbSJens Wiklander        elif self.warn_assign_override:
1393*c689edbbSJens Wiklander            self._warn(msg, filename, linenr)
1394*c689edbbSJens Wiklander
1395*c689edbbSJens Wiklander    def load_allconfig(self, filename):
1396*c689edbbSJens Wiklander        """
1397*c689edbbSJens Wiklander        Helper for all*config. Loads (merges) the configuration file specified
1398*c689edbbSJens Wiklander        by KCONFIG_ALLCONFIG, if any. See Documentation/kbuild/kconfig.txt in
1399*c689edbbSJens Wiklander        the Linux kernel.
1400*c689edbbSJens Wiklander
1401*c689edbbSJens Wiklander        Disables warnings for duplicated assignments within configuration files
1402*c689edbbSJens Wiklander        for the duration of the call
1403*c689edbbSJens Wiklander        (kconf.warn_assign_override/warn_assign_redun = False), and restores
1404*c689edbbSJens Wiklander        the previous warning settings at the end. The KCONFIG_ALLCONFIG
1405*c689edbbSJens Wiklander        configuration file is expected to override symbols.
1406*c689edbbSJens Wiklander
1407*c689edbbSJens Wiklander        Exits with sys.exit() (which raises a SystemExit exception) and prints
1408*c689edbbSJens Wiklander        an error to stderr if KCONFIG_ALLCONFIG is set but the configuration
1409*c689edbbSJens Wiklander        file can't be opened.
1410*c689edbbSJens Wiklander
1411*c689edbbSJens Wiklander        filename:
1412*c689edbbSJens Wiklander          Command-specific configuration filename - "allyes.config",
1413*c689edbbSJens Wiklander          "allno.config", etc.
1414*c689edbbSJens Wiklander        """
1415*c689edbbSJens Wiklander        load_allconfig(self, filename)
1416*c689edbbSJens Wiklander
1417*c689edbbSJens Wiklander    def write_autoconf(self, filename=None, header=None):
1418*c689edbbSJens Wiklander        r"""
1419*c689edbbSJens Wiklander        Writes out symbol values as a C header file, matching the format used
1420*c689edbbSJens Wiklander        by include/generated/autoconf.h in the kernel.
1421*c689edbbSJens Wiklander
1422*c689edbbSJens Wiklander        The ordering of the #defines matches the one generated by
1423*c689edbbSJens Wiklander        write_config(). The order in the C implementation depends on the hash
1424*c689edbbSJens Wiklander        table implementation as of writing, and so won't match.
1425*c689edbbSJens Wiklander
1426*c689edbbSJens Wiklander        If 'filename' exists and its contents is identical to what would get
1427*c689edbbSJens Wiklander        written out, it is left untouched. This avoids updating file metadata
1428*c689edbbSJens Wiklander        like the modification time and possibly triggering redundant work in
1429*c689edbbSJens Wiklander        build tools.
1430*c689edbbSJens Wiklander
1431*c689edbbSJens Wiklander        filename (default: None):
1432*c689edbbSJens Wiklander          Path to write header to.
1433*c689edbbSJens Wiklander
1434*c689edbbSJens Wiklander          If None (the default), the path in the environment variable
1435*c689edbbSJens Wiklander          KCONFIG_AUTOHEADER is used if set, and "include/generated/autoconf.h"
1436*c689edbbSJens Wiklander          otherwise. This is compatible with the C tools.
1437*c689edbbSJens Wiklander
1438*c689edbbSJens Wiklander        header (default: None):
1439*c689edbbSJens Wiklander          Text inserted verbatim at the beginning of the file. You would
1440*c689edbbSJens Wiklander          usually want it enclosed in '/* */' to make it a C comment, and
1441*c689edbbSJens Wiklander          include a trailing newline.
1442*c689edbbSJens Wiklander
1443*c689edbbSJens Wiklander          If None (the default), the value of the environment variable
1444*c689edbbSJens Wiklander          KCONFIG_AUTOHEADER_HEADER had when the Kconfig instance was created
1445*c689edbbSJens Wiklander          will be used if it was set, and no header otherwise. See the
1446*c689edbbSJens Wiklander          Kconfig.header_header attribute.
1447*c689edbbSJens Wiklander
1448*c689edbbSJens Wiklander        Returns a string with a message saying that the header got saved, or
1449*c689edbbSJens Wiklander        that there were no changes to it. This is meant to reduce boilerplate
1450*c689edbbSJens Wiklander        in tools, which can do e.g. print(kconf.write_autoconf()).
1451*c689edbbSJens Wiklander        """
1452*c689edbbSJens Wiklander        if filename is None:
1453*c689edbbSJens Wiklander            filename = os.getenv("KCONFIG_AUTOHEADER",
1454*c689edbbSJens Wiklander                                 "include/generated/autoconf.h")
1455*c689edbbSJens Wiklander
1456*c689edbbSJens Wiklander        if self._write_if_changed(filename, self._autoconf_contents(header)):
1457*c689edbbSJens Wiklander            return "Kconfig header saved to '{}'".format(filename)
1458*c689edbbSJens Wiklander        return "No change to Kconfig header in '{}'".format(filename)
1459*c689edbbSJens Wiklander
1460*c689edbbSJens Wiklander    def _autoconf_contents(self, header):
1461*c689edbbSJens Wiklander        # write_autoconf() helper. Returns the contents to write as a string,
1462*c689edbbSJens Wiklander        # with 'header' or KCONFIG_AUTOHEADER_HEADER at the beginning.
1463*c689edbbSJens Wiklander
1464*c689edbbSJens Wiklander        if header is None:
1465*c689edbbSJens Wiklander            header = self.header_header
1466*c689edbbSJens Wiklander
1467*c689edbbSJens Wiklander        chunks = [header]  # "".join()ed later
1468*c689edbbSJens Wiklander        add = chunks.append
1469*c689edbbSJens Wiklander
1470*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
1471*c689edbbSJens Wiklander            # _write_to_conf is determined when the value is calculated. This
1472*c689edbbSJens Wiklander            # is a hidden function call due to property magic.
1473*c689edbbSJens Wiklander            #
1474*c689edbbSJens Wiklander            # Note: In client code, you can check if sym.config_string is empty
1475*c689edbbSJens Wiklander            # instead, to avoid accessing the internal _write_to_conf variable
1476*c689edbbSJens Wiklander            # (though it's likely to keep working).
1477*c689edbbSJens Wiklander            val = sym.str_value
1478*c689edbbSJens Wiklander            if not sym._write_to_conf:
1479*c689edbbSJens Wiklander                continue
1480*c689edbbSJens Wiklander
1481*c689edbbSJens Wiklander            if sym.orig_type in _BOOL_TRISTATE:
1482*c689edbbSJens Wiklander                if val == "y":
1483*c689edbbSJens Wiklander                    add("#define {}{} 1\n"
1484*c689edbbSJens Wiklander                        .format(self.config_prefix, sym.name))
1485*c689edbbSJens Wiklander                elif val == "m":
1486*c689edbbSJens Wiklander                    add("#define {}{}_MODULE 1\n"
1487*c689edbbSJens Wiklander                        .format(self.config_prefix, sym.name))
1488*c689edbbSJens Wiklander
1489*c689edbbSJens Wiklander            elif sym.orig_type is STRING:
1490*c689edbbSJens Wiklander                add('#define {}{} "{}"\n'
1491*c689edbbSJens Wiklander                    .format(self.config_prefix, sym.name, escape(val)))
1492*c689edbbSJens Wiklander
1493*c689edbbSJens Wiklander            else:  # sym.orig_type in _INT_HEX:
1494*c689edbbSJens Wiklander                if sym.orig_type is HEX and \
1495*c689edbbSJens Wiklander                   not val.startswith(("0x", "0X")):
1496*c689edbbSJens Wiklander                    val = "0x" + val
1497*c689edbbSJens Wiklander
1498*c689edbbSJens Wiklander                add("#define {}{} {}\n"
1499*c689edbbSJens Wiklander                    .format(self.config_prefix, sym.name, val))
1500*c689edbbSJens Wiklander
1501*c689edbbSJens Wiklander        return "".join(chunks)
1502*c689edbbSJens Wiklander
1503*c689edbbSJens Wiklander    def write_config(self, filename=None, header=None, save_old=True,
1504*c689edbbSJens Wiklander                     verbose=None):
1505*c689edbbSJens Wiklander        r"""
1506*c689edbbSJens Wiklander        Writes out symbol values in the .config format. The format matches the
1507*c689edbbSJens Wiklander        C implementation, including ordering.
1508*c689edbbSJens Wiklander
1509*c689edbbSJens Wiklander        Symbols appear in the same order in generated .config files as they do
1510*c689edbbSJens Wiklander        in the Kconfig files. For symbols defined in multiple locations, a
1511*c689edbbSJens Wiklander        single assignment is written out corresponding to the first location
1512*c689edbbSJens Wiklander        where the symbol is defined.
1513*c689edbbSJens Wiklander
1514*c689edbbSJens Wiklander        See the 'Intro to symbol values' section in the module docstring to
1515*c689edbbSJens Wiklander        understand which symbols get written out.
1516*c689edbbSJens Wiklander
1517*c689edbbSJens Wiklander        If 'filename' exists and its contents is identical to what would get
1518*c689edbbSJens Wiklander        written out, it is left untouched. This avoids updating file metadata
1519*c689edbbSJens Wiklander        like the modification time and possibly triggering redundant work in
1520*c689edbbSJens Wiklander        build tools.
1521*c689edbbSJens Wiklander
1522*c689edbbSJens Wiklander        See the Kconfig.__init__() docstring for raised exceptions
1523*c689edbbSJens Wiklander        (OSError/IOError). KconfigError is never raised here.
1524*c689edbbSJens Wiklander
1525*c689edbbSJens Wiklander        filename (default: None):
1526*c689edbbSJens Wiklander          Path to write configuration to (a string).
1527*c689edbbSJens Wiklander
1528*c689edbbSJens Wiklander          If None (the default), the path in the environment variable
1529*c689edbbSJens Wiklander          KCONFIG_CONFIG is used if set, and ".config" otherwise. See
1530*c689edbbSJens Wiklander          standard_config_filename().
1531*c689edbbSJens Wiklander
1532*c689edbbSJens Wiklander        header (default: None):
1533*c689edbbSJens Wiklander          Text inserted verbatim at the beginning of the file. You would
1534*c689edbbSJens Wiklander          usually want each line to start with '#' to make it a comment, and
1535*c689edbbSJens Wiklander          include a trailing newline.
1536*c689edbbSJens Wiklander
1537*c689edbbSJens Wiklander          if None (the default), the value of the environment variable
1538*c689edbbSJens Wiklander          KCONFIG_CONFIG_HEADER had when the Kconfig instance was created will
1539*c689edbbSJens Wiklander          be used if it was set, and no header otherwise. See the
1540*c689edbbSJens Wiklander          Kconfig.config_header attribute.
1541*c689edbbSJens Wiklander
1542*c689edbbSJens Wiklander        save_old (default: True):
1543*c689edbbSJens Wiklander          If True and <filename> already exists, a copy of it will be saved to
1544*c689edbbSJens Wiklander          <filename>.old in the same directory before the new configuration is
1545*c689edbbSJens Wiklander          written.
1546*c689edbbSJens Wiklander
1547*c689edbbSJens Wiklander          Errors are silently ignored if <filename>.old cannot be written (e.g.
1548*c689edbbSJens Wiklander          due to being a directory, or <filename> being something like
1549*c689edbbSJens Wiklander          /dev/null).
1550*c689edbbSJens Wiklander
1551*c689edbbSJens Wiklander        verbose (default: None):
1552*c689edbbSJens Wiklander          Limited backwards compatibility to prevent crashes. A warning is
1553*c689edbbSJens Wiklander          printed if anything but None is passed.
1554*c689edbbSJens Wiklander
1555*c689edbbSJens Wiklander          Prior to Kconfiglib 12.0.0, this option enabled printing of messages
1556*c689edbbSJens Wiklander          to stdout when 'filename' was None. A message is (always) returned
1557*c689edbbSJens Wiklander          now instead, which is more flexible.
1558*c689edbbSJens Wiklander
1559*c689edbbSJens Wiklander          Will probably be removed in some future version.
1560*c689edbbSJens Wiklander
1561*c689edbbSJens Wiklander        Returns a string with a message saying which file got saved. This is
1562*c689edbbSJens Wiklander        meant to reduce boilerplate in tools, which can do e.g.
1563*c689edbbSJens Wiklander        print(kconf.write_config()).
1564*c689edbbSJens Wiklander        """
1565*c689edbbSJens Wiklander        if verbose is not None:
1566*c689edbbSJens Wiklander            _warn_verbose_deprecated("write_config")
1567*c689edbbSJens Wiklander
1568*c689edbbSJens Wiklander        if filename is None:
1569*c689edbbSJens Wiklander            filename = standard_config_filename()
1570*c689edbbSJens Wiklander
1571*c689edbbSJens Wiklander        contents = self._config_contents(header)
1572*c689edbbSJens Wiklander        if self._contents_eq(filename, contents):
1573*c689edbbSJens Wiklander            return "No change to configuration in '{}'".format(filename)
1574*c689edbbSJens Wiklander
1575*c689edbbSJens Wiklander        if save_old:
1576*c689edbbSJens Wiklander            _save_old(filename)
1577*c689edbbSJens Wiklander
1578*c689edbbSJens Wiklander        with self._open(filename, "w") as f:
1579*c689edbbSJens Wiklander            f.write(contents)
1580*c689edbbSJens Wiklander
1581*c689edbbSJens Wiklander        return "Configuration saved to '{}'".format(filename)
1582*c689edbbSJens Wiklander
1583*c689edbbSJens Wiklander    def _config_contents(self, header):
1584*c689edbbSJens Wiklander        # write_config() helper. Returns the contents to write as a string,
1585*c689edbbSJens Wiklander        # with 'header' or KCONFIG_CONFIG_HEADER at the beginning.
1586*c689edbbSJens Wiklander        #
1587*c689edbbSJens Wiklander        # More memory friendly would be to 'yield' the strings and
1588*c689edbbSJens Wiklander        # "".join(_config_contents()), but it was a bit slower on my system.
1589*c689edbbSJens Wiklander
1590*c689edbbSJens Wiklander        # node_iter() was used here before commit 3aea9f7 ("Add '# end of
1591*c689edbbSJens Wiklander        # <menu>' after menus in .config"). Those comments get tricky to
1592*c689edbbSJens Wiklander        # implement with it.
1593*c689edbbSJens Wiklander
1594*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
1595*c689edbbSJens Wiklander            sym._visited = False
1596*c689edbbSJens Wiklander
1597*c689edbbSJens Wiklander        if header is None:
1598*c689edbbSJens Wiklander            header = self.config_header
1599*c689edbbSJens Wiklander
1600*c689edbbSJens Wiklander        chunks = [header]  # "".join()ed later
1601*c689edbbSJens Wiklander        add = chunks.append
1602*c689edbbSJens Wiklander
1603*c689edbbSJens Wiklander        # Did we just print an '# end of ...' comment?
1604*c689edbbSJens Wiklander        after_end_comment = False
1605*c689edbbSJens Wiklander
1606*c689edbbSJens Wiklander        node = self.top_node
1607*c689edbbSJens Wiklander        while 1:
1608*c689edbbSJens Wiklander            # Jump to the next node with an iterative tree walk
1609*c689edbbSJens Wiklander            if node.list:
1610*c689edbbSJens Wiklander                node = node.list
1611*c689edbbSJens Wiklander            elif node.next:
1612*c689edbbSJens Wiklander                node = node.next
1613*c689edbbSJens Wiklander            else:
1614*c689edbbSJens Wiklander                while node.parent:
1615*c689edbbSJens Wiklander                    node = node.parent
1616*c689edbbSJens Wiklander
1617*c689edbbSJens Wiklander                    # Add a comment when leaving visible menus
1618*c689edbbSJens Wiklander                    if node.item is MENU and expr_value(node.dep) and \
1619*c689edbbSJens Wiklander                       expr_value(node.visibility) and \
1620*c689edbbSJens Wiklander                       node is not self.top_node:
1621*c689edbbSJens Wiklander                        add("# end of {}\n".format(node.prompt[0]))
1622*c689edbbSJens Wiklander                        after_end_comment = True
1623*c689edbbSJens Wiklander
1624*c689edbbSJens Wiklander                    if node.next:
1625*c689edbbSJens Wiklander                        node = node.next
1626*c689edbbSJens Wiklander                        break
1627*c689edbbSJens Wiklander                else:
1628*c689edbbSJens Wiklander                    # No more nodes
1629*c689edbbSJens Wiklander                    return "".join(chunks)
1630*c689edbbSJens Wiklander
1631*c689edbbSJens Wiklander            # Generate configuration output for the node
1632*c689edbbSJens Wiklander
1633*c689edbbSJens Wiklander            item = node.item
1634*c689edbbSJens Wiklander
1635*c689edbbSJens Wiklander            if item.__class__ is Symbol:
1636*c689edbbSJens Wiklander                if item._visited:
1637*c689edbbSJens Wiklander                    continue
1638*c689edbbSJens Wiklander                item._visited = True
1639*c689edbbSJens Wiklander
1640*c689edbbSJens Wiklander                conf_string = item.config_string
1641*c689edbbSJens Wiklander                if not conf_string:
1642*c689edbbSJens Wiklander                    continue
1643*c689edbbSJens Wiklander
1644*c689edbbSJens Wiklander                if after_end_comment:
1645*c689edbbSJens Wiklander                    # Add a blank line before the first symbol printed after an
1646*c689edbbSJens Wiklander                    # '# end of ...' comment
1647*c689edbbSJens Wiklander                    after_end_comment = False
1648*c689edbbSJens Wiklander                    add("\n")
1649*c689edbbSJens Wiklander                add(conf_string)
1650*c689edbbSJens Wiklander
1651*c689edbbSJens Wiklander            elif expr_value(node.dep) and \
1652*c689edbbSJens Wiklander                 ((item is MENU and expr_value(node.visibility)) or
1653*c689edbbSJens Wiklander                  item is COMMENT):
1654*c689edbbSJens Wiklander
1655*c689edbbSJens Wiklander                add("\n#\n# {}\n#\n".format(node.prompt[0]))
1656*c689edbbSJens Wiklander                after_end_comment = False
1657*c689edbbSJens Wiklander
1658*c689edbbSJens Wiklander    def write_min_config(self, filename, header=None):
1659*c689edbbSJens Wiklander        """
1660*c689edbbSJens Wiklander        Writes out a "minimal" configuration file, omitting symbols whose value
1661*c689edbbSJens Wiklander        matches their default value. The format matches the one produced by
1662*c689edbbSJens Wiklander        'make savedefconfig'.
1663*c689edbbSJens Wiklander
1664*c689edbbSJens Wiklander        The resulting configuration file is incomplete, but a complete
1665*c689edbbSJens Wiklander        configuration can be derived from it by loading it. Minimal
1666*c689edbbSJens Wiklander        configuration files can serve as a more manageable configuration format
1667*c689edbbSJens Wiklander        compared to a "full" .config file, especially when configurations files
1668*c689edbbSJens Wiklander        are merged or edited by hand.
1669*c689edbbSJens Wiklander
1670*c689edbbSJens Wiklander        See the Kconfig.__init__() docstring for raised exceptions
1671*c689edbbSJens Wiklander        (OSError/IOError). KconfigError is never raised here.
1672*c689edbbSJens Wiklander
1673*c689edbbSJens Wiklander        filename:
1674*c689edbbSJens Wiklander          Path to write minimal configuration to.
1675*c689edbbSJens Wiklander
1676*c689edbbSJens Wiklander        header (default: None):
1677*c689edbbSJens Wiklander          Text inserted verbatim at the beginning of the file. You would
1678*c689edbbSJens Wiklander          usually want each line to start with '#' to make it a comment, and
1679*c689edbbSJens Wiklander          include a final terminating newline.
1680*c689edbbSJens Wiklander
1681*c689edbbSJens Wiklander          if None (the default), the value of the environment variable
1682*c689edbbSJens Wiklander          KCONFIG_CONFIG_HEADER had when the Kconfig instance was created will
1683*c689edbbSJens Wiklander          be used if it was set, and no header otherwise. See the
1684*c689edbbSJens Wiklander          Kconfig.config_header attribute.
1685*c689edbbSJens Wiklander
1686*c689edbbSJens Wiklander        Returns a string with a message saying the minimal configuration got
1687*c689edbbSJens Wiklander        saved, or that there were no changes to it. This is meant to reduce
1688*c689edbbSJens Wiklander        boilerplate in tools, which can do e.g.
1689*c689edbbSJens Wiklander        print(kconf.write_min_config()).
1690*c689edbbSJens Wiklander        """
1691*c689edbbSJens Wiklander        if self._write_if_changed(filename, self._min_config_contents(header)):
1692*c689edbbSJens Wiklander            return "Minimal configuration saved to '{}'".format(filename)
1693*c689edbbSJens Wiklander        return "No change to minimal configuration in '{}'".format(filename)
1694*c689edbbSJens Wiklander
1695*c689edbbSJens Wiklander    def _min_config_contents(self, header):
1696*c689edbbSJens Wiklander        # write_min_config() helper. Returns the contents to write as a string,
1697*c689edbbSJens Wiklander        # with 'header' or KCONFIG_CONFIG_HEADER at the beginning.
1698*c689edbbSJens Wiklander
1699*c689edbbSJens Wiklander        if header is None:
1700*c689edbbSJens Wiklander            header = self.config_header
1701*c689edbbSJens Wiklander
1702*c689edbbSJens Wiklander        chunks = [header]  # "".join()ed later
1703*c689edbbSJens Wiklander        add = chunks.append
1704*c689edbbSJens Wiklander
1705*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
1706*c689edbbSJens Wiklander            # Skip symbols that cannot be changed. Only check
1707*c689edbbSJens Wiklander            # non-choice symbols, as selects don't affect choice
1708*c689edbbSJens Wiklander            # symbols.
1709*c689edbbSJens Wiklander            if not sym.choice and \
1710*c689edbbSJens Wiklander               sym.visibility <= expr_value(sym.rev_dep):
1711*c689edbbSJens Wiklander                continue
1712*c689edbbSJens Wiklander
1713*c689edbbSJens Wiklander            # Skip symbols whose value matches their default
1714*c689edbbSJens Wiklander            if sym.str_value == sym._str_default():
1715*c689edbbSJens Wiklander                continue
1716*c689edbbSJens Wiklander
1717*c689edbbSJens Wiklander            # Skip symbols that would be selected by default in a
1718*c689edbbSJens Wiklander            # choice, unless the choice is optional or the symbol type
1719*c689edbbSJens Wiklander            # isn't bool (it might be possible to set the choice mode
1720*c689edbbSJens Wiklander            # to n or the symbol to m in those cases).
1721*c689edbbSJens Wiklander            if sym.choice and \
1722*c689edbbSJens Wiklander               not sym.choice.is_optional and \
1723*c689edbbSJens Wiklander               sym.choice._selection_from_defaults() is sym and \
1724*c689edbbSJens Wiklander               sym.orig_type is BOOL and \
1725*c689edbbSJens Wiklander               sym.tri_value == 2:
1726*c689edbbSJens Wiklander                continue
1727*c689edbbSJens Wiklander
1728*c689edbbSJens Wiklander            add(sym.config_string)
1729*c689edbbSJens Wiklander
1730*c689edbbSJens Wiklander        return "".join(chunks)
1731*c689edbbSJens Wiklander
1732*c689edbbSJens Wiklander    def sync_deps(self, path):
1733*c689edbbSJens Wiklander        """
1734*c689edbbSJens Wiklander        Creates or updates a directory structure that can be used to avoid
1735*c689edbbSJens Wiklander        doing a full rebuild whenever the configuration is changed, mirroring
1736*c689edbbSJens Wiklander        include/config/ in the kernel.
1737*c689edbbSJens Wiklander
1738*c689edbbSJens Wiklander        This function is intended to be called during each build, before
1739*c689edbbSJens Wiklander        compiling source files that depend on configuration symbols.
1740*c689edbbSJens Wiklander
1741*c689edbbSJens Wiklander        See the Kconfig.__init__() docstring for raised exceptions
1742*c689edbbSJens Wiklander        (OSError/IOError). KconfigError is never raised here.
1743*c689edbbSJens Wiklander
1744*c689edbbSJens Wiklander        path:
1745*c689edbbSJens Wiklander          Path to directory
1746*c689edbbSJens Wiklander
1747*c689edbbSJens Wiklander        sync_deps(path) does the following:
1748*c689edbbSJens Wiklander
1749*c689edbbSJens Wiklander          1. If the directory <path> does not exist, it is created.
1750*c689edbbSJens Wiklander
1751*c689edbbSJens Wiklander          2. If <path>/auto.conf exists, old symbol values are loaded from it,
1752*c689edbbSJens Wiklander             which are then compared against the current symbol values. If a
1753*c689edbbSJens Wiklander             symbol has changed value (would generate different output in
1754*c689edbbSJens Wiklander             autoconf.h compared to before), the change is signaled by
1755*c689edbbSJens Wiklander             touch'ing a file corresponding to the symbol.
1756*c689edbbSJens Wiklander
1757*c689edbbSJens Wiklander             The first time sync_deps() is run on a directory, <path>/auto.conf
1758*c689edbbSJens Wiklander             won't exist, and no old symbol values will be available. This
1759*c689edbbSJens Wiklander             logically has the same effect as updating the entire
1760*c689edbbSJens Wiklander             configuration.
1761*c689edbbSJens Wiklander
1762*c689edbbSJens Wiklander             The path to a symbol's file is calculated from the symbol's name
1763*c689edbbSJens Wiklander             by replacing all '_' with '/' and appending '.h'. For example, the
1764*c689edbbSJens Wiklander             symbol FOO_BAR_BAZ gets the file <path>/foo/bar/baz.h, and FOO
1765*c689edbbSJens Wiklander             gets the file <path>/foo.h.
1766*c689edbbSJens Wiklander
1767*c689edbbSJens Wiklander             This scheme matches the C tools. The point is to avoid having a
1768*c689edbbSJens Wiklander             single directory with a huge number of files, which the underlying
1769*c689edbbSJens Wiklander             filesystem might not handle well.
1770*c689edbbSJens Wiklander
1771*c689edbbSJens Wiklander          3. A new auto.conf with the current symbol values is written, to keep
1772*c689edbbSJens Wiklander             track of them for the next build.
1773*c689edbbSJens Wiklander
1774*c689edbbSJens Wiklander             If auto.conf exists and its contents is identical to what would
1775*c689edbbSJens Wiklander             get written out, it is left untouched. This avoids updating file
1776*c689edbbSJens Wiklander             metadata like the modification time and possibly triggering
1777*c689edbbSJens Wiklander             redundant work in build tools.
1778*c689edbbSJens Wiklander
1779*c689edbbSJens Wiklander
1780*c689edbbSJens Wiklander        The last piece of the puzzle is knowing what symbols each source file
1781*c689edbbSJens Wiklander        depends on. Knowing that, dependencies can be added from source files
1782*c689edbbSJens Wiklander        to the files corresponding to the symbols they depends on. The source
1783*c689edbbSJens Wiklander        file will then get recompiled (only) when the symbol value changes
1784*c689edbbSJens Wiklander        (provided sync_deps() is run first during each build).
1785*c689edbbSJens Wiklander
1786*c689edbbSJens Wiklander        The tool in the kernel that extracts symbol dependencies from source
1787*c689edbbSJens Wiklander        files is scripts/basic/fixdep.c. Missing symbol files also correspond
1788*c689edbbSJens Wiklander        to "not changed", which fixdep deals with by using the $(wildcard) Make
1789*c689edbbSJens Wiklander        function when adding symbol prerequisites to source files.
1790*c689edbbSJens Wiklander
1791*c689edbbSJens Wiklander        In case you need a different scheme for your project, the sync_deps()
1792*c689edbbSJens Wiklander        implementation can be used as a template.
1793*c689edbbSJens Wiklander        """
1794*c689edbbSJens Wiklander        if not exists(path):
1795*c689edbbSJens Wiklander            os.mkdir(path, 0o755)
1796*c689edbbSJens Wiklander
1797*c689edbbSJens Wiklander        # Load old values from auto.conf, if any
1798*c689edbbSJens Wiklander        self._load_old_vals(path)
1799*c689edbbSJens Wiklander
1800*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
1801*c689edbbSJens Wiklander            # _write_to_conf is determined when the value is calculated. This
1802*c689edbbSJens Wiklander            # is a hidden function call due to property magic.
1803*c689edbbSJens Wiklander            #
1804*c689edbbSJens Wiklander            # Note: In client code, you can check if sym.config_string is empty
1805*c689edbbSJens Wiklander            # instead, to avoid accessing the internal _write_to_conf variable
1806*c689edbbSJens Wiklander            # (though it's likely to keep working).
1807*c689edbbSJens Wiklander            val = sym.str_value
1808*c689edbbSJens Wiklander
1809*c689edbbSJens Wiklander            # n tristate values do not get written to auto.conf and autoconf.h,
1810*c689edbbSJens Wiklander            # making a missing symbol logically equivalent to n
1811*c689edbbSJens Wiklander
1812*c689edbbSJens Wiklander            if sym._write_to_conf:
1813*c689edbbSJens Wiklander                if sym._old_val is None and \
1814*c689edbbSJens Wiklander                   sym.orig_type in _BOOL_TRISTATE and \
1815*c689edbbSJens Wiklander                   val == "n":
1816*c689edbbSJens Wiklander                    # No old value (the symbol was missing or n), new value n.
1817*c689edbbSJens Wiklander                    # No change.
1818*c689edbbSJens Wiklander                    continue
1819*c689edbbSJens Wiklander
1820*c689edbbSJens Wiklander                if val == sym._old_val:
1821*c689edbbSJens Wiklander                    # New value matches old. No change.
1822*c689edbbSJens Wiklander                    continue
1823*c689edbbSJens Wiklander
1824*c689edbbSJens Wiklander            elif sym._old_val is None:
1825*c689edbbSJens Wiklander                # The symbol wouldn't appear in autoconf.h (because
1826*c689edbbSJens Wiklander                # _write_to_conf is false), and it wouldn't have appeared in
1827*c689edbbSJens Wiklander                # autoconf.h previously either (because it didn't appear in
1828*c689edbbSJens Wiklander                # auto.conf). No change.
1829*c689edbbSJens Wiklander                continue
1830*c689edbbSJens Wiklander
1831*c689edbbSJens Wiklander            # 'sym' has a new value. Flag it.
1832*c689edbbSJens Wiklander            _touch_dep_file(path, sym.name)
1833*c689edbbSJens Wiklander
1834*c689edbbSJens Wiklander        # Remember the current values as the "new old" values.
1835*c689edbbSJens Wiklander        #
1836*c689edbbSJens Wiklander        # This call could go anywhere after the call to _load_old_vals(), but
1837*c689edbbSJens Wiklander        # putting it last means _sync_deps() can be safely rerun if it fails
1838*c689edbbSJens Wiklander        # before this point.
1839*c689edbbSJens Wiklander        self._write_old_vals(path)
1840*c689edbbSJens Wiklander
1841*c689edbbSJens Wiklander    def _load_old_vals(self, path):
1842*c689edbbSJens Wiklander        # Loads old symbol values from auto.conf into a dedicated
1843*c689edbbSJens Wiklander        # Symbol._old_val field. Mirrors load_config().
1844*c689edbbSJens Wiklander        #
1845*c689edbbSJens Wiklander        # The extra field could be avoided with some trickery involving dumping
1846*c689edbbSJens Wiklander        # symbol values and restoring them later, but this is simpler and
1847*c689edbbSJens Wiklander        # faster. The C tools also use a dedicated field for this purpose.
1848*c689edbbSJens Wiklander
1849*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
1850*c689edbbSJens Wiklander            sym._old_val = None
1851*c689edbbSJens Wiklander
1852*c689edbbSJens Wiklander        try:
1853*c689edbbSJens Wiklander            auto_conf = self._open(join(path, "auto.conf"), "r")
1854*c689edbbSJens Wiklander        except EnvironmentError as e:
1855*c689edbbSJens Wiklander            if e.errno == errno.ENOENT:
1856*c689edbbSJens Wiklander                # No old values
1857*c689edbbSJens Wiklander                return
1858*c689edbbSJens Wiklander            raise
1859*c689edbbSJens Wiklander
1860*c689edbbSJens Wiklander        with auto_conf as f:
1861*c689edbbSJens Wiklander            for line in f:
1862*c689edbbSJens Wiklander                match = self._set_match(line)
1863*c689edbbSJens Wiklander                if not match:
1864*c689edbbSJens Wiklander                    # We only expect CONFIG_FOO=... (and possibly a header
1865*c689edbbSJens Wiklander                    # comment) in auto.conf
1866*c689edbbSJens Wiklander                    continue
1867*c689edbbSJens Wiklander
1868*c689edbbSJens Wiklander                name, val = match.groups()
1869*c689edbbSJens Wiklander                if name in self.syms:
1870*c689edbbSJens Wiklander                    sym = self.syms[name]
1871*c689edbbSJens Wiklander
1872*c689edbbSJens Wiklander                    if sym.orig_type is STRING:
1873*c689edbbSJens Wiklander                        match = _conf_string_match(val)
1874*c689edbbSJens Wiklander                        if not match:
1875*c689edbbSJens Wiklander                            continue
1876*c689edbbSJens Wiklander                        val = unescape(match.group(1))
1877*c689edbbSJens Wiklander
1878*c689edbbSJens Wiklander                    self.syms[name]._old_val = val
1879*c689edbbSJens Wiklander                else:
1880*c689edbbSJens Wiklander                    # Flag that the symbol no longer exists, in
1881*c689edbbSJens Wiklander                    # case something still depends on it
1882*c689edbbSJens Wiklander                    _touch_dep_file(path, name)
1883*c689edbbSJens Wiklander
1884*c689edbbSJens Wiklander    def _write_old_vals(self, path):
1885*c689edbbSJens Wiklander        # Helper for writing auto.conf. Basically just a simplified
1886*c689edbbSJens Wiklander        # write_config() that doesn't write any comments (including
1887*c689edbbSJens Wiklander        # '# CONFIG_FOO is not set' comments). The format matches the C
1888*c689edbbSJens Wiklander        # implementation, though the ordering is arbitrary there (depends on
1889*c689edbbSJens Wiklander        # the hash table implementation).
1890*c689edbbSJens Wiklander        #
1891*c689edbbSJens Wiklander        # A separate helper function is neater than complicating write_config()
1892*c689edbbSJens Wiklander        # by passing a flag to it, plus we only need to look at symbols here.
1893*c689edbbSJens Wiklander
1894*c689edbbSJens Wiklander        self._write_if_changed(
1895*c689edbbSJens Wiklander            os.path.join(path, "auto.conf"),
1896*c689edbbSJens Wiklander            self._old_vals_contents())
1897*c689edbbSJens Wiklander
1898*c689edbbSJens Wiklander    def _old_vals_contents(self):
1899*c689edbbSJens Wiklander        # _write_old_vals() helper. Returns the contents to write as a string.
1900*c689edbbSJens Wiklander
1901*c689edbbSJens Wiklander        # Temporary list instead of generator makes this a bit faster
1902*c689edbbSJens Wiklander        return "".join([
1903*c689edbbSJens Wiklander            sym.config_string for sym in self.unique_defined_syms
1904*c689edbbSJens Wiklander                if not (sym.orig_type in _BOOL_TRISTATE and not sym.tri_value)
1905*c689edbbSJens Wiklander        ])
1906*c689edbbSJens Wiklander
1907*c689edbbSJens Wiklander    def node_iter(self, unique_syms=False):
1908*c689edbbSJens Wiklander        """
1909*c689edbbSJens Wiklander        Returns a generator for iterating through all MenuNode's in the Kconfig
1910*c689edbbSJens Wiklander        tree. The iteration is done in Kconfig definition order (each node is
1911*c689edbbSJens Wiklander        visited before its children, and the children of a node are visited
1912*c689edbbSJens Wiklander        before the next node).
1913*c689edbbSJens Wiklander
1914*c689edbbSJens Wiklander        The Kconfig.top_node menu node is skipped. It contains an implicit menu
1915*c689edbbSJens Wiklander        that holds the top-level items.
1916*c689edbbSJens Wiklander
1917*c689edbbSJens Wiklander        As an example, the following code will produce a list equal to
1918*c689edbbSJens Wiklander        Kconfig.defined_syms:
1919*c689edbbSJens Wiklander
1920*c689edbbSJens Wiklander          defined_syms = [node.item for node in kconf.node_iter()
1921*c689edbbSJens Wiklander                          if isinstance(node.item, Symbol)]
1922*c689edbbSJens Wiklander
1923*c689edbbSJens Wiklander        unique_syms (default: False):
1924*c689edbbSJens Wiklander          If True, only the first MenuNode will be included for symbols defined
1925*c689edbbSJens Wiklander          in multiple locations.
1926*c689edbbSJens Wiklander
1927*c689edbbSJens Wiklander          Using kconf.node_iter(True) in the example above would give a list
1928*c689edbbSJens Wiklander          equal to unique_defined_syms.
1929*c689edbbSJens Wiklander        """
1930*c689edbbSJens Wiklander        if unique_syms:
1931*c689edbbSJens Wiklander            for sym in self.unique_defined_syms:
1932*c689edbbSJens Wiklander                sym._visited = False
1933*c689edbbSJens Wiklander
1934*c689edbbSJens Wiklander        node = self.top_node
1935*c689edbbSJens Wiklander        while 1:
1936*c689edbbSJens Wiklander            # Jump to the next node with an iterative tree walk
1937*c689edbbSJens Wiklander            if node.list:
1938*c689edbbSJens Wiklander                node = node.list
1939*c689edbbSJens Wiklander            elif node.next:
1940*c689edbbSJens Wiklander                node = node.next
1941*c689edbbSJens Wiklander            else:
1942*c689edbbSJens Wiklander                while node.parent:
1943*c689edbbSJens Wiklander                    node = node.parent
1944*c689edbbSJens Wiklander                    if node.next:
1945*c689edbbSJens Wiklander                        node = node.next
1946*c689edbbSJens Wiklander                        break
1947*c689edbbSJens Wiklander                else:
1948*c689edbbSJens Wiklander                    # No more nodes
1949*c689edbbSJens Wiklander                    return
1950*c689edbbSJens Wiklander
1951*c689edbbSJens Wiklander            if unique_syms and node.item.__class__ is Symbol:
1952*c689edbbSJens Wiklander                if node.item._visited:
1953*c689edbbSJens Wiklander                    continue
1954*c689edbbSJens Wiklander                node.item._visited = True
1955*c689edbbSJens Wiklander
1956*c689edbbSJens Wiklander            yield node
1957*c689edbbSJens Wiklander
1958*c689edbbSJens Wiklander    def eval_string(self, s):
1959*c689edbbSJens Wiklander        """
1960*c689edbbSJens Wiklander        Returns the tristate value of the expression 's', represented as 0, 1,
1961*c689edbbSJens Wiklander        and 2 for n, m, and y, respectively. Raises KconfigError on syntax
1962*c689edbbSJens Wiklander        errors. Warns if undefined symbols are referenced.
1963*c689edbbSJens Wiklander
1964*c689edbbSJens Wiklander        As an example, if FOO and BAR are tristate symbols at least one of
1965*c689edbbSJens Wiklander        which has the value y, then eval_string("y && (FOO || BAR)") returns
1966*c689edbbSJens Wiklander        2 (y).
1967*c689edbbSJens Wiklander
1968*c689edbbSJens Wiklander        To get the string value of non-bool/tristate symbols, use
1969*c689edbbSJens Wiklander        Symbol.str_value. eval_string() always returns a tristate value, and
1970*c689edbbSJens Wiklander        all non-bool/tristate symbols have the tristate value 0 (n).
1971*c689edbbSJens Wiklander
1972*c689edbbSJens Wiklander        The expression parsing is consistent with how parsing works for
1973*c689edbbSJens Wiklander        conditional ('if ...') expressions in the configuration, and matches
1974*c689edbbSJens Wiklander        the C implementation. m is rewritten to 'm && MODULES', so
1975*c689edbbSJens Wiklander        eval_string("m") will return 0 (n) unless modules are enabled.
1976*c689edbbSJens Wiklander        """
1977*c689edbbSJens Wiklander        # The parser is optimized to be fast when parsing Kconfig files (where
1978*c689edbbSJens Wiklander        # an expression can never appear at the beginning of a line). We have
1979*c689edbbSJens Wiklander        # to monkey-patch things a bit here to reuse it.
1980*c689edbbSJens Wiklander
1981*c689edbbSJens Wiklander        self.filename = None
1982*c689edbbSJens Wiklander
1983*c689edbbSJens Wiklander        self._tokens = self._tokenize("if " + s)
1984*c689edbbSJens Wiklander        # Strip "if " to avoid giving confusing error messages
1985*c689edbbSJens Wiklander        self._line = s
1986*c689edbbSJens Wiklander        self._tokens_i = 1  # Skip the 'if' token
1987*c689edbbSJens Wiklander
1988*c689edbbSJens Wiklander        return expr_value(self._expect_expr_and_eol())
1989*c689edbbSJens Wiklander
1990*c689edbbSJens Wiklander    def unset_values(self):
1991*c689edbbSJens Wiklander        """
1992*c689edbbSJens Wiklander        Removes any user values from all symbols, as if Kconfig.load_config()
1993*c689edbbSJens Wiklander        or Symbol.set_value() had never been called.
1994*c689edbbSJens Wiklander        """
1995*c689edbbSJens Wiklander        self._warn_assign_no_prompt = False
1996*c689edbbSJens Wiklander        try:
1997*c689edbbSJens Wiklander            # set_value() already rejects undefined symbols, and they don't
1998*c689edbbSJens Wiklander            # need to be invalidated (because their value never changes), so we
1999*c689edbbSJens Wiklander            # can just iterate over defined symbols
2000*c689edbbSJens Wiklander            for sym in self.unique_defined_syms:
2001*c689edbbSJens Wiklander                sym.unset_value()
2002*c689edbbSJens Wiklander
2003*c689edbbSJens Wiklander            for choice in self.unique_choices:
2004*c689edbbSJens Wiklander                choice.unset_value()
2005*c689edbbSJens Wiklander        finally:
2006*c689edbbSJens Wiklander            self._warn_assign_no_prompt = True
2007*c689edbbSJens Wiklander
2008*c689edbbSJens Wiklander    def enable_warnings(self):
2009*c689edbbSJens Wiklander        """
2010*c689edbbSJens Wiklander        Do 'Kconfig.warn = True' instead. Maintained for backwards
2011*c689edbbSJens Wiklander        compatibility.
2012*c689edbbSJens Wiklander        """
2013*c689edbbSJens Wiklander        self.warn = True
2014*c689edbbSJens Wiklander
2015*c689edbbSJens Wiklander    def disable_warnings(self):
2016*c689edbbSJens Wiklander        """
2017*c689edbbSJens Wiklander        Do 'Kconfig.warn = False' instead. Maintained for backwards
2018*c689edbbSJens Wiklander        compatibility.
2019*c689edbbSJens Wiklander        """
2020*c689edbbSJens Wiklander        self.warn = False
2021*c689edbbSJens Wiklander
2022*c689edbbSJens Wiklander    def enable_stderr_warnings(self):
2023*c689edbbSJens Wiklander        """
2024*c689edbbSJens Wiklander        Do 'Kconfig.warn_to_stderr = True' instead. Maintained for backwards
2025*c689edbbSJens Wiklander        compatibility.
2026*c689edbbSJens Wiklander        """
2027*c689edbbSJens Wiklander        self.warn_to_stderr = True
2028*c689edbbSJens Wiklander
2029*c689edbbSJens Wiklander    def disable_stderr_warnings(self):
2030*c689edbbSJens Wiklander        """
2031*c689edbbSJens Wiklander        Do 'Kconfig.warn_to_stderr = False' instead. Maintained for backwards
2032*c689edbbSJens Wiklander        compatibility.
2033*c689edbbSJens Wiklander        """
2034*c689edbbSJens Wiklander        self.warn_to_stderr = False
2035*c689edbbSJens Wiklander
2036*c689edbbSJens Wiklander    def enable_undef_warnings(self):
2037*c689edbbSJens Wiklander        """
2038*c689edbbSJens Wiklander        Do 'Kconfig.warn_assign_undef = True' instead. Maintained for backwards
2039*c689edbbSJens Wiklander        compatibility.
2040*c689edbbSJens Wiklander        """
2041*c689edbbSJens Wiklander        self.warn_assign_undef = True
2042*c689edbbSJens Wiklander
2043*c689edbbSJens Wiklander    def disable_undef_warnings(self):
2044*c689edbbSJens Wiklander        """
2045*c689edbbSJens Wiklander        Do 'Kconfig.warn_assign_undef = False' instead. Maintained for
2046*c689edbbSJens Wiklander        backwards compatibility.
2047*c689edbbSJens Wiklander        """
2048*c689edbbSJens Wiklander        self.warn_assign_undef = False
2049*c689edbbSJens Wiklander
2050*c689edbbSJens Wiklander    def enable_override_warnings(self):
2051*c689edbbSJens Wiklander        """
2052*c689edbbSJens Wiklander        Do 'Kconfig.warn_assign_override = True' instead. Maintained for
2053*c689edbbSJens Wiklander        backwards compatibility.
2054*c689edbbSJens Wiklander        """
2055*c689edbbSJens Wiklander        self.warn_assign_override = True
2056*c689edbbSJens Wiklander
2057*c689edbbSJens Wiklander    def disable_override_warnings(self):
2058*c689edbbSJens Wiklander        """
2059*c689edbbSJens Wiklander        Do 'Kconfig.warn_assign_override = False' instead. Maintained for
2060*c689edbbSJens Wiklander        backwards compatibility.
2061*c689edbbSJens Wiklander        """
2062*c689edbbSJens Wiklander        self.warn_assign_override = False
2063*c689edbbSJens Wiklander
2064*c689edbbSJens Wiklander    def enable_redun_warnings(self):
2065*c689edbbSJens Wiklander        """
2066*c689edbbSJens Wiklander        Do 'Kconfig.warn_assign_redun = True' instead. Maintained for backwards
2067*c689edbbSJens Wiklander        compatibility.
2068*c689edbbSJens Wiklander        """
2069*c689edbbSJens Wiklander        self.warn_assign_redun = True
2070*c689edbbSJens Wiklander
2071*c689edbbSJens Wiklander    def disable_redun_warnings(self):
2072*c689edbbSJens Wiklander        """
2073*c689edbbSJens Wiklander        Do 'Kconfig.warn_assign_redun = False' instead. Maintained for
2074*c689edbbSJens Wiklander        backwards compatibility.
2075*c689edbbSJens Wiklander        """
2076*c689edbbSJens Wiklander        self.warn_assign_redun = False
2077*c689edbbSJens Wiklander
2078*c689edbbSJens Wiklander    def __repr__(self):
2079*c689edbbSJens Wiklander        """
2080*c689edbbSJens Wiklander        Returns a string with information about the Kconfig object when it is
2081*c689edbbSJens Wiklander        evaluated on e.g. the interactive Python prompt.
2082*c689edbbSJens Wiklander        """
2083*c689edbbSJens Wiklander        def status(flag):
2084*c689edbbSJens Wiklander            return "enabled" if flag else "disabled"
2085*c689edbbSJens Wiklander
2086*c689edbbSJens Wiklander        return "<{}>".format(", ".join((
2087*c689edbbSJens Wiklander            "configuration with {} symbols".format(len(self.syms)),
2088*c689edbbSJens Wiklander            'main menu prompt "{}"'.format(self.mainmenu_text),
2089*c689edbbSJens Wiklander            "srctree is current directory" if not self.srctree else
2090*c689edbbSJens Wiklander                'srctree "{}"'.format(self.srctree),
2091*c689edbbSJens Wiklander            'config symbol prefix "{}"'.format(self.config_prefix),
2092*c689edbbSJens Wiklander            "warnings " + status(self.warn),
2093*c689edbbSJens Wiklander            "printing of warnings to stderr " + status(self.warn_to_stderr),
2094*c689edbbSJens Wiklander            "undef. symbol assignment warnings " +
2095*c689edbbSJens Wiklander                status(self.warn_assign_undef),
2096*c689edbbSJens Wiklander            "overriding symbol assignment warnings " +
2097*c689edbbSJens Wiklander                status(self.warn_assign_override),
2098*c689edbbSJens Wiklander            "redundant symbol assignment warnings " +
2099*c689edbbSJens Wiklander                status(self.warn_assign_redun)
2100*c689edbbSJens Wiklander        )))
2101*c689edbbSJens Wiklander
2102*c689edbbSJens Wiklander    #
2103*c689edbbSJens Wiklander    # Private methods
2104*c689edbbSJens Wiklander    #
2105*c689edbbSJens Wiklander
2106*c689edbbSJens Wiklander
2107*c689edbbSJens Wiklander    #
2108*c689edbbSJens Wiklander    # File reading
2109*c689edbbSJens Wiklander    #
2110*c689edbbSJens Wiklander
2111*c689edbbSJens Wiklander    def _open_config(self, filename):
2112*c689edbbSJens Wiklander        # Opens a .config file. First tries to open 'filename', then
2113*c689edbbSJens Wiklander        # '$srctree/filename' if $srctree was set when the configuration was
2114*c689edbbSJens Wiklander        # loaded.
2115*c689edbbSJens Wiklander
2116*c689edbbSJens Wiklander        try:
2117*c689edbbSJens Wiklander            return self._open(filename, "r")
2118*c689edbbSJens Wiklander        except EnvironmentError as e:
2119*c689edbbSJens Wiklander            # This will try opening the same file twice if $srctree is unset,
2120*c689edbbSJens Wiklander            # but it's not a big deal
2121*c689edbbSJens Wiklander            try:
2122*c689edbbSJens Wiklander                return self._open(join(self.srctree, filename), "r")
2123*c689edbbSJens Wiklander            except EnvironmentError as e2:
2124*c689edbbSJens Wiklander                # This is needed for Python 3, because e2 is deleted after
2125*c689edbbSJens Wiklander                # the try block:
2126*c689edbbSJens Wiklander                #
2127*c689edbbSJens Wiklander                # https://docs.python.org/3/reference/compound_stmts.html#the-try-statement
2128*c689edbbSJens Wiklander                e = e2
2129*c689edbbSJens Wiklander
2130*c689edbbSJens Wiklander            raise _KconfigIOError(
2131*c689edbbSJens Wiklander                e, "Could not open '{}' ({}: {}). Check that the $srctree "
2132*c689edbbSJens Wiklander                   "environment variable ({}) is set correctly."
2133*c689edbbSJens Wiklander                   .format(filename, errno.errorcode[e.errno], e.strerror,
2134*c689edbbSJens Wiklander                           "set to '{}'".format(self.srctree) if self.srctree
2135*c689edbbSJens Wiklander                               else "unset or blank"))
2136*c689edbbSJens Wiklander
2137*c689edbbSJens Wiklander    def _enter_file(self, filename):
2138*c689edbbSJens Wiklander        # Jumps to the beginning of a sourced Kconfig file, saving the previous
2139*c689edbbSJens Wiklander        # position and file object.
2140*c689edbbSJens Wiklander        #
2141*c689edbbSJens Wiklander        # filename:
2142*c689edbbSJens Wiklander        #   Absolute path to file
2143*c689edbbSJens Wiklander
2144*c689edbbSJens Wiklander        # Path relative to $srctree, stored in e.g. self.filename (which makes
2145*c689edbbSJens Wiklander        # it indirectly show up in MenuNode.filename). Equals 'filename' for
2146*c689edbbSJens Wiklander        # absolute paths passed to 'source'.
2147*c689edbbSJens Wiklander        if filename.startswith(self._srctree_prefix):
2148*c689edbbSJens Wiklander            # Relative path (or a redundant absolute path to within $srctree,
2149*c689edbbSJens Wiklander            # but it's probably fine to reduce those too)
2150*c689edbbSJens Wiklander            rel_filename = filename[len(self._srctree_prefix):]
2151*c689edbbSJens Wiklander        else:
2152*c689edbbSJens Wiklander            # Absolute path
2153*c689edbbSJens Wiklander            rel_filename = filename
2154*c689edbbSJens Wiklander
2155*c689edbbSJens Wiklander        self.kconfig_filenames.append(rel_filename)
2156*c689edbbSJens Wiklander
2157*c689edbbSJens Wiklander        # The parent Kconfig files are represented as a list of
2158*c689edbbSJens Wiklander        # (<include path>, <Python 'file' object for Kconfig file>) tuples.
2159*c689edbbSJens Wiklander        #
2160*c689edbbSJens Wiklander        # <include path> is immutable and holds a *tuple* of
2161*c689edbbSJens Wiklander        # (<filename>, <linenr>) tuples, giving the locations of the 'source'
2162*c689edbbSJens Wiklander        # statements in the parent Kconfig files. The current include path is
2163*c689edbbSJens Wiklander        # also available in Kconfig._include_path.
2164*c689edbbSJens Wiklander        #
2165*c689edbbSJens Wiklander        # The point of this redundant setup is to allow Kconfig._include_path
2166*c689edbbSJens Wiklander        # to be assigned directly to MenuNode.include_path without having to
2167*c689edbbSJens Wiklander        # copy it, sharing it wherever possible.
2168*c689edbbSJens Wiklander
2169*c689edbbSJens Wiklander        # Save include path and 'file' object (via its 'readline' function)
2170*c689edbbSJens Wiklander        # before entering the file
2171*c689edbbSJens Wiklander        self._filestack.append((self._include_path, self._readline))
2172*c689edbbSJens Wiklander
2173*c689edbbSJens Wiklander        # _include_path is a tuple, so this rebinds the variable instead of
2174*c689edbbSJens Wiklander        # doing in-place modification
2175*c689edbbSJens Wiklander        self._include_path += ((self.filename, self.linenr),)
2176*c689edbbSJens Wiklander
2177*c689edbbSJens Wiklander        # Check for recursive 'source'
2178*c689edbbSJens Wiklander        for name, _ in self._include_path:
2179*c689edbbSJens Wiklander            if name == rel_filename:
2180*c689edbbSJens Wiklander                raise KconfigError(
2181*c689edbbSJens Wiklander                    "\n{}:{}: recursive 'source' of '{}' detected. Check that "
2182*c689edbbSJens Wiklander                    "environment variables are set correctly.\n"
2183*c689edbbSJens Wiklander                    "Include path:\n{}"
2184*c689edbbSJens Wiklander                    .format(self.filename, self.linenr, rel_filename,
2185*c689edbbSJens Wiklander                            "\n".join("{}:{}".format(name, linenr)
2186*c689edbbSJens Wiklander                                      for name, linenr in self._include_path)))
2187*c689edbbSJens Wiklander
2188*c689edbbSJens Wiklander        try:
2189*c689edbbSJens Wiklander            self._readline = self._open(filename, "r").readline
2190*c689edbbSJens Wiklander        except EnvironmentError as e:
2191*c689edbbSJens Wiklander            # We already know that the file exists
2192*c689edbbSJens Wiklander            raise _KconfigIOError(
2193*c689edbbSJens Wiklander                e, "{}:{}: Could not open '{}' (in '{}') ({}: {})"
2194*c689edbbSJens Wiklander                   .format(self.filename, self.linenr, filename,
2195*c689edbbSJens Wiklander                           self._line.strip(),
2196*c689edbbSJens Wiklander                           errno.errorcode[e.errno], e.strerror))
2197*c689edbbSJens Wiklander
2198*c689edbbSJens Wiklander        self.filename = rel_filename
2199*c689edbbSJens Wiklander        self.linenr = 0
2200*c689edbbSJens Wiklander
2201*c689edbbSJens Wiklander    def _leave_file(self):
2202*c689edbbSJens Wiklander        # Returns from a Kconfig file to the file that sourced it. See
2203*c689edbbSJens Wiklander        # _enter_file().
2204*c689edbbSJens Wiklander
2205*c689edbbSJens Wiklander        # Restore location from parent Kconfig file
2206*c689edbbSJens Wiklander        self.filename, self.linenr = self._include_path[-1]
2207*c689edbbSJens Wiklander        # Restore include path and 'file' object
2208*c689edbbSJens Wiklander        self._readline.__self__.close()  # __self__ fetches the 'file' object
2209*c689edbbSJens Wiklander        self._include_path, self._readline = self._filestack.pop()
2210*c689edbbSJens Wiklander
2211*c689edbbSJens Wiklander    def _next_line(self):
2212*c689edbbSJens Wiklander        # Fetches and tokenizes the next line from the current Kconfig file.
2213*c689edbbSJens Wiklander        # Returns False at EOF and True otherwise.
2214*c689edbbSJens Wiklander
2215*c689edbbSJens Wiklander        # We might already have tokens from parsing a line and discovering that
2216*c689edbbSJens Wiklander        # it's part of a different construct
2217*c689edbbSJens Wiklander        if self._reuse_tokens:
2218*c689edbbSJens Wiklander            self._reuse_tokens = False
2219*c689edbbSJens Wiklander            # self._tokens_i is known to be 1 here, because _parse_props()
2220*c689edbbSJens Wiklander            # leaves it like that when it can't recognize a line (or parses a
2221*c689edbbSJens Wiklander            # help text)
2222*c689edbbSJens Wiklander            return True
2223*c689edbbSJens Wiklander
2224*c689edbbSJens Wiklander        # readline() returns '' over and over at EOF, which we rely on for help
2225*c689edbbSJens Wiklander        # texts at the end of files (see _line_after_help())
2226*c689edbbSJens Wiklander        line = self._readline()
2227*c689edbbSJens Wiklander        if not line:
2228*c689edbbSJens Wiklander            return False
2229*c689edbbSJens Wiklander        self.linenr += 1
2230*c689edbbSJens Wiklander
2231*c689edbbSJens Wiklander        # Handle line joining
2232*c689edbbSJens Wiklander        while line.endswith("\\\n"):
2233*c689edbbSJens Wiklander            line = line[:-2] + self._readline()
2234*c689edbbSJens Wiklander            self.linenr += 1
2235*c689edbbSJens Wiklander
2236*c689edbbSJens Wiklander        self._tokens = self._tokenize(line)
2237*c689edbbSJens Wiklander        # Initialize to 1 instead of 0 to factor out code from _parse_block()
2238*c689edbbSJens Wiklander        # and _parse_props(). They immediately fetch self._tokens[0].
2239*c689edbbSJens Wiklander        self._tokens_i = 1
2240*c689edbbSJens Wiklander
2241*c689edbbSJens Wiklander        return True
2242*c689edbbSJens Wiklander
2243*c689edbbSJens Wiklander    def _line_after_help(self, line):
2244*c689edbbSJens Wiklander        # Tokenizes a line after a help text. This case is special in that the
2245*c689edbbSJens Wiklander        # line has already been fetched (to discover that it isn't part of the
2246*c689edbbSJens Wiklander        # help text).
2247*c689edbbSJens Wiklander        #
2248*c689edbbSJens Wiklander        # An earlier version used a _saved_line variable instead that was
2249*c689edbbSJens Wiklander        # checked in _next_line(). This special-casing gets rid of it and makes
2250*c689edbbSJens Wiklander        # _reuse_tokens alone sufficient to handle unget.
2251*c689edbbSJens Wiklander
2252*c689edbbSJens Wiklander        # Handle line joining
2253*c689edbbSJens Wiklander        while line.endswith("\\\n"):
2254*c689edbbSJens Wiklander            line = line[:-2] + self._readline()
2255*c689edbbSJens Wiklander            self.linenr += 1
2256*c689edbbSJens Wiklander
2257*c689edbbSJens Wiklander        self._tokens = self._tokenize(line)
2258*c689edbbSJens Wiklander        self._reuse_tokens = True
2259*c689edbbSJens Wiklander
2260*c689edbbSJens Wiklander    def _write_if_changed(self, filename, contents):
2261*c689edbbSJens Wiklander        # Writes 'contents' into 'filename', but only if it differs from the
2262*c689edbbSJens Wiklander        # current contents of the file.
2263*c689edbbSJens Wiklander        #
2264*c689edbbSJens Wiklander        # Another variant would be write a temporary file on the same
2265*c689edbbSJens Wiklander        # filesystem, compare the files, and rename() the temporary file if it
2266*c689edbbSJens Wiklander        # differs, but it breaks stuff like write_config("/dev/null"), which is
2267*c689edbbSJens Wiklander        # used out there to force evaluation-related warnings to be generated.
2268*c689edbbSJens Wiklander        # This simple version is pretty failsafe and portable.
2269*c689edbbSJens Wiklander        #
2270*c689edbbSJens Wiklander        # Returns True if the file has changed and is updated, and False
2271*c689edbbSJens Wiklander        # otherwise.
2272*c689edbbSJens Wiklander
2273*c689edbbSJens Wiklander        if self._contents_eq(filename, contents):
2274*c689edbbSJens Wiklander            return False
2275*c689edbbSJens Wiklander        with self._open(filename, "w") as f:
2276*c689edbbSJens Wiklander            f.write(contents)
2277*c689edbbSJens Wiklander        return True
2278*c689edbbSJens Wiklander
2279*c689edbbSJens Wiklander    def _contents_eq(self, filename, contents):
2280*c689edbbSJens Wiklander        # Returns True if the contents of 'filename' is 'contents' (a string),
2281*c689edbbSJens Wiklander        # and False otherwise (including if 'filename' can't be opened/read)
2282*c689edbbSJens Wiklander
2283*c689edbbSJens Wiklander        try:
2284*c689edbbSJens Wiklander            with self._open(filename, "r") as f:
2285*c689edbbSJens Wiklander                # Robust re. things like encoding and line endings (mmap()
2286*c689edbbSJens Wiklander                # trickery isn't)
2287*c689edbbSJens Wiklander                return f.read(len(contents) + 1) == contents
2288*c689edbbSJens Wiklander        except EnvironmentError:
2289*c689edbbSJens Wiklander            # If the error here would prevent writing the file as well, we'll
2290*c689edbbSJens Wiklander            # notice it later
2291*c689edbbSJens Wiklander            return False
2292*c689edbbSJens Wiklander
2293*c689edbbSJens Wiklander    #
2294*c689edbbSJens Wiklander    # Tokenization
2295*c689edbbSJens Wiklander    #
2296*c689edbbSJens Wiklander
2297*c689edbbSJens Wiklander    def _lookup_sym(self, name):
2298*c689edbbSJens Wiklander        # Fetches the symbol 'name' from the symbol table, creating and
2299*c689edbbSJens Wiklander        # registering it if it does not exist. If '_parsing_kconfigs' is False,
2300*c689edbbSJens Wiklander        # it means we're in eval_string(), and new symbols won't be registered.
2301*c689edbbSJens Wiklander
2302*c689edbbSJens Wiklander        if name in self.syms:
2303*c689edbbSJens Wiklander            return self.syms[name]
2304*c689edbbSJens Wiklander
2305*c689edbbSJens Wiklander        sym = Symbol()
2306*c689edbbSJens Wiklander        sym.kconfig = self
2307*c689edbbSJens Wiklander        sym.name = name
2308*c689edbbSJens Wiklander        sym.is_constant = False
2309*c689edbbSJens Wiklander        sym.rev_dep = sym.weak_rev_dep = sym.direct_dep = self.n
2310*c689edbbSJens Wiklander
2311*c689edbbSJens Wiklander        if self._parsing_kconfigs:
2312*c689edbbSJens Wiklander            self.syms[name] = sym
2313*c689edbbSJens Wiklander        else:
2314*c689edbbSJens Wiklander            self._warn("no symbol {} in configuration".format(name))
2315*c689edbbSJens Wiklander
2316*c689edbbSJens Wiklander        return sym
2317*c689edbbSJens Wiklander
2318*c689edbbSJens Wiklander    def _lookup_const_sym(self, name):
2319*c689edbbSJens Wiklander        # Like _lookup_sym(), for constant (quoted) symbols
2320*c689edbbSJens Wiklander
2321*c689edbbSJens Wiklander        if name in self.const_syms:
2322*c689edbbSJens Wiklander            return self.const_syms[name]
2323*c689edbbSJens Wiklander
2324*c689edbbSJens Wiklander        sym = Symbol()
2325*c689edbbSJens Wiklander        sym.kconfig = self
2326*c689edbbSJens Wiklander        sym.name = name
2327*c689edbbSJens Wiklander        sym.is_constant = True
2328*c689edbbSJens Wiklander        sym.rev_dep = sym.weak_rev_dep = sym.direct_dep = self.n
2329*c689edbbSJens Wiklander
2330*c689edbbSJens Wiklander        if self._parsing_kconfigs:
2331*c689edbbSJens Wiklander            self.const_syms[name] = sym
2332*c689edbbSJens Wiklander
2333*c689edbbSJens Wiklander        return sym
2334*c689edbbSJens Wiklander
2335*c689edbbSJens Wiklander    def _tokenize(self, s):
2336*c689edbbSJens Wiklander        # Parses 's', returning a None-terminated list of tokens. Registers any
2337*c689edbbSJens Wiklander        # new symbols encountered with _lookup(_const)_sym().
2338*c689edbbSJens Wiklander        #
2339*c689edbbSJens Wiklander        # Tries to be reasonably speedy by processing chunks of text via
2340*c689edbbSJens Wiklander        # regexes and string operations where possible. This is the biggest
2341*c689edbbSJens Wiklander        # hotspot during parsing.
2342*c689edbbSJens Wiklander        #
2343*c689edbbSJens Wiklander        # It might be possible to rewrite this to 'yield' tokens instead,
2344*c689edbbSJens Wiklander        # working across multiple lines. Lookback and compatibility with old
2345*c689edbbSJens Wiklander        # janky versions of the C tools complicate things though.
2346*c689edbbSJens Wiklander
2347*c689edbbSJens Wiklander        self._line = s  # Used for error reporting
2348*c689edbbSJens Wiklander
2349*c689edbbSJens Wiklander        # Initial token on the line
2350*c689edbbSJens Wiklander        match = _command_match(s)
2351*c689edbbSJens Wiklander        if not match:
2352*c689edbbSJens Wiklander            if s.isspace() or s.lstrip().startswith("#"):
2353*c689edbbSJens Wiklander                return (None,)
2354*c689edbbSJens Wiklander            self._parse_error("unknown token at start of line")
2355*c689edbbSJens Wiklander
2356*c689edbbSJens Wiklander        # Tricky implementation detail: While parsing a token, 'token' refers
2357*c689edbbSJens Wiklander        # to the previous token. See _STRING_LEX for why this is needed.
2358*c689edbbSJens Wiklander        token = _get_keyword(match.group(1))
2359*c689edbbSJens Wiklander        if not token:
2360*c689edbbSJens Wiklander            # Backwards compatibility with old versions of the C tools, which
2361*c689edbbSJens Wiklander            # (accidentally) accepted stuff like "--help--" and "-help---".
2362*c689edbbSJens Wiklander            # This was fixed in the C tools by commit c2264564 ("kconfig: warn
2363*c689edbbSJens Wiklander            # of unhandled characters in Kconfig commands"), committed in July
2364*c689edbbSJens Wiklander            # 2015, but it seems people still run Kconfiglib on older kernels.
2365*c689edbbSJens Wiklander            if s.strip(" \t\n-") == "help":
2366*c689edbbSJens Wiklander                return (_T_HELP, None)
2367*c689edbbSJens Wiklander
2368*c689edbbSJens Wiklander            # If the first token is not a keyword (and not a weird help token),
2369*c689edbbSJens Wiklander            # we have a preprocessor variable assignment (or a bare macro on a
2370*c689edbbSJens Wiklander            # line)
2371*c689edbbSJens Wiklander            self._parse_assignment(s)
2372*c689edbbSJens Wiklander            return (None,)
2373*c689edbbSJens Wiklander
2374*c689edbbSJens Wiklander        tokens = [token]
2375*c689edbbSJens Wiklander        # The current index in the string being tokenized
2376*c689edbbSJens Wiklander        i = match.end()
2377*c689edbbSJens Wiklander
2378*c689edbbSJens Wiklander        # Main tokenization loop (for tokens past the first one)
2379*c689edbbSJens Wiklander        while i < len(s):
2380*c689edbbSJens Wiklander            # Test for an identifier/keyword first. This is the most common
2381*c689edbbSJens Wiklander            # case.
2382*c689edbbSJens Wiklander            match = _id_keyword_match(s, i)
2383*c689edbbSJens Wiklander            if match:
2384*c689edbbSJens Wiklander                # We have an identifier or keyword
2385*c689edbbSJens Wiklander
2386*c689edbbSJens Wiklander                # Check what it is. lookup_sym() will take care of allocating
2387*c689edbbSJens Wiklander                # new symbols for us the first time we see them. Note that
2388*c689edbbSJens Wiklander                # 'token' still refers to the previous token.
2389*c689edbbSJens Wiklander
2390*c689edbbSJens Wiklander                name = match.group(1)
2391*c689edbbSJens Wiklander                keyword = _get_keyword(name)
2392*c689edbbSJens Wiklander                if keyword:
2393*c689edbbSJens Wiklander                    # It's a keyword
2394*c689edbbSJens Wiklander                    token = keyword
2395*c689edbbSJens Wiklander                    # Jump past it
2396*c689edbbSJens Wiklander                    i = match.end()
2397*c689edbbSJens Wiklander
2398*c689edbbSJens Wiklander                elif token not in _STRING_LEX:
2399*c689edbbSJens Wiklander                    # It's a non-const symbol, except we translate n, m, and y
2400*c689edbbSJens Wiklander                    # into the corresponding constant symbols, like the C
2401*c689edbbSJens Wiklander                    # implementation
2402*c689edbbSJens Wiklander
2403*c689edbbSJens Wiklander                    if "$" in name:
2404*c689edbbSJens Wiklander                        # Macro expansion within symbol name
2405*c689edbbSJens Wiklander                        name, s, i = self._expand_name(s, i)
2406*c689edbbSJens Wiklander                    else:
2407*c689edbbSJens Wiklander                        i = match.end()
2408*c689edbbSJens Wiklander
2409*c689edbbSJens Wiklander                    token = self.const_syms[name] if name in STR_TO_TRI else \
2410*c689edbbSJens Wiklander                        self._lookup_sym(name)
2411*c689edbbSJens Wiklander
2412*c689edbbSJens Wiklander                else:
2413*c689edbbSJens Wiklander                    # It's a case of missing quotes. For example, the
2414*c689edbbSJens Wiklander                    # following is accepted:
2415*c689edbbSJens Wiklander                    #
2416*c689edbbSJens Wiklander                    #   menu unquoted_title
2417*c689edbbSJens Wiklander                    #
2418*c689edbbSJens Wiklander                    #   config A
2419*c689edbbSJens Wiklander                    #       tristate unquoted_prompt
2420*c689edbbSJens Wiklander                    #
2421*c689edbbSJens Wiklander                    #   endmenu
2422*c689edbbSJens Wiklander                    #
2423*c689edbbSJens Wiklander                    # Named choices ('choice FOO') also end up here.
2424*c689edbbSJens Wiklander
2425*c689edbbSJens Wiklander                    if token is not _T_CHOICE:
2426*c689edbbSJens Wiklander                        self._warn("style: quotes recommended around '{}' in '{}'"
2427*c689edbbSJens Wiklander                                   .format(name, self._line.strip()),
2428*c689edbbSJens Wiklander                                   self.filename, self.linenr)
2429*c689edbbSJens Wiklander
2430*c689edbbSJens Wiklander                    token = name
2431*c689edbbSJens Wiklander                    i = match.end()
2432*c689edbbSJens Wiklander
2433*c689edbbSJens Wiklander            else:
2434*c689edbbSJens Wiklander                # Neither a keyword nor a non-const symbol
2435*c689edbbSJens Wiklander
2436*c689edbbSJens Wiklander                # We always strip whitespace after tokens, so it is safe to
2437*c689edbbSJens Wiklander                # assume that s[i] is the start of a token here.
2438*c689edbbSJens Wiklander                c = s[i]
2439*c689edbbSJens Wiklander
2440*c689edbbSJens Wiklander                if c in "\"'":
2441*c689edbbSJens Wiklander                    if "$" not in s and "\\" not in s:
2442*c689edbbSJens Wiklander                        # Fast path for lines without $ and \. Find the
2443*c689edbbSJens Wiklander                        # matching quote.
2444*c689edbbSJens Wiklander                        end_i = s.find(c, i + 1) + 1
2445*c689edbbSJens Wiklander                        if not end_i:
2446*c689edbbSJens Wiklander                            self._parse_error("unterminated string")
2447*c689edbbSJens Wiklander                        val = s[i + 1:end_i - 1]
2448*c689edbbSJens Wiklander                        i = end_i
2449*c689edbbSJens Wiklander                    else:
2450*c689edbbSJens Wiklander                        # Slow path
2451*c689edbbSJens Wiklander                        s, end_i = self._expand_str(s, i)
2452*c689edbbSJens Wiklander
2453*c689edbbSJens Wiklander                        # os.path.expandvars() and the $UNAME_RELEASE replace()
2454*c689edbbSJens Wiklander                        # is a backwards compatibility hack, which should be
2455*c689edbbSJens Wiklander                        # reasonably safe as expandvars() leaves references to
2456*c689edbbSJens Wiklander                        # undefined env. vars. as is.
2457*c689edbbSJens Wiklander                        #
2458*c689edbbSJens Wiklander                        # The preprocessor functionality changed how
2459*c689edbbSJens Wiklander                        # environment variables are referenced, to $(FOO).
2460*c689edbbSJens Wiklander                        val = expandvars(s[i + 1:end_i - 1]
2461*c689edbbSJens Wiklander                                         .replace("$UNAME_RELEASE",
2462*c689edbbSJens Wiklander                                                  _UNAME_RELEASE))
2463*c689edbbSJens Wiklander
2464*c689edbbSJens Wiklander                        i = end_i
2465*c689edbbSJens Wiklander
2466*c689edbbSJens Wiklander                    # This is the only place where we don't survive with a
2467*c689edbbSJens Wiklander                    # single token of lookback: 'option env="FOO"' does not
2468*c689edbbSJens Wiklander                    # refer to a constant symbol named "FOO".
2469*c689edbbSJens Wiklander                    token = \
2470*c689edbbSJens Wiklander                        val if token in _STRING_LEX or tokens[0] is _T_OPTION \
2471*c689edbbSJens Wiklander                        else self._lookup_const_sym(val)
2472*c689edbbSJens Wiklander
2473*c689edbbSJens Wiklander                elif s.startswith("&&", i):
2474*c689edbbSJens Wiklander                    token = _T_AND
2475*c689edbbSJens Wiklander                    i += 2
2476*c689edbbSJens Wiklander
2477*c689edbbSJens Wiklander                elif s.startswith("||", i):
2478*c689edbbSJens Wiklander                    token = _T_OR
2479*c689edbbSJens Wiklander                    i += 2
2480*c689edbbSJens Wiklander
2481*c689edbbSJens Wiklander                elif c == "=":
2482*c689edbbSJens Wiklander                    token = _T_EQUAL
2483*c689edbbSJens Wiklander                    i += 1
2484*c689edbbSJens Wiklander
2485*c689edbbSJens Wiklander                elif s.startswith("!=", i):
2486*c689edbbSJens Wiklander                    token = _T_UNEQUAL
2487*c689edbbSJens Wiklander                    i += 2
2488*c689edbbSJens Wiklander
2489*c689edbbSJens Wiklander                elif c == "!":
2490*c689edbbSJens Wiklander                    token = _T_NOT
2491*c689edbbSJens Wiklander                    i += 1
2492*c689edbbSJens Wiklander
2493*c689edbbSJens Wiklander                elif c == "(":
2494*c689edbbSJens Wiklander                    token = _T_OPEN_PAREN
2495*c689edbbSJens Wiklander                    i += 1
2496*c689edbbSJens Wiklander
2497*c689edbbSJens Wiklander                elif c == ")":
2498*c689edbbSJens Wiklander                    token = _T_CLOSE_PAREN
2499*c689edbbSJens Wiklander                    i += 1
2500*c689edbbSJens Wiklander
2501*c689edbbSJens Wiklander                elif c == "#":
2502*c689edbbSJens Wiklander                    break
2503*c689edbbSJens Wiklander
2504*c689edbbSJens Wiklander
2505*c689edbbSJens Wiklander                # Very rare
2506*c689edbbSJens Wiklander
2507*c689edbbSJens Wiklander                elif s.startswith("<=", i):
2508*c689edbbSJens Wiklander                    token = _T_LESS_EQUAL
2509*c689edbbSJens Wiklander                    i += 2
2510*c689edbbSJens Wiklander
2511*c689edbbSJens Wiklander                elif c == "<":
2512*c689edbbSJens Wiklander                    token = _T_LESS
2513*c689edbbSJens Wiklander                    i += 1
2514*c689edbbSJens Wiklander
2515*c689edbbSJens Wiklander                elif s.startswith(">=", i):
2516*c689edbbSJens Wiklander                    token = _T_GREATER_EQUAL
2517*c689edbbSJens Wiklander                    i += 2
2518*c689edbbSJens Wiklander
2519*c689edbbSJens Wiklander                elif c == ">":
2520*c689edbbSJens Wiklander                    token = _T_GREATER
2521*c689edbbSJens Wiklander                    i += 1
2522*c689edbbSJens Wiklander
2523*c689edbbSJens Wiklander
2524*c689edbbSJens Wiklander                else:
2525*c689edbbSJens Wiklander                    self._parse_error("unknown tokens in line")
2526*c689edbbSJens Wiklander
2527*c689edbbSJens Wiklander
2528*c689edbbSJens Wiklander                # Skip trailing whitespace
2529*c689edbbSJens Wiklander                while i < len(s) and s[i].isspace():
2530*c689edbbSJens Wiklander                    i += 1
2531*c689edbbSJens Wiklander
2532*c689edbbSJens Wiklander
2533*c689edbbSJens Wiklander            # Add the token
2534*c689edbbSJens Wiklander            tokens.append(token)
2535*c689edbbSJens Wiklander
2536*c689edbbSJens Wiklander        # None-terminating the token list makes token fetching simpler/faster
2537*c689edbbSJens Wiklander        tokens.append(None)
2538*c689edbbSJens Wiklander
2539*c689edbbSJens Wiklander        return tokens
2540*c689edbbSJens Wiklander
2541*c689edbbSJens Wiklander    # Helpers for syntax checking and token fetching. See the
2542*c689edbbSJens Wiklander    # 'Intro to expressions' section for what a constant symbol is.
2543*c689edbbSJens Wiklander    #
2544*c689edbbSJens Wiklander    # More of these could be added, but the single-use cases are inlined as an
2545*c689edbbSJens Wiklander    # optimization.
2546*c689edbbSJens Wiklander
2547*c689edbbSJens Wiklander    def _expect_sym(self):
2548*c689edbbSJens Wiklander        token = self._tokens[self._tokens_i]
2549*c689edbbSJens Wiklander        self._tokens_i += 1
2550*c689edbbSJens Wiklander
2551*c689edbbSJens Wiklander        if token.__class__ is not Symbol:
2552*c689edbbSJens Wiklander            self._parse_error("expected symbol")
2553*c689edbbSJens Wiklander
2554*c689edbbSJens Wiklander        return token
2555*c689edbbSJens Wiklander
2556*c689edbbSJens Wiklander    def _expect_nonconst_sym(self):
2557*c689edbbSJens Wiklander        # Used for 'select' and 'imply' only. We know the token indices.
2558*c689edbbSJens Wiklander
2559*c689edbbSJens Wiklander        token = self._tokens[1]
2560*c689edbbSJens Wiklander        self._tokens_i = 2
2561*c689edbbSJens Wiklander
2562*c689edbbSJens Wiklander        if token.__class__ is not Symbol or token.is_constant:
2563*c689edbbSJens Wiklander            self._parse_error("expected nonconstant symbol")
2564*c689edbbSJens Wiklander
2565*c689edbbSJens Wiklander        return token
2566*c689edbbSJens Wiklander
2567*c689edbbSJens Wiklander    def _expect_str_and_eol(self):
2568*c689edbbSJens Wiklander        token = self._tokens[self._tokens_i]
2569*c689edbbSJens Wiklander        self._tokens_i += 1
2570*c689edbbSJens Wiklander
2571*c689edbbSJens Wiklander        if token.__class__ is not str:
2572*c689edbbSJens Wiklander            self._parse_error("expected string")
2573*c689edbbSJens Wiklander
2574*c689edbbSJens Wiklander        if self._tokens[self._tokens_i] is not None:
2575*c689edbbSJens Wiklander            self._trailing_tokens_error()
2576*c689edbbSJens Wiklander
2577*c689edbbSJens Wiklander        return token
2578*c689edbbSJens Wiklander
2579*c689edbbSJens Wiklander    def _expect_expr_and_eol(self):
2580*c689edbbSJens Wiklander        expr = self._parse_expr(True)
2581*c689edbbSJens Wiklander
2582*c689edbbSJens Wiklander        if self._tokens[self._tokens_i] is not None:
2583*c689edbbSJens Wiklander            self._trailing_tokens_error()
2584*c689edbbSJens Wiklander
2585*c689edbbSJens Wiklander        return expr
2586*c689edbbSJens Wiklander
2587*c689edbbSJens Wiklander    def _check_token(self, token):
2588*c689edbbSJens Wiklander        # If the next token is 'token', removes it and returns True
2589*c689edbbSJens Wiklander
2590*c689edbbSJens Wiklander        if self._tokens[self._tokens_i] is token:
2591*c689edbbSJens Wiklander            self._tokens_i += 1
2592*c689edbbSJens Wiklander            return True
2593*c689edbbSJens Wiklander        return False
2594*c689edbbSJens Wiklander
2595*c689edbbSJens Wiklander    #
2596*c689edbbSJens Wiklander    # Preprocessor logic
2597*c689edbbSJens Wiklander    #
2598*c689edbbSJens Wiklander
2599*c689edbbSJens Wiklander    def _parse_assignment(self, s):
2600*c689edbbSJens Wiklander        # Parses a preprocessor variable assignment, registering the variable
2601*c689edbbSJens Wiklander        # if it doesn't already exist. Also takes care of bare macros on lines
2602*c689edbbSJens Wiklander        # (which are allowed, and can be useful for their side effects).
2603*c689edbbSJens Wiklander
2604*c689edbbSJens Wiklander        # Expand any macros in the left-hand side of the assignment (the
2605*c689edbbSJens Wiklander        # variable name)
2606*c689edbbSJens Wiklander        s = s.lstrip()
2607*c689edbbSJens Wiklander        i = 0
2608*c689edbbSJens Wiklander        while 1:
2609*c689edbbSJens Wiklander            i = _assignment_lhs_fragment_match(s, i).end()
2610*c689edbbSJens Wiklander            if s.startswith("$(", i):
2611*c689edbbSJens Wiklander                s, i = self._expand_macro(s, i, ())
2612*c689edbbSJens Wiklander            else:
2613*c689edbbSJens Wiklander                break
2614*c689edbbSJens Wiklander
2615*c689edbbSJens Wiklander        if s.isspace():
2616*c689edbbSJens Wiklander            # We also accept a bare macro on a line (e.g.
2617*c689edbbSJens Wiklander            # $(warning-if,$(foo),ops)), provided it expands to a blank string
2618*c689edbbSJens Wiklander            return
2619*c689edbbSJens Wiklander
2620*c689edbbSJens Wiklander        # Assigned variable
2621*c689edbbSJens Wiklander        name = s[:i]
2622*c689edbbSJens Wiklander
2623*c689edbbSJens Wiklander
2624*c689edbbSJens Wiklander        # Extract assignment operator (=, :=, or +=) and value
2625*c689edbbSJens Wiklander        rhs_match = _assignment_rhs_match(s, i)
2626*c689edbbSJens Wiklander        if not rhs_match:
2627*c689edbbSJens Wiklander            self._parse_error("syntax error")
2628*c689edbbSJens Wiklander
2629*c689edbbSJens Wiklander        op, val = rhs_match.groups()
2630*c689edbbSJens Wiklander
2631*c689edbbSJens Wiklander
2632*c689edbbSJens Wiklander        if name in self.variables:
2633*c689edbbSJens Wiklander            # Already seen variable
2634*c689edbbSJens Wiklander            var = self.variables[name]
2635*c689edbbSJens Wiklander        else:
2636*c689edbbSJens Wiklander            # New variable
2637*c689edbbSJens Wiklander            var = Variable()
2638*c689edbbSJens Wiklander            var.kconfig = self
2639*c689edbbSJens Wiklander            var.name = name
2640*c689edbbSJens Wiklander            var._n_expansions = 0
2641*c689edbbSJens Wiklander            self.variables[name] = var
2642*c689edbbSJens Wiklander
2643*c689edbbSJens Wiklander            # += acts like = on undefined variables (defines a recursive
2644*c689edbbSJens Wiklander            # variable)
2645*c689edbbSJens Wiklander            if op == "+=":
2646*c689edbbSJens Wiklander                op = "="
2647*c689edbbSJens Wiklander
2648*c689edbbSJens Wiklander        if op == "=":
2649*c689edbbSJens Wiklander            var.is_recursive = True
2650*c689edbbSJens Wiklander            var.value = val
2651*c689edbbSJens Wiklander        elif op == ":=":
2652*c689edbbSJens Wiklander            var.is_recursive = False
2653*c689edbbSJens Wiklander            var.value = self._expand_whole(val, ())
2654*c689edbbSJens Wiklander        else:  # op == "+="
2655*c689edbbSJens Wiklander            # += does immediate expansion if the variable was last set
2656*c689edbbSJens Wiklander            # with :=
2657*c689edbbSJens Wiklander            var.value += " " + (val if var.is_recursive else
2658*c689edbbSJens Wiklander                                self._expand_whole(val, ()))
2659*c689edbbSJens Wiklander
2660*c689edbbSJens Wiklander    def _expand_whole(self, s, args):
2661*c689edbbSJens Wiklander        # Expands preprocessor macros in all of 's'. Used whenever we don't
2662*c689edbbSJens Wiklander        # have to worry about delimiters. See _expand_macro() re. the 'args'
2663*c689edbbSJens Wiklander        # parameter.
2664*c689edbbSJens Wiklander        #
2665*c689edbbSJens Wiklander        # Returns the expanded string.
2666*c689edbbSJens Wiklander
2667*c689edbbSJens Wiklander        i = 0
2668*c689edbbSJens Wiklander        while 1:
2669*c689edbbSJens Wiklander            i = s.find("$(", i)
2670*c689edbbSJens Wiklander            if i == -1:
2671*c689edbbSJens Wiklander                break
2672*c689edbbSJens Wiklander            s, i = self._expand_macro(s, i, args)
2673*c689edbbSJens Wiklander        return s
2674*c689edbbSJens Wiklander
2675*c689edbbSJens Wiklander    def _expand_name(self, s, i):
2676*c689edbbSJens Wiklander        # Expands a symbol name starting at index 'i' in 's'.
2677*c689edbbSJens Wiklander        #
2678*c689edbbSJens Wiklander        # Returns the expanded name, the expanded 's' (including the part
2679*c689edbbSJens Wiklander        # before the name), and the index of the first character in the next
2680*c689edbbSJens Wiklander        # token after the name.
2681*c689edbbSJens Wiklander
2682*c689edbbSJens Wiklander        s, end_i = self._expand_name_iter(s, i)
2683*c689edbbSJens Wiklander        name = s[i:end_i]
2684*c689edbbSJens Wiklander        # isspace() is False for empty strings
2685*c689edbbSJens Wiklander        if not name.strip():
2686*c689edbbSJens Wiklander            # Avoid creating a Kconfig symbol with a blank name. It's almost
2687*c689edbbSJens Wiklander            # guaranteed to be an error.
2688*c689edbbSJens Wiklander            self._parse_error("macro expanded to blank string")
2689*c689edbbSJens Wiklander
2690*c689edbbSJens Wiklander        # Skip trailing whitespace
2691*c689edbbSJens Wiklander        while end_i < len(s) and s[end_i].isspace():
2692*c689edbbSJens Wiklander            end_i += 1
2693*c689edbbSJens Wiklander
2694*c689edbbSJens Wiklander        return name, s, end_i
2695*c689edbbSJens Wiklander
2696*c689edbbSJens Wiklander    def _expand_name_iter(self, s, i):
2697*c689edbbSJens Wiklander        # Expands a symbol name starting at index 'i' in 's'.
2698*c689edbbSJens Wiklander        #
2699*c689edbbSJens Wiklander        # Returns the expanded 's' (including the part before the name) and the
2700*c689edbbSJens Wiklander        # index of the first character after the expanded name in 's'.
2701*c689edbbSJens Wiklander
2702*c689edbbSJens Wiklander        while 1:
2703*c689edbbSJens Wiklander            match = _name_special_search(s, i)
2704*c689edbbSJens Wiklander
2705*c689edbbSJens Wiklander            if match.group() != "$(":
2706*c689edbbSJens Wiklander                return (s, match.start())
2707*c689edbbSJens Wiklander            s, i = self._expand_macro(s, match.start(), ())
2708*c689edbbSJens Wiklander
2709*c689edbbSJens Wiklander    def _expand_str(self, s, i):
2710*c689edbbSJens Wiklander        # Expands a quoted string starting at index 'i' in 's'. Handles both
2711*c689edbbSJens Wiklander        # backslash escapes and macro expansion.
2712*c689edbbSJens Wiklander        #
2713*c689edbbSJens Wiklander        # Returns the expanded 's' (including the part before the string) and
2714*c689edbbSJens Wiklander        # the index of the first character after the expanded string in 's'.
2715*c689edbbSJens Wiklander
2716*c689edbbSJens Wiklander        quote = s[i]
2717*c689edbbSJens Wiklander        i += 1  # Skip over initial "/'
2718*c689edbbSJens Wiklander        while 1:
2719*c689edbbSJens Wiklander            match = _string_special_search(s, i)
2720*c689edbbSJens Wiklander            if not match:
2721*c689edbbSJens Wiklander                self._parse_error("unterminated string")
2722*c689edbbSJens Wiklander
2723*c689edbbSJens Wiklander
2724*c689edbbSJens Wiklander            if match.group() == quote:
2725*c689edbbSJens Wiklander                # Found the end of the string
2726*c689edbbSJens Wiklander                return (s, match.end())
2727*c689edbbSJens Wiklander
2728*c689edbbSJens Wiklander            elif match.group() == "\\":
2729*c689edbbSJens Wiklander                # Replace '\x' with 'x'. 'i' ends up pointing to the character
2730*c689edbbSJens Wiklander                # after 'x', which allows macros to be canceled with '\$(foo)'.
2731*c689edbbSJens Wiklander                i = match.end()
2732*c689edbbSJens Wiklander                s = s[:match.start()] + s[i:]
2733*c689edbbSJens Wiklander
2734*c689edbbSJens Wiklander            elif match.group() == "$(":
2735*c689edbbSJens Wiklander                # A macro call within the string
2736*c689edbbSJens Wiklander                s, i = self._expand_macro(s, match.start(), ())
2737*c689edbbSJens Wiklander
2738*c689edbbSJens Wiklander            else:
2739*c689edbbSJens Wiklander                # A ' quote within " quotes or vice versa
2740*c689edbbSJens Wiklander                i += 1
2741*c689edbbSJens Wiklander
2742*c689edbbSJens Wiklander    def _expand_macro(self, s, i, args):
2743*c689edbbSJens Wiklander        # Expands a macro starting at index 'i' in 's'. If this macro resulted
2744*c689edbbSJens Wiklander        # from the expansion of another macro, 'args' holds the arguments
2745*c689edbbSJens Wiklander        # passed to that macro.
2746*c689edbbSJens Wiklander        #
2747*c689edbbSJens Wiklander        # Returns the expanded 's' (including the part before the macro) and
2748*c689edbbSJens Wiklander        # the index of the first character after the expanded macro in 's'.
2749*c689edbbSJens Wiklander
2750*c689edbbSJens Wiklander        res = s[:i]
2751*c689edbbSJens Wiklander        i += 2  # Skip over "$("
2752*c689edbbSJens Wiklander
2753*c689edbbSJens Wiklander        arg_start = i  # Start of current macro argument
2754*c689edbbSJens Wiklander        new_args = []  # Arguments of this macro call
2755*c689edbbSJens Wiklander        nesting = 0  # Current parentheses nesting level
2756*c689edbbSJens Wiklander
2757*c689edbbSJens Wiklander        while 1:
2758*c689edbbSJens Wiklander            match = _macro_special_search(s, i)
2759*c689edbbSJens Wiklander            if not match:
2760*c689edbbSJens Wiklander                self._parse_error("missing end parenthesis in macro expansion")
2761*c689edbbSJens Wiklander
2762*c689edbbSJens Wiklander
2763*c689edbbSJens Wiklander            if match.group() == "(":
2764*c689edbbSJens Wiklander                nesting += 1
2765*c689edbbSJens Wiklander                i = match.end()
2766*c689edbbSJens Wiklander
2767*c689edbbSJens Wiklander            elif match.group() == ")":
2768*c689edbbSJens Wiklander                if nesting:
2769*c689edbbSJens Wiklander                    nesting -= 1
2770*c689edbbSJens Wiklander                    i = match.end()
2771*c689edbbSJens Wiklander                    continue
2772*c689edbbSJens Wiklander
2773*c689edbbSJens Wiklander                # Found the end of the macro
2774*c689edbbSJens Wiklander
2775*c689edbbSJens Wiklander                new_args.append(s[arg_start:match.start()])
2776*c689edbbSJens Wiklander
2777*c689edbbSJens Wiklander                # $(1) is replaced by the first argument to the function, etc.,
2778*c689edbbSJens Wiklander                # provided at least that many arguments were passed
2779*c689edbbSJens Wiklander
2780*c689edbbSJens Wiklander                try:
2781*c689edbbSJens Wiklander                    # Does the macro look like an integer, with a corresponding
2782*c689edbbSJens Wiklander                    # argument? If so, expand it to the value of the argument.
2783*c689edbbSJens Wiklander                    res += args[int(new_args[0])]
2784*c689edbbSJens Wiklander                except (ValueError, IndexError):
2785*c689edbbSJens Wiklander                    # Regular variables are just functions without arguments,
2786*c689edbbSJens Wiklander                    # and also go through the function value path
2787*c689edbbSJens Wiklander                    res += self._fn_val(new_args)
2788*c689edbbSJens Wiklander
2789*c689edbbSJens Wiklander                return (res + s[match.end():], len(res))
2790*c689edbbSJens Wiklander
2791*c689edbbSJens Wiklander            elif match.group() == ",":
2792*c689edbbSJens Wiklander                i = match.end()
2793*c689edbbSJens Wiklander                if nesting:
2794*c689edbbSJens Wiklander                    continue
2795*c689edbbSJens Wiklander
2796*c689edbbSJens Wiklander                # Found the end of a macro argument
2797*c689edbbSJens Wiklander                new_args.append(s[arg_start:match.start()])
2798*c689edbbSJens Wiklander                arg_start = i
2799*c689edbbSJens Wiklander
2800*c689edbbSJens Wiklander            else:  # match.group() == "$("
2801*c689edbbSJens Wiklander                # A nested macro call within the macro
2802*c689edbbSJens Wiklander                s, i = self._expand_macro(s, match.start(), args)
2803*c689edbbSJens Wiklander
2804*c689edbbSJens Wiklander    def _fn_val(self, args):
2805*c689edbbSJens Wiklander        # Returns the result of calling the function args[0] with the arguments
2806*c689edbbSJens Wiklander        # args[1..len(args)-1]. Plain variables are treated as functions
2807*c689edbbSJens Wiklander        # without arguments.
2808*c689edbbSJens Wiklander
2809*c689edbbSJens Wiklander        fn = args[0]
2810*c689edbbSJens Wiklander
2811*c689edbbSJens Wiklander        if fn in self.variables:
2812*c689edbbSJens Wiklander            var = self.variables[fn]
2813*c689edbbSJens Wiklander
2814*c689edbbSJens Wiklander            if len(args) == 1:
2815*c689edbbSJens Wiklander                # Plain variable
2816*c689edbbSJens Wiklander                if var._n_expansions:
2817*c689edbbSJens Wiklander                    self._parse_error("Preprocessor variable {} recursively "
2818*c689edbbSJens Wiklander                                      "references itself".format(var.name))
2819*c689edbbSJens Wiklander            elif var._n_expansions > 100:
2820*c689edbbSJens Wiklander                # Allow functions to call themselves, but guess that functions
2821*c689edbbSJens Wiklander                # that are overly recursive are stuck
2822*c689edbbSJens Wiklander                self._parse_error("Preprocessor function {} seems stuck "
2823*c689edbbSJens Wiklander                                  "in infinite recursion".format(var.name))
2824*c689edbbSJens Wiklander
2825*c689edbbSJens Wiklander            var._n_expansions += 1
2826*c689edbbSJens Wiklander            res = self._expand_whole(self.variables[fn].value, args)
2827*c689edbbSJens Wiklander            var._n_expansions -= 1
2828*c689edbbSJens Wiklander            return res
2829*c689edbbSJens Wiklander
2830*c689edbbSJens Wiklander        if fn in self._functions:
2831*c689edbbSJens Wiklander            # Built-in or user-defined function
2832*c689edbbSJens Wiklander
2833*c689edbbSJens Wiklander            py_fn, min_arg, max_arg = self._functions[fn]
2834*c689edbbSJens Wiklander
2835*c689edbbSJens Wiklander            if len(args) - 1 < min_arg or \
2836*c689edbbSJens Wiklander               (max_arg is not None and len(args) - 1 > max_arg):
2837*c689edbbSJens Wiklander
2838*c689edbbSJens Wiklander                if min_arg == max_arg:
2839*c689edbbSJens Wiklander                    expected_args = min_arg
2840*c689edbbSJens Wiklander                elif max_arg is None:
2841*c689edbbSJens Wiklander                    expected_args = "{} or more".format(min_arg)
2842*c689edbbSJens Wiklander                else:
2843*c689edbbSJens Wiklander                    expected_args = "{}-{}".format(min_arg, max_arg)
2844*c689edbbSJens Wiklander
2845*c689edbbSJens Wiklander                raise KconfigError("{}:{}: bad number of arguments in call "
2846*c689edbbSJens Wiklander                                   "to {}, expected {}, got {}"
2847*c689edbbSJens Wiklander                                   .format(self.filename, self.linenr, fn,
2848*c689edbbSJens Wiklander                                           expected_args, len(args) - 1))
2849*c689edbbSJens Wiklander
2850*c689edbbSJens Wiklander            return py_fn(self, *args)
2851*c689edbbSJens Wiklander
2852*c689edbbSJens Wiklander        # Environment variables are tried last
2853*c689edbbSJens Wiklander        if fn in os.environ:
2854*c689edbbSJens Wiklander            self.env_vars.add(fn)
2855*c689edbbSJens Wiklander            return os.environ[fn]
2856*c689edbbSJens Wiklander
2857*c689edbbSJens Wiklander        return ""
2858*c689edbbSJens Wiklander
2859*c689edbbSJens Wiklander    #
2860*c689edbbSJens Wiklander    # Parsing
2861*c689edbbSJens Wiklander    #
2862*c689edbbSJens Wiklander
2863*c689edbbSJens Wiklander    def _make_and(self, e1, e2):
2864*c689edbbSJens Wiklander        # Constructs an AND (&&) expression. Performs trivial simplification.
2865*c689edbbSJens Wiklander
2866*c689edbbSJens Wiklander        if e1 is self.y:
2867*c689edbbSJens Wiklander            return e2
2868*c689edbbSJens Wiklander
2869*c689edbbSJens Wiklander        if e2 is self.y:
2870*c689edbbSJens Wiklander            return e1
2871*c689edbbSJens Wiklander
2872*c689edbbSJens Wiklander        if e1 is self.n or e2 is self.n:
2873*c689edbbSJens Wiklander            return self.n
2874*c689edbbSJens Wiklander
2875*c689edbbSJens Wiklander        return (AND, e1, e2)
2876*c689edbbSJens Wiklander
2877*c689edbbSJens Wiklander    def _make_or(self, e1, e2):
2878*c689edbbSJens Wiklander        # Constructs an OR (||) expression. Performs trivial simplification.
2879*c689edbbSJens Wiklander
2880*c689edbbSJens Wiklander        if e1 is self.n:
2881*c689edbbSJens Wiklander            return e2
2882*c689edbbSJens Wiklander
2883*c689edbbSJens Wiklander        if e2 is self.n:
2884*c689edbbSJens Wiklander            return e1
2885*c689edbbSJens Wiklander
2886*c689edbbSJens Wiklander        if e1 is self.y or e2 is self.y:
2887*c689edbbSJens Wiklander            return self.y
2888*c689edbbSJens Wiklander
2889*c689edbbSJens Wiklander        return (OR, e1, e2)
2890*c689edbbSJens Wiklander
2891*c689edbbSJens Wiklander    def _parse_block(self, end_token, parent, prev):
2892*c689edbbSJens Wiklander        # Parses a block, which is the contents of either a file or an if,
2893*c689edbbSJens Wiklander        # menu, or choice statement.
2894*c689edbbSJens Wiklander        #
2895*c689edbbSJens Wiklander        # end_token:
2896*c689edbbSJens Wiklander        #   The token that ends the block, e.g. _T_ENDIF ("endif") for ifs.
2897*c689edbbSJens Wiklander        #   None for files.
2898*c689edbbSJens Wiklander        #
2899*c689edbbSJens Wiklander        # parent:
2900*c689edbbSJens Wiklander        #   The parent menu node, corresponding to a menu, Choice, or 'if'.
2901*c689edbbSJens Wiklander        #   'if's are flattened after parsing.
2902*c689edbbSJens Wiklander        #
2903*c689edbbSJens Wiklander        # prev:
2904*c689edbbSJens Wiklander        #   The previous menu node. New nodes will be added after this one (by
2905*c689edbbSJens Wiklander        #   modifying 'next' pointers).
2906*c689edbbSJens Wiklander        #
2907*c689edbbSJens Wiklander        #   'prev' is reused to parse a list of child menu nodes (for a menu or
2908*c689edbbSJens Wiklander        #   Choice): After parsing the children, the 'next' pointer is assigned
2909*c689edbbSJens Wiklander        #   to the 'list' pointer to "tilt up" the children above the node.
2910*c689edbbSJens Wiklander        #
2911*c689edbbSJens Wiklander        # Returns the final menu node in the block (or 'prev' if the block is
2912*c689edbbSJens Wiklander        # empty). This allows chaining.
2913*c689edbbSJens Wiklander
2914*c689edbbSJens Wiklander        while self._next_line():
2915*c689edbbSJens Wiklander            t0 = self._tokens[0]
2916*c689edbbSJens Wiklander
2917*c689edbbSJens Wiklander            if t0 is _T_CONFIG or t0 is _T_MENUCONFIG:
2918*c689edbbSJens Wiklander                # The tokenizer allocates Symbol objects for us
2919*c689edbbSJens Wiklander                sym = self._tokens[1]
2920*c689edbbSJens Wiklander
2921*c689edbbSJens Wiklander                if sym.__class__ is not Symbol or sym.is_constant:
2922*c689edbbSJens Wiklander                    self._parse_error("missing or bad symbol name")
2923*c689edbbSJens Wiklander
2924*c689edbbSJens Wiklander                if self._tokens[2] is not None:
2925*c689edbbSJens Wiklander                    self._trailing_tokens_error()
2926*c689edbbSJens Wiklander
2927*c689edbbSJens Wiklander                self.defined_syms.append(sym)
2928*c689edbbSJens Wiklander
2929*c689edbbSJens Wiklander                node = MenuNode()
2930*c689edbbSJens Wiklander                node.kconfig = self
2931*c689edbbSJens Wiklander                node.item = sym
2932*c689edbbSJens Wiklander                node.is_menuconfig = (t0 is _T_MENUCONFIG)
2933*c689edbbSJens Wiklander                node.prompt = node.help = node.list = None
2934*c689edbbSJens Wiklander                node.parent = parent
2935*c689edbbSJens Wiklander                node.filename = self.filename
2936*c689edbbSJens Wiklander                node.linenr = self.linenr
2937*c689edbbSJens Wiklander                node.include_path = self._include_path
2938*c689edbbSJens Wiklander
2939*c689edbbSJens Wiklander                sym.nodes.append(node)
2940*c689edbbSJens Wiklander
2941*c689edbbSJens Wiklander                self._parse_props(node)
2942*c689edbbSJens Wiklander
2943*c689edbbSJens Wiklander                if node.is_menuconfig and not node.prompt:
2944*c689edbbSJens Wiklander                    self._warn("the menuconfig symbol {} has no prompt"
2945*c689edbbSJens Wiklander                               .format(sym.name_and_loc))
2946*c689edbbSJens Wiklander
2947*c689edbbSJens Wiklander                # Equivalent to
2948*c689edbbSJens Wiklander                #
2949*c689edbbSJens Wiklander                #   prev.next = node
2950*c689edbbSJens Wiklander                #   prev = node
2951*c689edbbSJens Wiklander                #
2952*c689edbbSJens Wiklander                # due to tricky Python semantics. The order matters.
2953*c689edbbSJens Wiklander                prev.next = prev = node
2954*c689edbbSJens Wiklander
2955*c689edbbSJens Wiklander            elif t0 is None:
2956*c689edbbSJens Wiklander                # Blank line
2957*c689edbbSJens Wiklander                continue
2958*c689edbbSJens Wiklander
2959*c689edbbSJens Wiklander            elif t0 in _SOURCE_TOKENS:
2960*c689edbbSJens Wiklander                pattern = self._expect_str_and_eol()
2961*c689edbbSJens Wiklander
2962*c689edbbSJens Wiklander                if t0 in _REL_SOURCE_TOKENS:
2963*c689edbbSJens Wiklander                    # Relative source
2964*c689edbbSJens Wiklander                    pattern = join(dirname(self.filename), pattern)
2965*c689edbbSJens Wiklander
2966*c689edbbSJens Wiklander                # - glob() doesn't support globbing relative to a directory, so
2967*c689edbbSJens Wiklander                #   we need to prepend $srctree to 'pattern'. Use join()
2968*c689edbbSJens Wiklander                #   instead of '+' so that an absolute path in 'pattern' is
2969*c689edbbSJens Wiklander                #   preserved.
2970*c689edbbSJens Wiklander                #
2971*c689edbbSJens Wiklander                # - Sort the glob results to ensure a consistent ordering of
2972*c689edbbSJens Wiklander                #   Kconfig symbols, which indirectly ensures a consistent
2973*c689edbbSJens Wiklander                #   ordering in e.g. .config files
2974*c689edbbSJens Wiklander                filenames = sorted(iglob(join(self._srctree_prefix, pattern)))
2975*c689edbbSJens Wiklander
2976*c689edbbSJens Wiklander                if not filenames and t0 in _OBL_SOURCE_TOKENS:
2977*c689edbbSJens Wiklander                    raise KconfigError(
2978*c689edbbSJens Wiklander                        "{}:{}: '{}' not found (in '{}'). Check that "
2979*c689edbbSJens Wiklander                        "environment variables are set correctly (e.g. "
2980*c689edbbSJens Wiklander                        "$srctree, which is {}). Also note that unset "
2981*c689edbbSJens Wiklander                        "environment variables expand to the empty string."
2982*c689edbbSJens Wiklander                        .format(self.filename, self.linenr, pattern,
2983*c689edbbSJens Wiklander                                self._line.strip(),
2984*c689edbbSJens Wiklander                                "set to '{}'".format(self.srctree)
2985*c689edbbSJens Wiklander                                    if self.srctree else "unset or blank"))
2986*c689edbbSJens Wiklander
2987*c689edbbSJens Wiklander                for filename in filenames:
2988*c689edbbSJens Wiklander                    self._enter_file(filename)
2989*c689edbbSJens Wiklander                    prev = self._parse_block(None, parent, prev)
2990*c689edbbSJens Wiklander                    self._leave_file()
2991*c689edbbSJens Wiklander
2992*c689edbbSJens Wiklander            elif t0 is end_token:
2993*c689edbbSJens Wiklander                # Reached the end of the block. Terminate the final node and
2994*c689edbbSJens Wiklander                # return it.
2995*c689edbbSJens Wiklander
2996*c689edbbSJens Wiklander                if self._tokens[1] is not None:
2997*c689edbbSJens Wiklander                    self._trailing_tokens_error()
2998*c689edbbSJens Wiklander
2999*c689edbbSJens Wiklander                prev.next = None
3000*c689edbbSJens Wiklander                return prev
3001*c689edbbSJens Wiklander
3002*c689edbbSJens Wiklander            elif t0 is _T_IF:
3003*c689edbbSJens Wiklander                node = MenuNode()
3004*c689edbbSJens Wiklander                node.item = node.prompt = None
3005*c689edbbSJens Wiklander                node.parent = parent
3006*c689edbbSJens Wiklander                node.dep = self._expect_expr_and_eol()
3007*c689edbbSJens Wiklander
3008*c689edbbSJens Wiklander                self._parse_block(_T_ENDIF, node, node)
3009*c689edbbSJens Wiklander                node.list = node.next
3010*c689edbbSJens Wiklander
3011*c689edbbSJens Wiklander                prev.next = prev = node
3012*c689edbbSJens Wiklander
3013*c689edbbSJens Wiklander            elif t0 is _T_MENU:
3014*c689edbbSJens Wiklander                node = MenuNode()
3015*c689edbbSJens Wiklander                node.kconfig = self
3016*c689edbbSJens Wiklander                node.item = t0  # _T_MENU == MENU
3017*c689edbbSJens Wiklander                node.is_menuconfig = True
3018*c689edbbSJens Wiklander                node.prompt = (self._expect_str_and_eol(), self.y)
3019*c689edbbSJens Wiklander                node.visibility = self.y
3020*c689edbbSJens Wiklander                node.parent = parent
3021*c689edbbSJens Wiklander                node.filename = self.filename
3022*c689edbbSJens Wiklander                node.linenr = self.linenr
3023*c689edbbSJens Wiklander                node.include_path = self._include_path
3024*c689edbbSJens Wiklander
3025*c689edbbSJens Wiklander                self.menus.append(node)
3026*c689edbbSJens Wiklander
3027*c689edbbSJens Wiklander                self._parse_props(node)
3028*c689edbbSJens Wiklander                self._parse_block(_T_ENDMENU, node, node)
3029*c689edbbSJens Wiklander                node.list = node.next
3030*c689edbbSJens Wiklander
3031*c689edbbSJens Wiklander                prev.next = prev = node
3032*c689edbbSJens Wiklander
3033*c689edbbSJens Wiklander            elif t0 is _T_COMMENT:
3034*c689edbbSJens Wiklander                node = MenuNode()
3035*c689edbbSJens Wiklander                node.kconfig = self
3036*c689edbbSJens Wiklander                node.item = t0  # _T_COMMENT == COMMENT
3037*c689edbbSJens Wiklander                node.is_menuconfig = False
3038*c689edbbSJens Wiklander                node.prompt = (self._expect_str_and_eol(), self.y)
3039*c689edbbSJens Wiklander                node.list = None
3040*c689edbbSJens Wiklander                node.parent = parent
3041*c689edbbSJens Wiklander                node.filename = self.filename
3042*c689edbbSJens Wiklander                node.linenr = self.linenr
3043*c689edbbSJens Wiklander                node.include_path = self._include_path
3044*c689edbbSJens Wiklander
3045*c689edbbSJens Wiklander                self.comments.append(node)
3046*c689edbbSJens Wiklander
3047*c689edbbSJens Wiklander                self._parse_props(node)
3048*c689edbbSJens Wiklander
3049*c689edbbSJens Wiklander                prev.next = prev = node
3050*c689edbbSJens Wiklander
3051*c689edbbSJens Wiklander            elif t0 is _T_CHOICE:
3052*c689edbbSJens Wiklander                if self._tokens[1] is None:
3053*c689edbbSJens Wiklander                    choice = Choice()
3054*c689edbbSJens Wiklander                    choice.direct_dep = self.n
3055*c689edbbSJens Wiklander                else:
3056*c689edbbSJens Wiklander                    # Named choice
3057*c689edbbSJens Wiklander                    name = self._expect_str_and_eol()
3058*c689edbbSJens Wiklander                    choice = self.named_choices.get(name)
3059*c689edbbSJens Wiklander                    if not choice:
3060*c689edbbSJens Wiklander                        choice = Choice()
3061*c689edbbSJens Wiklander                        choice.name = name
3062*c689edbbSJens Wiklander                        choice.direct_dep = self.n
3063*c689edbbSJens Wiklander                        self.named_choices[name] = choice
3064*c689edbbSJens Wiklander
3065*c689edbbSJens Wiklander                self.choices.append(choice)
3066*c689edbbSJens Wiklander
3067*c689edbbSJens Wiklander                node = MenuNode()
3068*c689edbbSJens Wiklander                node.kconfig = choice.kconfig = self
3069*c689edbbSJens Wiklander                node.item = choice
3070*c689edbbSJens Wiklander                node.is_menuconfig = True
3071*c689edbbSJens Wiklander                node.prompt = node.help = None
3072*c689edbbSJens Wiklander                node.parent = parent
3073*c689edbbSJens Wiklander                node.filename = self.filename
3074*c689edbbSJens Wiklander                node.linenr = self.linenr
3075*c689edbbSJens Wiklander                node.include_path = self._include_path
3076*c689edbbSJens Wiklander
3077*c689edbbSJens Wiklander                choice.nodes.append(node)
3078*c689edbbSJens Wiklander
3079*c689edbbSJens Wiklander                self._parse_props(node)
3080*c689edbbSJens Wiklander                self._parse_block(_T_ENDCHOICE, node, node)
3081*c689edbbSJens Wiklander                node.list = node.next
3082*c689edbbSJens Wiklander
3083*c689edbbSJens Wiklander                prev.next = prev = node
3084*c689edbbSJens Wiklander
3085*c689edbbSJens Wiklander            elif t0 is _T_MAINMENU:
3086*c689edbbSJens Wiklander                self.top_node.prompt = (self._expect_str_and_eol(), self.y)
3087*c689edbbSJens Wiklander
3088*c689edbbSJens Wiklander            else:
3089*c689edbbSJens Wiklander                # A valid endchoice/endif/endmenu is caught by the 'end_token'
3090*c689edbbSJens Wiklander                # check above
3091*c689edbbSJens Wiklander                self._parse_error(
3092*c689edbbSJens Wiklander                    "no corresponding 'choice'" if t0 is _T_ENDCHOICE else
3093*c689edbbSJens Wiklander                    "no corresponding 'if'"     if t0 is _T_ENDIF else
3094*c689edbbSJens Wiklander                    "no corresponding 'menu'"   if t0 is _T_ENDMENU else
3095*c689edbbSJens Wiklander                    "unrecognized construct")
3096*c689edbbSJens Wiklander
3097*c689edbbSJens Wiklander        # End of file reached. Return the last node.
3098*c689edbbSJens Wiklander
3099*c689edbbSJens Wiklander        if end_token:
3100*c689edbbSJens Wiklander            raise KconfigError(
3101*c689edbbSJens Wiklander                "error: expected '{}' at end of '{}'"
3102*c689edbbSJens Wiklander                .format("endchoice" if end_token is _T_ENDCHOICE else
3103*c689edbbSJens Wiklander                        "endif"     if end_token is _T_ENDIF else
3104*c689edbbSJens Wiklander                        "endmenu",
3105*c689edbbSJens Wiklander                        self.filename))
3106*c689edbbSJens Wiklander
3107*c689edbbSJens Wiklander        return prev
3108*c689edbbSJens Wiklander
3109*c689edbbSJens Wiklander    def _parse_cond(self):
3110*c689edbbSJens Wiklander        # Parses an optional 'if <expr>' construct and returns the parsed
3111*c689edbbSJens Wiklander        # <expr>, or self.y if the next token is not _T_IF
3112*c689edbbSJens Wiklander
3113*c689edbbSJens Wiklander        expr = self._parse_expr(True) if self._check_token(_T_IF) else self.y
3114*c689edbbSJens Wiklander
3115*c689edbbSJens Wiklander        if self._tokens[self._tokens_i] is not None:
3116*c689edbbSJens Wiklander            self._trailing_tokens_error()
3117*c689edbbSJens Wiklander
3118*c689edbbSJens Wiklander        return expr
3119*c689edbbSJens Wiklander
3120*c689edbbSJens Wiklander    def _parse_props(self, node):
3121*c689edbbSJens Wiklander        # Parses and adds properties to the MenuNode 'node' (type, 'prompt',
3122*c689edbbSJens Wiklander        # 'default's, etc.) Properties are later copied up to symbols and
3123*c689edbbSJens Wiklander        # choices in a separate pass after parsing, in e.g.
3124*c689edbbSJens Wiklander        # _add_props_to_sym().
3125*c689edbbSJens Wiklander        #
3126*c689edbbSJens Wiklander        # An older version of this code added properties directly to symbols
3127*c689edbbSJens Wiklander        # and choices instead of to their menu nodes (and handled dependency
3128*c689edbbSJens Wiklander        # propagation simultaneously), but that loses information on where a
3129*c689edbbSJens Wiklander        # property is added when a symbol or choice is defined in multiple
3130*c689edbbSJens Wiklander        # locations. Some Kconfig configuration systems rely heavily on such
3131*c689edbbSJens Wiklander        # symbols, and better docs can be generated by keeping track of where
3132*c689edbbSJens Wiklander        # properties are added.
3133*c689edbbSJens Wiklander        #
3134*c689edbbSJens Wiklander        # node:
3135*c689edbbSJens Wiklander        #   The menu node we're parsing properties on
3136*c689edbbSJens Wiklander
3137*c689edbbSJens Wiklander        # Dependencies from 'depends on'. Will get propagated to the properties
3138*c689edbbSJens Wiklander        # below.
3139*c689edbbSJens Wiklander        node.dep = self.y
3140*c689edbbSJens Wiklander
3141*c689edbbSJens Wiklander        while self._next_line():
3142*c689edbbSJens Wiklander            t0 = self._tokens[0]
3143*c689edbbSJens Wiklander
3144*c689edbbSJens Wiklander            if t0 in _TYPE_TOKENS:
3145*c689edbbSJens Wiklander                # Relies on '_T_BOOL is BOOL', etc., to save a conversion
3146*c689edbbSJens Wiklander                self._set_type(node.item, t0)
3147*c689edbbSJens Wiklander                if self._tokens[1] is not None:
3148*c689edbbSJens Wiklander                    self._parse_prompt(node)
3149*c689edbbSJens Wiklander
3150*c689edbbSJens Wiklander            elif t0 is _T_DEPENDS:
3151*c689edbbSJens Wiklander                if not self._check_token(_T_ON):
3152*c689edbbSJens Wiklander                    self._parse_error("expected 'on' after 'depends'")
3153*c689edbbSJens Wiklander
3154*c689edbbSJens Wiklander                node.dep = self._make_and(node.dep,
3155*c689edbbSJens Wiklander                                          self._expect_expr_and_eol())
3156*c689edbbSJens Wiklander
3157*c689edbbSJens Wiklander            elif t0 is _T_HELP:
3158*c689edbbSJens Wiklander                self._parse_help(node)
3159*c689edbbSJens Wiklander
3160*c689edbbSJens Wiklander            elif t0 is _T_SELECT:
3161*c689edbbSJens Wiklander                if node.item.__class__ is not Symbol:
3162*c689edbbSJens Wiklander                    self._parse_error("only symbols can select")
3163*c689edbbSJens Wiklander
3164*c689edbbSJens Wiklander                node.selects.append((self._expect_nonconst_sym(),
3165*c689edbbSJens Wiklander                                     self._parse_cond()))
3166*c689edbbSJens Wiklander
3167*c689edbbSJens Wiklander            elif t0 is None:
3168*c689edbbSJens Wiklander                # Blank line
3169*c689edbbSJens Wiklander                continue
3170*c689edbbSJens Wiklander
3171*c689edbbSJens Wiklander            elif t0 is _T_DEFAULT:
3172*c689edbbSJens Wiklander                node.defaults.append((self._parse_expr(False),
3173*c689edbbSJens Wiklander                                      self._parse_cond()))
3174*c689edbbSJens Wiklander
3175*c689edbbSJens Wiklander            elif t0 in _DEF_TOKEN_TO_TYPE:
3176*c689edbbSJens Wiklander                self._set_type(node.item, _DEF_TOKEN_TO_TYPE[t0])
3177*c689edbbSJens Wiklander                node.defaults.append((self._parse_expr(False),
3178*c689edbbSJens Wiklander                                      self._parse_cond()))
3179*c689edbbSJens Wiklander
3180*c689edbbSJens Wiklander            elif t0 is _T_PROMPT:
3181*c689edbbSJens Wiklander                self._parse_prompt(node)
3182*c689edbbSJens Wiklander
3183*c689edbbSJens Wiklander            elif t0 is _T_RANGE:
3184*c689edbbSJens Wiklander                node.ranges.append((self._expect_sym(), self._expect_sym(),
3185*c689edbbSJens Wiklander                                    self._parse_cond()))
3186*c689edbbSJens Wiklander
3187*c689edbbSJens Wiklander            elif t0 is _T_IMPLY:
3188*c689edbbSJens Wiklander                if node.item.__class__ is not Symbol:
3189*c689edbbSJens Wiklander                    self._parse_error("only symbols can imply")
3190*c689edbbSJens Wiklander
3191*c689edbbSJens Wiklander                node.implies.append((self._expect_nonconst_sym(),
3192*c689edbbSJens Wiklander                                     self._parse_cond()))
3193*c689edbbSJens Wiklander
3194*c689edbbSJens Wiklander            elif t0 is _T_VISIBLE:
3195*c689edbbSJens Wiklander                if not self._check_token(_T_IF):
3196*c689edbbSJens Wiklander                    self._parse_error("expected 'if' after 'visible'")
3197*c689edbbSJens Wiklander
3198*c689edbbSJens Wiklander                node.visibility = self._make_and(node.visibility,
3199*c689edbbSJens Wiklander                                                 self._expect_expr_and_eol())
3200*c689edbbSJens Wiklander
3201*c689edbbSJens Wiklander            elif t0 is _T_OPTION:
3202*c689edbbSJens Wiklander                if self._check_token(_T_ENV):
3203*c689edbbSJens Wiklander                    if not self._check_token(_T_EQUAL):
3204*c689edbbSJens Wiklander                        self._parse_error("expected '=' after 'env'")
3205*c689edbbSJens Wiklander
3206*c689edbbSJens Wiklander                    env_var = self._expect_str_and_eol()
3207*c689edbbSJens Wiklander                    node.item.env_var = env_var
3208*c689edbbSJens Wiklander
3209*c689edbbSJens Wiklander                    if env_var in os.environ:
3210*c689edbbSJens Wiklander                        node.defaults.append(
3211*c689edbbSJens Wiklander                            (self._lookup_const_sym(os.environ[env_var]),
3212*c689edbbSJens Wiklander                             self.y))
3213*c689edbbSJens Wiklander                    else:
3214*c689edbbSJens Wiklander                        self._warn("{1} has 'option env=\"{0}\"', "
3215*c689edbbSJens Wiklander                                   "but the environment variable {0} is not "
3216*c689edbbSJens Wiklander                                   "set".format(node.item.name, env_var),
3217*c689edbbSJens Wiklander                                   self.filename, self.linenr)
3218*c689edbbSJens Wiklander
3219*c689edbbSJens Wiklander                    if env_var != node.item.name:
3220*c689edbbSJens Wiklander                        self._warn("Kconfiglib expands environment variables "
3221*c689edbbSJens Wiklander                                   "in strings directly, meaning you do not "
3222*c689edbbSJens Wiklander                                   "need 'option env=...' \"bounce\" symbols. "
3223*c689edbbSJens Wiklander                                   "For compatibility with the C tools, "
3224*c689edbbSJens Wiklander                                   "rename {} to {} (so that the symbol name "
3225*c689edbbSJens Wiklander                                   "matches the environment variable name)."
3226*c689edbbSJens Wiklander                                   .format(node.item.name, env_var),
3227*c689edbbSJens Wiklander                                   self.filename, self.linenr)
3228*c689edbbSJens Wiklander
3229*c689edbbSJens Wiklander                elif self._check_token(_T_DEFCONFIG_LIST):
3230*c689edbbSJens Wiklander                    if not self.defconfig_list:
3231*c689edbbSJens Wiklander                        self.defconfig_list = node.item
3232*c689edbbSJens Wiklander                    else:
3233*c689edbbSJens Wiklander                        self._warn("'option defconfig_list' set on multiple "
3234*c689edbbSJens Wiklander                                   "symbols ({0} and {1}). Only {0} will be "
3235*c689edbbSJens Wiklander                                   "used.".format(self.defconfig_list.name,
3236*c689edbbSJens Wiklander                                                  node.item.name),
3237*c689edbbSJens Wiklander                                   self.filename, self.linenr)
3238*c689edbbSJens Wiklander
3239*c689edbbSJens Wiklander                elif self._check_token(_T_MODULES):
3240*c689edbbSJens Wiklander                    # To reduce warning spam, only warn if 'option modules' is
3241*c689edbbSJens Wiklander                    # set on some symbol that isn't MODULES, which should be
3242*c689edbbSJens Wiklander                    # safe. I haven't run into any projects that make use
3243*c689edbbSJens Wiklander                    # modules besides the kernel yet, and there it's likely to
3244*c689edbbSJens Wiklander                    # keep being called "MODULES".
3245*c689edbbSJens Wiklander                    if node.item is not self.modules:
3246*c689edbbSJens Wiklander                        self._warn("the 'modules' option is not supported. "
3247*c689edbbSJens Wiklander                                   "Let me know if this is a problem for you, "
3248*c689edbbSJens Wiklander                                   "as it wouldn't be that hard to implement. "
3249*c689edbbSJens Wiklander                                   "Note that modules are supported -- "
3250*c689edbbSJens Wiklander                                   "Kconfiglib just assumes the symbol name "
3251*c689edbbSJens Wiklander                                   "MODULES, like older versions of the C "
3252*c689edbbSJens Wiklander                                   "implementation did when 'option modules' "
3253*c689edbbSJens Wiklander                                   "wasn't used.",
3254*c689edbbSJens Wiklander                                   self.filename, self.linenr)
3255*c689edbbSJens Wiklander
3256*c689edbbSJens Wiklander                elif self._check_token(_T_ALLNOCONFIG_Y):
3257*c689edbbSJens Wiklander                    if node.item.__class__ is not Symbol:
3258*c689edbbSJens Wiklander                        self._parse_error("the 'allnoconfig_y' option is only "
3259*c689edbbSJens Wiklander                                          "valid for symbols")
3260*c689edbbSJens Wiklander
3261*c689edbbSJens Wiklander                    node.item.is_allnoconfig_y = True
3262*c689edbbSJens Wiklander
3263*c689edbbSJens Wiklander                else:
3264*c689edbbSJens Wiklander                    self._parse_error("unrecognized option")
3265*c689edbbSJens Wiklander
3266*c689edbbSJens Wiklander            elif t0 is _T_OPTIONAL:
3267*c689edbbSJens Wiklander                if node.item.__class__ is not Choice:
3268*c689edbbSJens Wiklander                    self._parse_error('"optional" is only valid for choices')
3269*c689edbbSJens Wiklander
3270*c689edbbSJens Wiklander                node.item.is_optional = True
3271*c689edbbSJens Wiklander
3272*c689edbbSJens Wiklander            else:
3273*c689edbbSJens Wiklander                # Reuse the tokens for the non-property line later
3274*c689edbbSJens Wiklander                self._reuse_tokens = True
3275*c689edbbSJens Wiklander                return
3276*c689edbbSJens Wiklander
3277*c689edbbSJens Wiklander    def _set_type(self, sc, new_type):
3278*c689edbbSJens Wiklander        # Sets the type of 'sc' (symbol or choice) to 'new_type'
3279*c689edbbSJens Wiklander
3280*c689edbbSJens Wiklander        # UNKNOWN is falsy
3281*c689edbbSJens Wiklander        if sc.orig_type and sc.orig_type is not new_type:
3282*c689edbbSJens Wiklander            self._warn("{} defined with multiple types, {} will be used"
3283*c689edbbSJens Wiklander                       .format(sc.name_and_loc, TYPE_TO_STR[new_type]))
3284*c689edbbSJens Wiklander
3285*c689edbbSJens Wiklander        sc.orig_type = new_type
3286*c689edbbSJens Wiklander
3287*c689edbbSJens Wiklander    def _parse_prompt(self, node):
3288*c689edbbSJens Wiklander        # 'prompt' properties override each other within a single definition of
3289*c689edbbSJens Wiklander        # a symbol, but additional prompts can be added by defining the symbol
3290*c689edbbSJens Wiklander        # multiple times
3291*c689edbbSJens Wiklander
3292*c689edbbSJens Wiklander        if node.prompt:
3293*c689edbbSJens Wiklander            self._warn(node.item.name_and_loc +
3294*c689edbbSJens Wiklander                       " defined with multiple prompts in single location")
3295*c689edbbSJens Wiklander
3296*c689edbbSJens Wiklander        prompt = self._tokens[1]
3297*c689edbbSJens Wiklander        self._tokens_i = 2
3298*c689edbbSJens Wiklander
3299*c689edbbSJens Wiklander        if prompt.__class__ is not str:
3300*c689edbbSJens Wiklander            self._parse_error("expected prompt string")
3301*c689edbbSJens Wiklander
3302*c689edbbSJens Wiklander        if prompt != prompt.strip():
3303*c689edbbSJens Wiklander            self._warn(node.item.name_and_loc +
3304*c689edbbSJens Wiklander                       " has leading or trailing whitespace in its prompt")
3305*c689edbbSJens Wiklander
3306*c689edbbSJens Wiklander            # This avoid issues for e.g. reStructuredText documentation, where
3307*c689edbbSJens Wiklander            # '*prompt *' is invalid
3308*c689edbbSJens Wiklander            prompt = prompt.strip()
3309*c689edbbSJens Wiklander
3310*c689edbbSJens Wiklander        node.prompt = (prompt, self._parse_cond())
3311*c689edbbSJens Wiklander
3312*c689edbbSJens Wiklander    def _parse_help(self, node):
3313*c689edbbSJens Wiklander        if node.help is not None:
3314*c689edbbSJens Wiklander            self._warn(node.item.name_and_loc + " defined with more than "
3315*c689edbbSJens Wiklander                       "one help text -- only the last one will be used")
3316*c689edbbSJens Wiklander
3317*c689edbbSJens Wiklander        # Micro-optimization. This code is pretty hot.
3318*c689edbbSJens Wiklander        readline = self._readline
3319*c689edbbSJens Wiklander
3320*c689edbbSJens Wiklander        # Find first non-blank (not all-space) line and get its
3321*c689edbbSJens Wiklander        # indentation
3322*c689edbbSJens Wiklander
3323*c689edbbSJens Wiklander        while 1:
3324*c689edbbSJens Wiklander            line = readline()
3325*c689edbbSJens Wiklander            self.linenr += 1
3326*c689edbbSJens Wiklander            if not line:
3327*c689edbbSJens Wiklander                self._empty_help(node, line)
3328*c689edbbSJens Wiklander                return
3329*c689edbbSJens Wiklander            if not line.isspace():
3330*c689edbbSJens Wiklander                break
3331*c689edbbSJens Wiklander
3332*c689edbbSJens Wiklander        len_ = len  # Micro-optimization
3333*c689edbbSJens Wiklander
3334*c689edbbSJens Wiklander        # Use a separate 'expline' variable here and below to avoid stomping on
3335*c689edbbSJens Wiklander        # any tabs people might've put deliberately into the first line after
3336*c689edbbSJens Wiklander        # the help text
3337*c689edbbSJens Wiklander        expline = line.expandtabs()
3338*c689edbbSJens Wiklander        indent = len_(expline) - len_(expline.lstrip())
3339*c689edbbSJens Wiklander        if not indent:
3340*c689edbbSJens Wiklander            self._empty_help(node, line)
3341*c689edbbSJens Wiklander            return
3342*c689edbbSJens Wiklander
3343*c689edbbSJens Wiklander        # The help text goes on till the first non-blank line with less indent
3344*c689edbbSJens Wiklander        # than the first line
3345*c689edbbSJens Wiklander
3346*c689edbbSJens Wiklander        # Add the first line
3347*c689edbbSJens Wiklander        lines = [expline[indent:]]
3348*c689edbbSJens Wiklander        add_line = lines.append  # Micro-optimization
3349*c689edbbSJens Wiklander
3350*c689edbbSJens Wiklander        while 1:
3351*c689edbbSJens Wiklander            line = readline()
3352*c689edbbSJens Wiklander            if line.isspace():
3353*c689edbbSJens Wiklander                # No need to preserve the exact whitespace in these
3354*c689edbbSJens Wiklander                add_line("\n")
3355*c689edbbSJens Wiklander            elif not line:
3356*c689edbbSJens Wiklander                # End of file
3357*c689edbbSJens Wiklander                break
3358*c689edbbSJens Wiklander            else:
3359*c689edbbSJens Wiklander                expline = line.expandtabs()
3360*c689edbbSJens Wiklander                if len_(expline) - len_(expline.lstrip()) < indent:
3361*c689edbbSJens Wiklander                    break
3362*c689edbbSJens Wiklander                add_line(expline[indent:])
3363*c689edbbSJens Wiklander
3364*c689edbbSJens Wiklander        self.linenr += len_(lines)
3365*c689edbbSJens Wiklander        node.help = "".join(lines).rstrip()
3366*c689edbbSJens Wiklander        if line:
3367*c689edbbSJens Wiklander            self._line_after_help(line)
3368*c689edbbSJens Wiklander
3369*c689edbbSJens Wiklander    def _empty_help(self, node, line):
3370*c689edbbSJens Wiklander        self._warn(node.item.name_and_loc +
3371*c689edbbSJens Wiklander                   " has 'help' but empty help text")
3372*c689edbbSJens Wiklander        node.help = ""
3373*c689edbbSJens Wiklander        if line:
3374*c689edbbSJens Wiklander            self._line_after_help(line)
3375*c689edbbSJens Wiklander
3376*c689edbbSJens Wiklander    def _parse_expr(self, transform_m):
3377*c689edbbSJens Wiklander        # Parses an expression from the tokens in Kconfig._tokens using a
3378*c689edbbSJens Wiklander        # simple top-down approach. See the module docstring for the expression
3379*c689edbbSJens Wiklander        # format.
3380*c689edbbSJens Wiklander        #
3381*c689edbbSJens Wiklander        # transform_m:
3382*c689edbbSJens Wiklander        #   True if m should be rewritten to m && MODULES. See the
3383*c689edbbSJens Wiklander        #   Kconfig.eval_string() documentation.
3384*c689edbbSJens Wiklander
3385*c689edbbSJens Wiklander        # Grammar:
3386*c689edbbSJens Wiklander        #
3387*c689edbbSJens Wiklander        #   expr:     and_expr ['||' expr]
3388*c689edbbSJens Wiklander        #   and_expr: factor ['&&' and_expr]
3389*c689edbbSJens Wiklander        #   factor:   <symbol> ['='/'!='/'<'/... <symbol>]
3390*c689edbbSJens Wiklander        #             '!' factor
3391*c689edbbSJens Wiklander        #             '(' expr ')'
3392*c689edbbSJens Wiklander        #
3393*c689edbbSJens Wiklander        # It helps to think of the 'expr: and_expr' case as a single-operand OR
3394*c689edbbSJens Wiklander        # (no ||), and of the 'and_expr: factor' case as a single-operand AND
3395*c689edbbSJens Wiklander        # (no &&). Parsing code is always a bit tricky.
3396*c689edbbSJens Wiklander
3397*c689edbbSJens Wiklander        # Mind dump: parse_factor() and two nested loops for OR and AND would
3398*c689edbbSJens Wiklander        # work as well. The straightforward implementation there gives a
3399*c689edbbSJens Wiklander        # (op, (op, (op, A, B), C), D) parse for A op B op C op D. Representing
3400*c689edbbSJens Wiklander        # expressions as (op, [list of operands]) instead goes nicely with that
3401*c689edbbSJens Wiklander        # version, but is wasteful for short expressions and complicates
3402*c689edbbSJens Wiklander        # expression evaluation and other code that works on expressions (more
3403*c689edbbSJens Wiklander        # complicated code likely offsets any performance gain from less
3404*c689edbbSJens Wiklander        # recursion too). If we also try to optimize the list representation by
3405*c689edbbSJens Wiklander        # merging lists when possible (e.g. when ANDing two AND expressions),
3406*c689edbbSJens Wiklander        # we end up allocating a ton of lists instead of reusing expressions,
3407*c689edbbSJens Wiklander        # which is bad.
3408*c689edbbSJens Wiklander
3409*c689edbbSJens Wiklander        and_expr = self._parse_and_expr(transform_m)
3410*c689edbbSJens Wiklander
3411*c689edbbSJens Wiklander        # Return 'and_expr' directly if we have a "single-operand" OR.
3412*c689edbbSJens Wiklander        # Otherwise, parse the expression on the right and make an OR node.
3413*c689edbbSJens Wiklander        # This turns A || B || C || D into (OR, A, (OR, B, (OR, C, D))).
3414*c689edbbSJens Wiklander        return and_expr if not self._check_token(_T_OR) else \
3415*c689edbbSJens Wiklander            (OR, and_expr, self._parse_expr(transform_m))
3416*c689edbbSJens Wiklander
3417*c689edbbSJens Wiklander    def _parse_and_expr(self, transform_m):
3418*c689edbbSJens Wiklander        factor = self._parse_factor(transform_m)
3419*c689edbbSJens Wiklander
3420*c689edbbSJens Wiklander        # Return 'factor' directly if we have a "single-operand" AND.
3421*c689edbbSJens Wiklander        # Otherwise, parse the right operand and make an AND node. This turns
3422*c689edbbSJens Wiklander        # A && B && C && D into (AND, A, (AND, B, (AND, C, D))).
3423*c689edbbSJens Wiklander        return factor if not self._check_token(_T_AND) else \
3424*c689edbbSJens Wiklander            (AND, factor, self._parse_and_expr(transform_m))
3425*c689edbbSJens Wiklander
3426*c689edbbSJens Wiklander    def _parse_factor(self, transform_m):
3427*c689edbbSJens Wiklander        token = self._tokens[self._tokens_i]
3428*c689edbbSJens Wiklander        self._tokens_i += 1
3429*c689edbbSJens Wiklander
3430*c689edbbSJens Wiklander        if token.__class__ is Symbol:
3431*c689edbbSJens Wiklander            # Plain symbol or relation
3432*c689edbbSJens Wiklander
3433*c689edbbSJens Wiklander            if self._tokens[self._tokens_i] not in _RELATIONS:
3434*c689edbbSJens Wiklander                # Plain symbol
3435*c689edbbSJens Wiklander
3436*c689edbbSJens Wiklander                # For conditional expressions ('depends on <expr>',
3437*c689edbbSJens Wiklander                # '... if <expr>', etc.), m is rewritten to m && MODULES.
3438*c689edbbSJens Wiklander                if transform_m and token is self.m:
3439*c689edbbSJens Wiklander                    return (AND, self.m, self.modules)
3440*c689edbbSJens Wiklander
3441*c689edbbSJens Wiklander                return token
3442*c689edbbSJens Wiklander
3443*c689edbbSJens Wiklander            # Relation
3444*c689edbbSJens Wiklander            #
3445*c689edbbSJens Wiklander            # _T_EQUAL, _T_UNEQUAL, etc., deliberately have the same values as
3446*c689edbbSJens Wiklander            # EQUAL, UNEQUAL, etc., so we can just use the token directly
3447*c689edbbSJens Wiklander            self._tokens_i += 1
3448*c689edbbSJens Wiklander            return (self._tokens[self._tokens_i - 1], token,
3449*c689edbbSJens Wiklander                    self._expect_sym())
3450*c689edbbSJens Wiklander
3451*c689edbbSJens Wiklander        if token is _T_NOT:
3452*c689edbbSJens Wiklander            # token == _T_NOT == NOT
3453*c689edbbSJens Wiklander            return (token, self._parse_factor(transform_m))
3454*c689edbbSJens Wiklander
3455*c689edbbSJens Wiklander        if token is _T_OPEN_PAREN:
3456*c689edbbSJens Wiklander            expr_parse = self._parse_expr(transform_m)
3457*c689edbbSJens Wiklander            if self._check_token(_T_CLOSE_PAREN):
3458*c689edbbSJens Wiklander                return expr_parse
3459*c689edbbSJens Wiklander
3460*c689edbbSJens Wiklander        self._parse_error("malformed expression")
3461*c689edbbSJens Wiklander
3462*c689edbbSJens Wiklander    #
3463*c689edbbSJens Wiklander    # Caching and invalidation
3464*c689edbbSJens Wiklander    #
3465*c689edbbSJens Wiklander
3466*c689edbbSJens Wiklander    def _build_dep(self):
3467*c689edbbSJens Wiklander        # Populates the Symbol/Choice._dependents sets, which contain all other
3468*c689edbbSJens Wiklander        # items (symbols and choices) that immediately depend on the item in
3469*c689edbbSJens Wiklander        # the sense that changing the value of the item might affect the value
3470*c689edbbSJens Wiklander        # of the dependent items. This is used for caching/invalidation.
3471*c689edbbSJens Wiklander        #
3472*c689edbbSJens Wiklander        # The calculated sets might be larger than necessary as we don't do any
3473*c689edbbSJens Wiklander        # complex analysis of the expressions.
3474*c689edbbSJens Wiklander
3475*c689edbbSJens Wiklander        depend_on = _depend_on  # Micro-optimization
3476*c689edbbSJens Wiklander
3477*c689edbbSJens Wiklander        # Only calculate _dependents for defined symbols. Constant and
3478*c689edbbSJens Wiklander        # undefined symbols could theoretically be selected/implied, but it
3479*c689edbbSJens Wiklander        # wouldn't change their value, so it's not a true dependency.
3480*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
3481*c689edbbSJens Wiklander            # Symbols depend on the following:
3482*c689edbbSJens Wiklander
3483*c689edbbSJens Wiklander            # The prompt conditions
3484*c689edbbSJens Wiklander            for node in sym.nodes:
3485*c689edbbSJens Wiklander                if node.prompt:
3486*c689edbbSJens Wiklander                    depend_on(sym, node.prompt[1])
3487*c689edbbSJens Wiklander
3488*c689edbbSJens Wiklander            # The default values and their conditions
3489*c689edbbSJens Wiklander            for value, cond in sym.defaults:
3490*c689edbbSJens Wiklander                depend_on(sym, value)
3491*c689edbbSJens Wiklander                depend_on(sym, cond)
3492*c689edbbSJens Wiklander
3493*c689edbbSJens Wiklander            # The reverse and weak reverse dependencies
3494*c689edbbSJens Wiklander            depend_on(sym, sym.rev_dep)
3495*c689edbbSJens Wiklander            depend_on(sym, sym.weak_rev_dep)
3496*c689edbbSJens Wiklander
3497*c689edbbSJens Wiklander            # The ranges along with their conditions
3498*c689edbbSJens Wiklander            for low, high, cond in sym.ranges:
3499*c689edbbSJens Wiklander                depend_on(sym, low)
3500*c689edbbSJens Wiklander                depend_on(sym, high)
3501*c689edbbSJens Wiklander                depend_on(sym, cond)
3502*c689edbbSJens Wiklander
3503*c689edbbSJens Wiklander            # The direct dependencies. This is usually redundant, as the direct
3504*c689edbbSJens Wiklander            # dependencies get propagated to properties, but it's needed to get
3505*c689edbbSJens Wiklander            # invalidation solid for 'imply', which only checks the direct
3506*c689edbbSJens Wiklander            # dependencies (even if there are no properties to propagate it
3507*c689edbbSJens Wiklander            # to).
3508*c689edbbSJens Wiklander            depend_on(sym, sym.direct_dep)
3509*c689edbbSJens Wiklander
3510*c689edbbSJens Wiklander            # In addition to the above, choice symbols depend on the choice
3511*c689edbbSJens Wiklander            # they're in, but that's handled automatically since the Choice is
3512*c689edbbSJens Wiklander            # propagated to the conditions of the properties before
3513*c689edbbSJens Wiklander            # _build_dep() runs.
3514*c689edbbSJens Wiklander
3515*c689edbbSJens Wiklander        for choice in self.unique_choices:
3516*c689edbbSJens Wiklander            # Choices depend on the following:
3517*c689edbbSJens Wiklander
3518*c689edbbSJens Wiklander            # The prompt conditions
3519*c689edbbSJens Wiklander            for node in choice.nodes:
3520*c689edbbSJens Wiklander                if node.prompt:
3521*c689edbbSJens Wiklander                    depend_on(choice, node.prompt[1])
3522*c689edbbSJens Wiklander
3523*c689edbbSJens Wiklander            # The default symbol conditions
3524*c689edbbSJens Wiklander            for _, cond in choice.defaults:
3525*c689edbbSJens Wiklander                depend_on(choice, cond)
3526*c689edbbSJens Wiklander
3527*c689edbbSJens Wiklander    def _add_choice_deps(self):
3528*c689edbbSJens Wiklander        # Choices also depend on the choice symbols themselves, because the
3529*c689edbbSJens Wiklander        # y-mode selection of the choice might change if a choice symbol's
3530*c689edbbSJens Wiklander        # visibility changes.
3531*c689edbbSJens Wiklander        #
3532*c689edbbSJens Wiklander        # We add these dependencies separately after dependency loop detection.
3533*c689edbbSJens Wiklander        # The invalidation algorithm can handle the resulting
3534*c689edbbSJens Wiklander        # <choice symbol> <-> <choice> dependency loops, but they make loop
3535*c689edbbSJens Wiklander        # detection awkward.
3536*c689edbbSJens Wiklander
3537*c689edbbSJens Wiklander        for choice in self.unique_choices:
3538*c689edbbSJens Wiklander            for sym in choice.syms:
3539*c689edbbSJens Wiklander                sym._dependents.add(choice)
3540*c689edbbSJens Wiklander
3541*c689edbbSJens Wiklander    def _invalidate_all(self):
3542*c689edbbSJens Wiklander        # Undefined symbols never change value and don't need to be
3543*c689edbbSJens Wiklander        # invalidated, so we can just iterate over defined symbols.
3544*c689edbbSJens Wiklander        # Invalidating constant symbols would break things horribly.
3545*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
3546*c689edbbSJens Wiklander            sym._invalidate()
3547*c689edbbSJens Wiklander
3548*c689edbbSJens Wiklander        for choice in self.unique_choices:
3549*c689edbbSJens Wiklander            choice._invalidate()
3550*c689edbbSJens Wiklander
3551*c689edbbSJens Wiklander    #
3552*c689edbbSJens Wiklander    # Post-parsing menu tree processing, including dependency propagation and
3553*c689edbbSJens Wiklander    # implicit submenu creation
3554*c689edbbSJens Wiklander    #
3555*c689edbbSJens Wiklander
3556*c689edbbSJens Wiklander    def _finalize_node(self, node, visible_if):
3557*c689edbbSJens Wiklander        # Finalizes a menu node and its children:
3558*c689edbbSJens Wiklander        #
3559*c689edbbSJens Wiklander        #  - Copies properties from menu nodes up to their contained
3560*c689edbbSJens Wiklander        #    symbols/choices
3561*c689edbbSJens Wiklander        #
3562*c689edbbSJens Wiklander        #  - Propagates dependencies from parent to child nodes
3563*c689edbbSJens Wiklander        #
3564*c689edbbSJens Wiklander        #  - Creates implicit menus (see kconfig-language.txt)
3565*c689edbbSJens Wiklander        #
3566*c689edbbSJens Wiklander        #  - Removes 'if' nodes
3567*c689edbbSJens Wiklander        #
3568*c689edbbSJens Wiklander        #  - Sets 'choice' types and registers choice symbols
3569*c689edbbSJens Wiklander        #
3570*c689edbbSJens Wiklander        # menu_finalize() in the C implementation is similar.
3571*c689edbbSJens Wiklander        #
3572*c689edbbSJens Wiklander        # node:
3573*c689edbbSJens Wiklander        #   The menu node to finalize. This node and its children will have
3574*c689edbbSJens Wiklander        #   been finalized when the function returns, and any implicit menus
3575*c689edbbSJens Wiklander        #   will have been created.
3576*c689edbbSJens Wiklander        #
3577*c689edbbSJens Wiklander        # visible_if:
3578*c689edbbSJens Wiklander        #   Dependencies from 'visible if' on parent menus. These are added to
3579*c689edbbSJens Wiklander        #   the prompts of symbols and choices.
3580*c689edbbSJens Wiklander
3581*c689edbbSJens Wiklander        if node.item.__class__ is Symbol:
3582*c689edbbSJens Wiklander            # Copy defaults, ranges, selects, and implies to the Symbol
3583*c689edbbSJens Wiklander            self._add_props_to_sym(node)
3584*c689edbbSJens Wiklander
3585*c689edbbSJens Wiklander            # Find any items that should go in an implicit menu rooted at the
3586*c689edbbSJens Wiklander            # symbol
3587*c689edbbSJens Wiklander            cur = node
3588*c689edbbSJens Wiklander            while cur.next and _auto_menu_dep(node, cur.next):
3589*c689edbbSJens Wiklander                # This makes implicit submenu creation work recursively, with
3590*c689edbbSJens Wiklander                # implicit menus inside implicit menus
3591*c689edbbSJens Wiklander                self._finalize_node(cur.next, visible_if)
3592*c689edbbSJens Wiklander                cur = cur.next
3593*c689edbbSJens Wiklander                cur.parent = node
3594*c689edbbSJens Wiklander
3595*c689edbbSJens Wiklander            if cur is not node:
3596*c689edbbSJens Wiklander                # Found symbols that should go in an implicit submenu. Tilt
3597*c689edbbSJens Wiklander                # them up above us.
3598*c689edbbSJens Wiklander                node.list = node.next
3599*c689edbbSJens Wiklander                node.next = cur.next
3600*c689edbbSJens Wiklander                cur.next = None
3601*c689edbbSJens Wiklander
3602*c689edbbSJens Wiklander        elif node.list:
3603*c689edbbSJens Wiklander            # The menu node is a choice, menu, or if. Finalize each child node.
3604*c689edbbSJens Wiklander
3605*c689edbbSJens Wiklander            if node.item is MENU:
3606*c689edbbSJens Wiklander                visible_if = self._make_and(visible_if, node.visibility)
3607*c689edbbSJens Wiklander
3608*c689edbbSJens Wiklander            # Propagate the menu node's dependencies to each child menu node.
3609*c689edbbSJens Wiklander            #
3610*c689edbbSJens Wiklander            # This needs to go before the recursive _finalize_node() call so
3611*c689edbbSJens Wiklander            # that implicit submenu creation can look ahead at dependencies.
3612*c689edbbSJens Wiklander            self._propagate_deps(node, visible_if)
3613*c689edbbSJens Wiklander
3614*c689edbbSJens Wiklander            # Finalize the children
3615*c689edbbSJens Wiklander            cur = node.list
3616*c689edbbSJens Wiklander            while cur:
3617*c689edbbSJens Wiklander                self._finalize_node(cur, visible_if)
3618*c689edbbSJens Wiklander                cur = cur.next
3619*c689edbbSJens Wiklander
3620*c689edbbSJens Wiklander        if node.list:
3621*c689edbbSJens Wiklander            # node's children have been individually finalized. Do final steps
3622*c689edbbSJens Wiklander            # to finalize this "level" in the menu tree.
3623*c689edbbSJens Wiklander            _flatten(node.list)
3624*c689edbbSJens Wiklander            _remove_ifs(node)
3625*c689edbbSJens Wiklander
3626*c689edbbSJens Wiklander        # Empty choices (node.list None) are possible, so this needs to go
3627*c689edbbSJens Wiklander        # outside
3628*c689edbbSJens Wiklander        if node.item.__class__ is Choice:
3629*c689edbbSJens Wiklander            # Add the node's non-node-specific properties to the choice, like
3630*c689edbbSJens Wiklander            # _add_props_to_sym() does
3631*c689edbbSJens Wiklander            choice = node.item
3632*c689edbbSJens Wiklander            choice.direct_dep = self._make_or(choice.direct_dep, node.dep)
3633*c689edbbSJens Wiklander            choice.defaults += node.defaults
3634*c689edbbSJens Wiklander
3635*c689edbbSJens Wiklander            _finalize_choice(node)
3636*c689edbbSJens Wiklander
3637*c689edbbSJens Wiklander    def _propagate_deps(self, node, visible_if):
3638*c689edbbSJens Wiklander        # Propagates 'node's dependencies to its child menu nodes
3639*c689edbbSJens Wiklander
3640*c689edbbSJens Wiklander        # If the parent node holds a Choice, we use the Choice itself as the
3641*c689edbbSJens Wiklander        # parent dependency. This makes sense as the value (mode) of the choice
3642*c689edbbSJens Wiklander        # limits the visibility of the contained choice symbols. The C
3643*c689edbbSJens Wiklander        # implementation works the same way.
3644*c689edbbSJens Wiklander        #
3645*c689edbbSJens Wiklander        # Due to the similar interface, Choice works as a drop-in replacement
3646*c689edbbSJens Wiklander        # for Symbol here.
3647*c689edbbSJens Wiklander        basedep = node.item if node.item.__class__ is Choice else node.dep
3648*c689edbbSJens Wiklander
3649*c689edbbSJens Wiklander        cur = node.list
3650*c689edbbSJens Wiklander        while cur:
3651*c689edbbSJens Wiklander            dep = cur.dep = self._make_and(cur.dep, basedep)
3652*c689edbbSJens Wiklander
3653*c689edbbSJens Wiklander            if cur.item.__class__ in _SYMBOL_CHOICE:
3654*c689edbbSJens Wiklander                # Propagate 'visible if' and dependencies to the prompt
3655*c689edbbSJens Wiklander                if cur.prompt:
3656*c689edbbSJens Wiklander                    cur.prompt = (cur.prompt[0],
3657*c689edbbSJens Wiklander                                  self._make_and(
3658*c689edbbSJens Wiklander                                      cur.prompt[1],
3659*c689edbbSJens Wiklander                                      self._make_and(visible_if, dep)))
3660*c689edbbSJens Wiklander
3661*c689edbbSJens Wiklander                # Propagate dependencies to defaults
3662*c689edbbSJens Wiklander                if cur.defaults:
3663*c689edbbSJens Wiklander                    cur.defaults = [(default, self._make_and(cond, dep))
3664*c689edbbSJens Wiklander                                    for default, cond in cur.defaults]
3665*c689edbbSJens Wiklander
3666*c689edbbSJens Wiklander                # Propagate dependencies to ranges
3667*c689edbbSJens Wiklander                if cur.ranges:
3668*c689edbbSJens Wiklander                    cur.ranges = [(low, high, self._make_and(cond, dep))
3669*c689edbbSJens Wiklander                                  for low, high, cond in cur.ranges]
3670*c689edbbSJens Wiklander
3671*c689edbbSJens Wiklander                # Propagate dependencies to selects
3672*c689edbbSJens Wiklander                if cur.selects:
3673*c689edbbSJens Wiklander                    cur.selects = [(target, self._make_and(cond, dep))
3674*c689edbbSJens Wiklander                                   for target, cond in cur.selects]
3675*c689edbbSJens Wiklander
3676*c689edbbSJens Wiklander                # Propagate dependencies to implies
3677*c689edbbSJens Wiklander                if cur.implies:
3678*c689edbbSJens Wiklander                    cur.implies = [(target, self._make_and(cond, dep))
3679*c689edbbSJens Wiklander                                   for target, cond in cur.implies]
3680*c689edbbSJens Wiklander
3681*c689edbbSJens Wiklander            elif cur.prompt:  # Not a symbol/choice
3682*c689edbbSJens Wiklander                # Propagate dependencies to the prompt. 'visible if' is only
3683*c689edbbSJens Wiklander                # propagated to symbols/choices.
3684*c689edbbSJens Wiklander                cur.prompt = (cur.prompt[0],
3685*c689edbbSJens Wiklander                              self._make_and(cur.prompt[1], dep))
3686*c689edbbSJens Wiklander
3687*c689edbbSJens Wiklander            cur = cur.next
3688*c689edbbSJens Wiklander
3689*c689edbbSJens Wiklander    def _add_props_to_sym(self, node):
3690*c689edbbSJens Wiklander        # Copies properties from the menu node 'node' up to its contained
3691*c689edbbSJens Wiklander        # symbol, and adds (weak) reverse dependencies to selected/implied
3692*c689edbbSJens Wiklander        # symbols.
3693*c689edbbSJens Wiklander        #
3694*c689edbbSJens Wiklander        # This can't be rolled into _propagate_deps(), because that function
3695*c689edbbSJens Wiklander        # traverses the menu tree roughly breadth-first, meaning properties on
3696*c689edbbSJens Wiklander        # symbols defined in multiple locations could end up in the wrong
3697*c689edbbSJens Wiklander        # order.
3698*c689edbbSJens Wiklander
3699*c689edbbSJens Wiklander        sym = node.item
3700*c689edbbSJens Wiklander
3701*c689edbbSJens Wiklander        # See the Symbol class docstring
3702*c689edbbSJens Wiklander        sym.direct_dep = self._make_or(sym.direct_dep, node.dep)
3703*c689edbbSJens Wiklander
3704*c689edbbSJens Wiklander        sym.defaults += node.defaults
3705*c689edbbSJens Wiklander        sym.ranges += node.ranges
3706*c689edbbSJens Wiklander        sym.selects += node.selects
3707*c689edbbSJens Wiklander        sym.implies += node.implies
3708*c689edbbSJens Wiklander
3709*c689edbbSJens Wiklander        # Modify the reverse dependencies of the selected symbol
3710*c689edbbSJens Wiklander        for target, cond in node.selects:
3711*c689edbbSJens Wiklander            target.rev_dep = self._make_or(
3712*c689edbbSJens Wiklander                target.rev_dep,
3713*c689edbbSJens Wiklander                self._make_and(sym, cond))
3714*c689edbbSJens Wiklander
3715*c689edbbSJens Wiklander        # Modify the weak reverse dependencies of the implied
3716*c689edbbSJens Wiklander        # symbol
3717*c689edbbSJens Wiklander        for target, cond in node.implies:
3718*c689edbbSJens Wiklander            target.weak_rev_dep = self._make_or(
3719*c689edbbSJens Wiklander                target.weak_rev_dep,
3720*c689edbbSJens Wiklander                self._make_and(sym, cond))
3721*c689edbbSJens Wiklander
3722*c689edbbSJens Wiklander    #
3723*c689edbbSJens Wiklander    # Misc.
3724*c689edbbSJens Wiklander    #
3725*c689edbbSJens Wiklander
3726*c689edbbSJens Wiklander    def _check_sym_sanity(self):
3727*c689edbbSJens Wiklander        # Checks various symbol properties that are handiest to check after
3728*c689edbbSJens Wiklander        # parsing. Only generates errors and warnings.
3729*c689edbbSJens Wiklander
3730*c689edbbSJens Wiklander        def num_ok(sym, type_):
3731*c689edbbSJens Wiklander            # Returns True if the (possibly constant) symbol 'sym' is valid as a value
3732*c689edbbSJens Wiklander            # for a symbol of type type_ (INT or HEX)
3733*c689edbbSJens Wiklander
3734*c689edbbSJens Wiklander            # 'not sym.nodes' implies a constant or undefined symbol, e.g. a plain
3735*c689edbbSJens Wiklander            # "123"
3736*c689edbbSJens Wiklander            if not sym.nodes:
3737*c689edbbSJens Wiklander                return _is_base_n(sym.name, _TYPE_TO_BASE[type_])
3738*c689edbbSJens Wiklander
3739*c689edbbSJens Wiklander            return sym.orig_type is type_
3740*c689edbbSJens Wiklander
3741*c689edbbSJens Wiklander        for sym in self.unique_defined_syms:
3742*c689edbbSJens Wiklander            if sym.orig_type in _BOOL_TRISTATE:
3743*c689edbbSJens Wiklander                # A helper function could be factored out here, but keep it
3744*c689edbbSJens Wiklander                # speedy/straightforward
3745*c689edbbSJens Wiklander
3746*c689edbbSJens Wiklander                for target_sym, _ in sym.selects:
3747*c689edbbSJens Wiklander                    if target_sym.orig_type not in _BOOL_TRISTATE_UNKNOWN:
3748*c689edbbSJens Wiklander                        self._warn("{} selects the {} symbol {}, which is not "
3749*c689edbbSJens Wiklander                                   "bool or tristate"
3750*c689edbbSJens Wiklander                                   .format(sym.name_and_loc,
3751*c689edbbSJens Wiklander                                           TYPE_TO_STR[target_sym.orig_type],
3752*c689edbbSJens Wiklander                                           target_sym.name_and_loc))
3753*c689edbbSJens Wiklander
3754*c689edbbSJens Wiklander                for target_sym, _ in sym.implies:
3755*c689edbbSJens Wiklander                    if target_sym.orig_type not in _BOOL_TRISTATE_UNKNOWN:
3756*c689edbbSJens Wiklander                        self._warn("{} implies the {} symbol {}, which is not "
3757*c689edbbSJens Wiklander                                   "bool or tristate"
3758*c689edbbSJens Wiklander                                   .format(sym.name_and_loc,
3759*c689edbbSJens Wiklander                                           TYPE_TO_STR[target_sym.orig_type],
3760*c689edbbSJens Wiklander                                           target_sym.name_and_loc))
3761*c689edbbSJens Wiklander
3762*c689edbbSJens Wiklander            elif sym.orig_type:  # STRING/INT/HEX
3763*c689edbbSJens Wiklander                for default, _ in sym.defaults:
3764*c689edbbSJens Wiklander                    if default.__class__ is not Symbol:
3765*c689edbbSJens Wiklander                        raise KconfigError(
3766*c689edbbSJens Wiklander                            "the {} symbol {} has a malformed default {} -- "
3767*c689edbbSJens Wiklander                            "expected a single symbol"
3768*c689edbbSJens Wiklander                            .format(TYPE_TO_STR[sym.orig_type],
3769*c689edbbSJens Wiklander                                    sym.name_and_loc, expr_str(default)))
3770*c689edbbSJens Wiklander
3771*c689edbbSJens Wiklander                    if sym.orig_type is STRING:
3772*c689edbbSJens Wiklander                        if not default.is_constant and not default.nodes and \
3773*c689edbbSJens Wiklander                           not default.name.isupper():
3774*c689edbbSJens Wiklander                            # 'default foo' on a string symbol could be either a symbol
3775*c689edbbSJens Wiklander                            # reference or someone leaving out the quotes. Guess that
3776*c689edbbSJens Wiklander                            # the quotes were left out if 'foo' isn't all-uppercase
3777*c689edbbSJens Wiklander                            # (and no symbol named 'foo' exists).
3778*c689edbbSJens Wiklander                            self._warn("style: quotes recommended around "
3779*c689edbbSJens Wiklander                                       "default value for string symbol "
3780*c689edbbSJens Wiklander                                       + sym.name_and_loc)
3781*c689edbbSJens Wiklander
3782*c689edbbSJens Wiklander                    elif not num_ok(default, sym.orig_type):  # INT/HEX
3783*c689edbbSJens Wiklander                        self._warn("the {0} symbol {1} has a non-{0} default {2}"
3784*c689edbbSJens Wiklander                                   .format(TYPE_TO_STR[sym.orig_type],
3785*c689edbbSJens Wiklander                                           sym.name_and_loc,
3786*c689edbbSJens Wiklander                                           default.name_and_loc))
3787*c689edbbSJens Wiklander
3788*c689edbbSJens Wiklander                if sym.selects or sym.implies:
3789*c689edbbSJens Wiklander                    self._warn("the {} symbol {} has selects or implies"
3790*c689edbbSJens Wiklander                               .format(TYPE_TO_STR[sym.orig_type],
3791*c689edbbSJens Wiklander                                       sym.name_and_loc))
3792*c689edbbSJens Wiklander
3793*c689edbbSJens Wiklander            else:  # UNKNOWN
3794*c689edbbSJens Wiklander                self._warn("{} defined without a type"
3795*c689edbbSJens Wiklander                           .format(sym.name_and_loc))
3796*c689edbbSJens Wiklander
3797*c689edbbSJens Wiklander
3798*c689edbbSJens Wiklander            if sym.ranges:
3799*c689edbbSJens Wiklander                if sym.orig_type not in _INT_HEX:
3800*c689edbbSJens Wiklander                    self._warn(
3801*c689edbbSJens Wiklander                        "the {} symbol {} has ranges, but is not int or hex"
3802*c689edbbSJens Wiklander                        .format(TYPE_TO_STR[sym.orig_type],
3803*c689edbbSJens Wiklander                                sym.name_and_loc))
3804*c689edbbSJens Wiklander                else:
3805*c689edbbSJens Wiklander                    for low, high, _ in sym.ranges:
3806*c689edbbSJens Wiklander                        if not num_ok(low, sym.orig_type) or \
3807*c689edbbSJens Wiklander                           not num_ok(high, sym.orig_type):
3808*c689edbbSJens Wiklander
3809*c689edbbSJens Wiklander                            self._warn("the {0} symbol {1} has a non-{0} "
3810*c689edbbSJens Wiklander                                       "range [{2}, {3}]"
3811*c689edbbSJens Wiklander                                       .format(TYPE_TO_STR[sym.orig_type],
3812*c689edbbSJens Wiklander                                               sym.name_and_loc,
3813*c689edbbSJens Wiklander                                               low.name_and_loc,
3814*c689edbbSJens Wiklander                                               high.name_and_loc))
3815*c689edbbSJens Wiklander
3816*c689edbbSJens Wiklander    def _check_choice_sanity(self):
3817*c689edbbSJens Wiklander        # Checks various choice properties that are handiest to check after
3818*c689edbbSJens Wiklander        # parsing. Only generates errors and warnings.
3819*c689edbbSJens Wiklander
3820*c689edbbSJens Wiklander        def warn_select_imply(sym, expr, expr_type):
3821*c689edbbSJens Wiklander            msg = "the choice symbol {} is {} by the following symbols, but " \
3822*c689edbbSJens Wiklander                  "select/imply has no effect on choice symbols" \
3823*c689edbbSJens Wiklander                  .format(sym.name_and_loc, expr_type)
3824*c689edbbSJens Wiklander
3825*c689edbbSJens Wiklander            # si = select/imply
3826*c689edbbSJens Wiklander            for si in split_expr(expr, OR):
3827*c689edbbSJens Wiklander                msg += "\n - " + split_expr(si, AND)[0].name_and_loc
3828*c689edbbSJens Wiklander
3829*c689edbbSJens Wiklander            self._warn(msg)
3830*c689edbbSJens Wiklander
3831*c689edbbSJens Wiklander        for choice in self.unique_choices:
3832*c689edbbSJens Wiklander            if choice.orig_type not in _BOOL_TRISTATE:
3833*c689edbbSJens Wiklander                self._warn("{} defined with type {}"
3834*c689edbbSJens Wiklander                           .format(choice.name_and_loc,
3835*c689edbbSJens Wiklander                                   TYPE_TO_STR[choice.orig_type]))
3836*c689edbbSJens Wiklander
3837*c689edbbSJens Wiklander            for node in choice.nodes:
3838*c689edbbSJens Wiklander                if node.prompt:
3839*c689edbbSJens Wiklander                    break
3840*c689edbbSJens Wiklander            else:
3841*c689edbbSJens Wiklander                self._warn(choice.name_and_loc + " defined without a prompt")
3842*c689edbbSJens Wiklander
3843*c689edbbSJens Wiklander            for default, _ in choice.defaults:
3844*c689edbbSJens Wiklander                if default.__class__ is not Symbol:
3845*c689edbbSJens Wiklander                    raise KconfigError(
3846*c689edbbSJens Wiklander                        "{} has a malformed default {}"
3847*c689edbbSJens Wiklander                        .format(choice.name_and_loc, expr_str(default)))
3848*c689edbbSJens Wiklander
3849*c689edbbSJens Wiklander                if default.choice is not choice:
3850*c689edbbSJens Wiklander                    self._warn("the default selection {} of {} is not "
3851*c689edbbSJens Wiklander                               "contained in the choice"
3852*c689edbbSJens Wiklander                               .format(default.name_and_loc,
3853*c689edbbSJens Wiklander                                       choice.name_and_loc))
3854*c689edbbSJens Wiklander
3855*c689edbbSJens Wiklander            for sym in choice.syms:
3856*c689edbbSJens Wiklander                if sym.defaults:
3857*c689edbbSJens Wiklander                    self._warn("default on the choice symbol {} will have "
3858*c689edbbSJens Wiklander                               "no effect, as defaults do not affect choice "
3859*c689edbbSJens Wiklander                               "symbols".format(sym.name_and_loc))
3860*c689edbbSJens Wiklander
3861*c689edbbSJens Wiklander                if sym.rev_dep is not sym.kconfig.n:
3862*c689edbbSJens Wiklander                    warn_select_imply(sym, sym.rev_dep, "selected")
3863*c689edbbSJens Wiklander
3864*c689edbbSJens Wiklander                if sym.weak_rev_dep is not sym.kconfig.n:
3865*c689edbbSJens Wiklander                    warn_select_imply(sym, sym.weak_rev_dep, "implied")
3866*c689edbbSJens Wiklander
3867*c689edbbSJens Wiklander                for node in sym.nodes:
3868*c689edbbSJens Wiklander                    if node.parent.item is choice:
3869*c689edbbSJens Wiklander                        if not node.prompt:
3870*c689edbbSJens Wiklander                            self._warn("the choice symbol {} has no prompt"
3871*c689edbbSJens Wiklander                                       .format(sym.name_and_loc))
3872*c689edbbSJens Wiklander
3873*c689edbbSJens Wiklander                    elif node.prompt:
3874*c689edbbSJens Wiklander                        self._warn("the choice symbol {} is defined with a "
3875*c689edbbSJens Wiklander                                   "prompt outside the choice"
3876*c689edbbSJens Wiklander                                   .format(sym.name_and_loc))
3877*c689edbbSJens Wiklander
3878*c689edbbSJens Wiklander    def _parse_error(self, msg):
3879*c689edbbSJens Wiklander        raise KconfigError("{}error: couldn't parse '{}': {}".format(
3880*c689edbbSJens Wiklander            "" if self.filename is None else
3881*c689edbbSJens Wiklander                "{}:{}: ".format(self.filename, self.linenr),
3882*c689edbbSJens Wiklander            self._line.strip(), msg))
3883*c689edbbSJens Wiklander
3884*c689edbbSJens Wiklander    def _trailing_tokens_error(self):
3885*c689edbbSJens Wiklander        self._parse_error("extra tokens at end of line")
3886*c689edbbSJens Wiklander
3887*c689edbbSJens Wiklander    def _open(self, filename, mode):
3888*c689edbbSJens Wiklander        # open() wrapper:
3889*c689edbbSJens Wiklander        #
3890*c689edbbSJens Wiklander        # - Enable universal newlines mode on Python 2 to ease
3891*c689edbbSJens Wiklander        #   interoperability between Linux and Windows. It's already the
3892*c689edbbSJens Wiklander        #   default on Python 3.
3893*c689edbbSJens Wiklander        #
3894*c689edbbSJens Wiklander        #   The "U" flag would currently work for both Python 2 and 3, but it's
3895*c689edbbSJens Wiklander        #   deprecated on Python 3, so play it future-safe.
3896*c689edbbSJens Wiklander        #
3897*c689edbbSJens Wiklander        #   io.open() defaults to universal newlines on Python 2 (and is an
3898*c689edbbSJens Wiklander        #   alias for open() on Python 3), but it returns 'unicode' strings and
3899*c689edbbSJens Wiklander        #   slows things down:
3900*c689edbbSJens Wiklander        #
3901*c689edbbSJens Wiklander        #     Parsing x86 Kconfigs on Python 2
3902*c689edbbSJens Wiklander        #
3903*c689edbbSJens Wiklander        #     with open(..., "rU"):
3904*c689edbbSJens Wiklander        #
3905*c689edbbSJens Wiklander        #       real  0m0.930s
3906*c689edbbSJens Wiklander        #       user  0m0.905s
3907*c689edbbSJens Wiklander        #       sys   0m0.025s
3908*c689edbbSJens Wiklander        #
3909*c689edbbSJens Wiklander        #     with io.open():
3910*c689edbbSJens Wiklander        #
3911*c689edbbSJens Wiklander        #       real  0m1.069s
3912*c689edbbSJens Wiklander        #       user  0m1.040s
3913*c689edbbSJens Wiklander        #       sys   0m0.029s
3914*c689edbbSJens Wiklander        #
3915*c689edbbSJens Wiklander        #   There's no appreciable performance difference between "r" and
3916*c689edbbSJens Wiklander        #   "rU" for parsing performance on Python 2.
3917*c689edbbSJens Wiklander        #
3918*c689edbbSJens Wiklander        # - For Python 3, force the encoding. Forcing the encoding on Python 2
3919*c689edbbSJens Wiklander        #   turns strings into Unicode strings, which gets messy. Python 2
3920*c689edbbSJens Wiklander        #   doesn't decode regular strings anyway.
3921*c689edbbSJens Wiklander        return open(filename, "rU" if mode == "r" else mode) if _IS_PY2 else \
3922*c689edbbSJens Wiklander               open(filename, mode, encoding=self._encoding)
3923*c689edbbSJens Wiklander
3924*c689edbbSJens Wiklander    def _check_undef_syms(self):
3925*c689edbbSJens Wiklander        # Prints warnings for all references to undefined symbols within the
3926*c689edbbSJens Wiklander        # Kconfig files
3927*c689edbbSJens Wiklander
3928*c689edbbSJens Wiklander        def is_num(s):
3929*c689edbbSJens Wiklander            # Returns True if the string 's' looks like a number.
3930*c689edbbSJens Wiklander            #
3931*c689edbbSJens Wiklander            # Internally, all operands in Kconfig are symbols, only undefined symbols
3932*c689edbbSJens Wiklander            # (which numbers usually are) get their name as their value.
3933*c689edbbSJens Wiklander            #
3934*c689edbbSJens Wiklander            # Only hex numbers that start with 0x/0X are classified as numbers.
3935*c689edbbSJens Wiklander            # Otherwise, symbols whose names happen to contain only the letters A-F
3936*c689edbbSJens Wiklander            # would trigger false positives.
3937*c689edbbSJens Wiklander
3938*c689edbbSJens Wiklander            try:
3939*c689edbbSJens Wiklander                int(s)
3940*c689edbbSJens Wiklander            except ValueError:
3941*c689edbbSJens Wiklander                if not s.startswith(("0x", "0X")):
3942*c689edbbSJens Wiklander                    return False
3943*c689edbbSJens Wiklander
3944*c689edbbSJens Wiklander                try:
3945*c689edbbSJens Wiklander                    int(s, 16)
3946*c689edbbSJens Wiklander                except ValueError:
3947*c689edbbSJens Wiklander                    return False
3948*c689edbbSJens Wiklander
3949*c689edbbSJens Wiklander            return True
3950*c689edbbSJens Wiklander
3951*c689edbbSJens Wiklander        for sym in (self.syms.viewvalues if _IS_PY2 else self.syms.values)():
3952*c689edbbSJens Wiklander            # - sym.nodes empty means the symbol is undefined (has no
3953*c689edbbSJens Wiklander            #   definition locations)
3954*c689edbbSJens Wiklander            #
3955*c689edbbSJens Wiklander            # - Due to Kconfig internals, numbers show up as undefined Kconfig
3956*c689edbbSJens Wiklander            #   symbols, but shouldn't be flagged
3957*c689edbbSJens Wiklander            #
3958*c689edbbSJens Wiklander            # - The MODULES symbol always exists
3959*c689edbbSJens Wiklander            if not sym.nodes and not is_num(sym.name) and \
3960*c689edbbSJens Wiklander               sym.name != "MODULES":
3961*c689edbbSJens Wiklander
3962*c689edbbSJens Wiklander                msg = "undefined symbol {}:".format(sym.name)
3963*c689edbbSJens Wiklander                for node in self.node_iter():
3964*c689edbbSJens Wiklander                    if sym in node.referenced:
3965*c689edbbSJens Wiklander                        msg += "\n\n- Referenced at {}:{}:\n\n{}" \
3966*c689edbbSJens Wiklander                               .format(node.filename, node.linenr, node)
3967*c689edbbSJens Wiklander                self._warn(msg)
3968*c689edbbSJens Wiklander
3969*c689edbbSJens Wiklander    def _warn(self, msg, filename=None, linenr=None):
3970*c689edbbSJens Wiklander        # For printing general warnings
3971*c689edbbSJens Wiklander
3972*c689edbbSJens Wiklander        if not self.warn:
3973*c689edbbSJens Wiklander            return
3974*c689edbbSJens Wiklander
3975*c689edbbSJens Wiklander        msg = "warning: " + msg
3976*c689edbbSJens Wiklander        if filename is not None:
3977*c689edbbSJens Wiklander            msg = "{}:{}: {}".format(filename, linenr, msg)
3978*c689edbbSJens Wiklander
3979*c689edbbSJens Wiklander        self.warnings.append(msg)
3980*c689edbbSJens Wiklander        if self.warn_to_stderr:
3981*c689edbbSJens Wiklander            sys.stderr.write(msg + "\n")
3982*c689edbbSJens Wiklander
3983*c689edbbSJens Wiklander
3984*c689edbbSJens Wiklanderclass Symbol(object):
3985*c689edbbSJens Wiklander    """
3986*c689edbbSJens Wiklander    Represents a configuration symbol:
3987*c689edbbSJens Wiklander
3988*c689edbbSJens Wiklander      (menu)config FOO
3989*c689edbbSJens Wiklander          ...
3990*c689edbbSJens Wiklander
3991*c689edbbSJens Wiklander    The following attributes are available. They should be viewed as read-only,
3992*c689edbbSJens Wiklander    and some are implemented through @property magic (but are still efficient
3993*c689edbbSJens Wiklander    to access due to internal caching).
3994*c689edbbSJens Wiklander
3995*c689edbbSJens Wiklander    Note: Prompts, help texts, and locations are stored in the Symbol's
3996*c689edbbSJens Wiklander    MenuNode(s) rather than in the Symbol itself. Check the MenuNode class and
3997*c689edbbSJens Wiklander    the Symbol.nodes attribute. This organization matches the C tools.
3998*c689edbbSJens Wiklander
3999*c689edbbSJens Wiklander    name:
4000*c689edbbSJens Wiklander      The name of the symbol, e.g. "FOO" for 'config FOO'.
4001*c689edbbSJens Wiklander
4002*c689edbbSJens Wiklander    type:
4003*c689edbbSJens Wiklander      The type of the symbol. One of BOOL, TRISTATE, STRING, INT, HEX, UNKNOWN.
4004*c689edbbSJens Wiklander      UNKNOWN is for undefined symbols, (non-special) constant symbols, and
4005*c689edbbSJens Wiklander      symbols defined without a type.
4006*c689edbbSJens Wiklander
4007*c689edbbSJens Wiklander      When running without modules (MODULES having the value n), TRISTATE
4008*c689edbbSJens Wiklander      symbols magically change type to BOOL. This also happens for symbols
4009*c689edbbSJens Wiklander      within choices in "y" mode. This matches the C tools, and makes sense for
4010*c689edbbSJens Wiklander      menuconfig-like functionality.
4011*c689edbbSJens Wiklander
4012*c689edbbSJens Wiklander    orig_type:
4013*c689edbbSJens Wiklander      The type as given in the Kconfig file, without any magic applied. Used
4014*c689edbbSJens Wiklander      when printing the symbol.
4015*c689edbbSJens Wiklander
4016*c689edbbSJens Wiklander    tri_value:
4017*c689edbbSJens Wiklander      The tristate value of the symbol as an integer. One of 0, 1, 2,
4018*c689edbbSJens Wiklander      representing n, m, y. Always 0 (n) for non-bool/tristate symbols.
4019*c689edbbSJens Wiklander
4020*c689edbbSJens Wiklander      This is the symbol value that's used outside of relation expressions
4021*c689edbbSJens Wiklander      (A, !A, A && B, A || B).
4022*c689edbbSJens Wiklander
4023*c689edbbSJens Wiklander    str_value:
4024*c689edbbSJens Wiklander      The value of the symbol as a string. Gives the value for string/int/hex
4025*c689edbbSJens Wiklander      symbols. For bool/tristate symbols, gives "n", "m", or "y".
4026*c689edbbSJens Wiklander
4027*c689edbbSJens Wiklander      This is the symbol value that's used in relational expressions
4028*c689edbbSJens Wiklander      (A = B, A != B, etc.)
4029*c689edbbSJens Wiklander
4030*c689edbbSJens Wiklander      Gotcha: For int/hex symbols, the exact format of the value is often
4031*c689edbbSJens Wiklander      preserved (e.g. when writing a .config file), hence why you can't get it
4032*c689edbbSJens Wiklander      directly as an int. Do int(int_sym.str_value) or
4033*c689edbbSJens Wiklander      int(hex_sym.str_value, 16) to get the integer value.
4034*c689edbbSJens Wiklander
4035*c689edbbSJens Wiklander    user_value:
4036*c689edbbSJens Wiklander      The user value of the symbol. None if no user value has been assigned
4037*c689edbbSJens Wiklander      (via Kconfig.load_config() or Symbol.set_value()).
4038*c689edbbSJens Wiklander
4039*c689edbbSJens Wiklander      Holds 0, 1, or 2 for bool/tristate symbols, and a string for the other
4040*c689edbbSJens Wiklander      symbol types.
4041*c689edbbSJens Wiklander
4042*c689edbbSJens Wiklander      WARNING: Do not assign directly to this. It will break things. Use
4043*c689edbbSJens Wiklander      Symbol.set_value().
4044*c689edbbSJens Wiklander
4045*c689edbbSJens Wiklander    assignable:
4046*c689edbbSJens Wiklander      A tuple containing the tristate user values that can currently be
4047*c689edbbSJens Wiklander      assigned to the symbol (that would be respected), ordered from lowest (0,
4048*c689edbbSJens Wiklander      representing n) to highest (2, representing y). This corresponds to the
4049*c689edbbSJens Wiklander      selections available in the menuconfig interface. The set of assignable
4050*c689edbbSJens Wiklander      values is calculated from the symbol's visibility and selects/implies.
4051*c689edbbSJens Wiklander
4052*c689edbbSJens Wiklander      Returns the empty set for non-bool/tristate symbols and for symbols with
4053*c689edbbSJens Wiklander      visibility n. The other possible values are (0, 2), (0, 1, 2), (1, 2),
4054*c689edbbSJens Wiklander      (1,), and (2,). A (1,) or (2,) result means the symbol is visible but
4055*c689edbbSJens Wiklander      "locked" to m or y through a select, perhaps in combination with the
4056*c689edbbSJens Wiklander      visibility. menuconfig represents this as -M- and -*-, respectively.
4057*c689edbbSJens Wiklander
4058*c689edbbSJens Wiklander      For string/hex/int symbols, check if Symbol.visibility is non-0 (non-n)
4059*c689edbbSJens Wiklander      instead to determine if the value can be changed.
4060*c689edbbSJens Wiklander
4061*c689edbbSJens Wiklander      Some handy 'assignable' idioms:
4062*c689edbbSJens Wiklander
4063*c689edbbSJens Wiklander        # Is 'sym' an assignable (visible) bool/tristate symbol?
4064*c689edbbSJens Wiklander        if sym.assignable:
4065*c689edbbSJens Wiklander            # What's the highest value it can be assigned? [-1] in Python
4066*c689edbbSJens Wiklander            # gives the last element.
4067*c689edbbSJens Wiklander            sym_high = sym.assignable[-1]
4068*c689edbbSJens Wiklander
4069*c689edbbSJens Wiklander            # The lowest?
4070*c689edbbSJens Wiklander            sym_low = sym.assignable[0]
4071*c689edbbSJens Wiklander
4072*c689edbbSJens Wiklander            # Can the symbol be set to at least m?
4073*c689edbbSJens Wiklander            if sym.assignable[-1] >= 1:
4074*c689edbbSJens Wiklander                ...
4075*c689edbbSJens Wiklander
4076*c689edbbSJens Wiklander        # Can the symbol be set to m?
4077*c689edbbSJens Wiklander        if 1 in sym.assignable:
4078*c689edbbSJens Wiklander            ...
4079*c689edbbSJens Wiklander
4080*c689edbbSJens Wiklander    visibility:
4081*c689edbbSJens Wiklander      The visibility of the symbol. One of 0, 1, 2, representing n, m, y. See
4082*c689edbbSJens Wiklander      the module documentation for an overview of symbol values and visibility.
4083*c689edbbSJens Wiklander
4084*c689edbbSJens Wiklander    config_string:
4085*c689edbbSJens Wiklander      The .config assignment string that would get written out for the symbol
4086*c689edbbSJens Wiklander      by Kconfig.write_config(). Returns the empty string if no .config
4087*c689edbbSJens Wiklander      assignment would get written out.
4088*c689edbbSJens Wiklander
4089*c689edbbSJens Wiklander      In general, visible symbols, symbols with (active) defaults, and selected
4090*c689edbbSJens Wiklander      symbols get written out. This includes all non-n-valued bool/tristate
4091*c689edbbSJens Wiklander      symbols, and all visible string/int/hex symbols.
4092*c689edbbSJens Wiklander
4093*c689edbbSJens Wiklander      Symbols with the (no longer needed) 'option env=...' option generate no
4094*c689edbbSJens Wiklander      configuration output, and neither does the special
4095*c689edbbSJens Wiklander      'option defconfig_list' symbol.
4096*c689edbbSJens Wiklander
4097*c689edbbSJens Wiklander      Tip: This field is useful when generating custom configuration output,
4098*c689edbbSJens Wiklander      even for non-.config-like formats. To write just the symbols that would
4099*c689edbbSJens Wiklander      get written out to .config files, do this:
4100*c689edbbSJens Wiklander
4101*c689edbbSJens Wiklander        if sym.config_string:
4102*c689edbbSJens Wiklander            *Write symbol, e.g. by looking sym.str_value*
4103*c689edbbSJens Wiklander
4104*c689edbbSJens Wiklander      This is a superset of the symbols written out by write_autoconf().
4105*c689edbbSJens Wiklander      That function skips all n-valued symbols.
4106*c689edbbSJens Wiklander
4107*c689edbbSJens Wiklander      There usually won't be any great harm in just writing all symbols either,
4108*c689edbbSJens Wiklander      though you might get some special symbols and possibly some "redundant"
4109*c689edbbSJens Wiklander      n-valued symbol entries in there.
4110*c689edbbSJens Wiklander
4111*c689edbbSJens Wiklander    name_and_loc:
4112*c689edbbSJens Wiklander      Holds a string like
4113*c689edbbSJens Wiklander
4114*c689edbbSJens Wiklander        "MY_SYMBOL (defined at foo/Kconfig:12, bar/Kconfig:14)"
4115*c689edbbSJens Wiklander
4116*c689edbbSJens Wiklander      , giving the name of the symbol and its definition location(s).
4117*c689edbbSJens Wiklander
4118*c689edbbSJens Wiklander      If the symbol is undefined, the location is given as "(undefined)".
4119*c689edbbSJens Wiklander
4120*c689edbbSJens Wiklander    nodes:
4121*c689edbbSJens Wiklander      A list of MenuNodes for this symbol. Will contain a single MenuNode for
4122*c689edbbSJens Wiklander      most symbols. Undefined and constant symbols have an empty nodes list.
4123*c689edbbSJens Wiklander      Symbols defined in multiple locations get one node for each location.
4124*c689edbbSJens Wiklander
4125*c689edbbSJens Wiklander    choice:
4126*c689edbbSJens Wiklander      Holds the parent Choice for choice symbols, and None for non-choice
4127*c689edbbSJens Wiklander      symbols. Doubles as a flag for whether a symbol is a choice symbol.
4128*c689edbbSJens Wiklander
4129*c689edbbSJens Wiklander    defaults:
4130*c689edbbSJens Wiklander      List of (default, cond) tuples for the symbol's 'default' properties. For
4131*c689edbbSJens Wiklander      example, 'default A && B if C || D' is represented as
4132*c689edbbSJens Wiklander      ((AND, A, B), (OR, C, D)). If no condition was given, 'cond' is
4133*c689edbbSJens Wiklander      self.kconfig.y.
4134*c689edbbSJens Wiklander
4135*c689edbbSJens Wiklander      Note that 'depends on' and parent dependencies are propagated to
4136*c689edbbSJens Wiklander      'default' conditions.
4137*c689edbbSJens Wiklander
4138*c689edbbSJens Wiklander    selects:
4139*c689edbbSJens Wiklander      List of (symbol, cond) tuples for the symbol's 'select' properties. For
4140*c689edbbSJens Wiklander      example, 'select A if B && C' is represented as (A, (AND, B, C)). If no
4141*c689edbbSJens Wiklander      condition was given, 'cond' is self.kconfig.y.
4142*c689edbbSJens Wiklander
4143*c689edbbSJens Wiklander      Note that 'depends on' and parent dependencies are propagated to 'select'
4144*c689edbbSJens Wiklander      conditions.
4145*c689edbbSJens Wiklander
4146*c689edbbSJens Wiklander    implies:
4147*c689edbbSJens Wiklander      Like 'selects', for imply.
4148*c689edbbSJens Wiklander
4149*c689edbbSJens Wiklander    ranges:
4150*c689edbbSJens Wiklander      List of (low, high, cond) tuples for the symbol's 'range' properties. For
4151*c689edbbSJens Wiklander      example, 'range 1 2 if A' is represented as (1, 2, A). If there is no
4152*c689edbbSJens Wiklander      condition, 'cond' is self.kconfig.y.
4153*c689edbbSJens Wiklander
4154*c689edbbSJens Wiklander      Note that 'depends on' and parent dependencies are propagated to 'range'
4155*c689edbbSJens Wiklander      conditions.
4156*c689edbbSJens Wiklander
4157*c689edbbSJens Wiklander      Gotcha: 1 and 2 above will be represented as (undefined) Symbols rather
4158*c689edbbSJens Wiklander      than plain integers. Undefined symbols get their name as their string
4159*c689edbbSJens Wiklander      value, so this works out. The C tools work the same way.
4160*c689edbbSJens Wiklander
4161*c689edbbSJens Wiklander    orig_defaults:
4162*c689edbbSJens Wiklander    orig_selects:
4163*c689edbbSJens Wiklander    orig_implies:
4164*c689edbbSJens Wiklander    orig_ranges:
4165*c689edbbSJens Wiklander      See the corresponding attributes on the MenuNode class.
4166*c689edbbSJens Wiklander
4167*c689edbbSJens Wiklander    rev_dep:
4168*c689edbbSJens Wiklander      Reverse dependency expression from other symbols selecting this symbol.
4169*c689edbbSJens Wiklander      Multiple selections get ORed together. A condition on a select is ANDed
4170*c689edbbSJens Wiklander      with the selecting symbol.
4171*c689edbbSJens Wiklander
4172*c689edbbSJens Wiklander      For example, if A has 'select FOO' and B has 'select FOO if C', then
4173*c689edbbSJens Wiklander      FOO's rev_dep will be (OR, A, (AND, B, C)).
4174*c689edbbSJens Wiklander
4175*c689edbbSJens Wiklander    weak_rev_dep:
4176*c689edbbSJens Wiklander      Like rev_dep, for imply.
4177*c689edbbSJens Wiklander
4178*c689edbbSJens Wiklander    direct_dep:
4179*c689edbbSJens Wiklander      The direct ('depends on') dependencies for the symbol, or self.kconfig.y
4180*c689edbbSJens Wiklander      if there are no direct dependencies.
4181*c689edbbSJens Wiklander
4182*c689edbbSJens Wiklander      This attribute includes any dependencies from surrounding menus and ifs.
4183*c689edbbSJens Wiklander      Those get propagated to the direct dependencies, and the resulting direct
4184*c689edbbSJens Wiklander      dependencies in turn get propagated to the conditions of all properties.
4185*c689edbbSJens Wiklander
4186*c689edbbSJens Wiklander      If the symbol is defined in multiple locations, the dependencies from the
4187*c689edbbSJens Wiklander      different locations get ORed together.
4188*c689edbbSJens Wiklander
4189*c689edbbSJens Wiklander    referenced:
4190*c689edbbSJens Wiklander      A set() with all symbols and choices referenced in the properties and
4191*c689edbbSJens Wiklander      property conditions of the symbol.
4192*c689edbbSJens Wiklander
4193*c689edbbSJens Wiklander      Also includes dependencies from surrounding menus and ifs, because those
4194*c689edbbSJens Wiklander      get propagated to the symbol (see the 'Intro to symbol values' section in
4195*c689edbbSJens Wiklander      the module docstring).
4196*c689edbbSJens Wiklander
4197*c689edbbSJens Wiklander      Choices appear in the dependencies of choice symbols.
4198*c689edbbSJens Wiklander
4199*c689edbbSJens Wiklander      For the following definitions, only B and not C appears in A's
4200*c689edbbSJens Wiklander      'referenced'. To get transitive references, you'll have to recursively
4201*c689edbbSJens Wiklander      expand 'references' until no new items appear.
4202*c689edbbSJens Wiklander
4203*c689edbbSJens Wiklander        config A
4204*c689edbbSJens Wiklander                bool
4205*c689edbbSJens Wiklander                depends on B
4206*c689edbbSJens Wiklander
4207*c689edbbSJens Wiklander        config B
4208*c689edbbSJens Wiklander                bool
4209*c689edbbSJens Wiklander                depends on C
4210*c689edbbSJens Wiklander
4211*c689edbbSJens Wiklander        config C
4212*c689edbbSJens Wiklander                bool
4213*c689edbbSJens Wiklander
4214*c689edbbSJens Wiklander      See the Symbol.direct_dep attribute if you're only interested in the
4215*c689edbbSJens Wiklander      direct dependencies of the symbol (its 'depends on'). You can extract the
4216*c689edbbSJens Wiklander      symbols in it with the global expr_items() function.
4217*c689edbbSJens Wiklander
4218*c689edbbSJens Wiklander    env_var:
4219*c689edbbSJens Wiklander      If the Symbol has an 'option env="FOO"' option, this contains the name
4220*c689edbbSJens Wiklander      ("FOO") of the environment variable. None for symbols without no
4221*c689edbbSJens Wiklander      'option env'.
4222*c689edbbSJens Wiklander
4223*c689edbbSJens Wiklander      'option env="FOO"' acts like a 'default' property whose value is the
4224*c689edbbSJens Wiklander      value of $FOO.
4225*c689edbbSJens Wiklander
4226*c689edbbSJens Wiklander      Symbols with 'option env' are never written out to .config files, even if
4227*c689edbbSJens Wiklander      they are visible. env_var corresponds to a flag called SYMBOL_AUTO in the
4228*c689edbbSJens Wiklander      C implementation.
4229*c689edbbSJens Wiklander
4230*c689edbbSJens Wiklander    is_allnoconfig_y:
4231*c689edbbSJens Wiklander      True if the symbol has 'option allnoconfig_y' set on it. This has no
4232*c689edbbSJens Wiklander      effect internally (except when printing symbols), but can be checked by
4233*c689edbbSJens Wiklander      scripts.
4234*c689edbbSJens Wiklander
4235*c689edbbSJens Wiklander    is_constant:
4236*c689edbbSJens Wiklander      True if the symbol is a constant (quoted) symbol.
4237*c689edbbSJens Wiklander
4238*c689edbbSJens Wiklander    kconfig:
4239*c689edbbSJens Wiklander      The Kconfig instance this symbol is from.
4240*c689edbbSJens Wiklander    """
4241*c689edbbSJens Wiklander    __slots__ = (
4242*c689edbbSJens Wiklander        "_cached_assignable",
4243*c689edbbSJens Wiklander        "_cached_str_val",
4244*c689edbbSJens Wiklander        "_cached_tri_val",
4245*c689edbbSJens Wiklander        "_cached_vis",
4246*c689edbbSJens Wiklander        "_dependents",
4247*c689edbbSJens Wiklander        "_old_val",
4248*c689edbbSJens Wiklander        "_visited",
4249*c689edbbSJens Wiklander        "_was_set",
4250*c689edbbSJens Wiklander        "_write_to_conf",
4251*c689edbbSJens Wiklander        "choice",
4252*c689edbbSJens Wiklander        "defaults",
4253*c689edbbSJens Wiklander        "direct_dep",
4254*c689edbbSJens Wiklander        "env_var",
4255*c689edbbSJens Wiklander        "implies",
4256*c689edbbSJens Wiklander        "is_allnoconfig_y",
4257*c689edbbSJens Wiklander        "is_constant",
4258*c689edbbSJens Wiklander        "kconfig",
4259*c689edbbSJens Wiklander        "name",
4260*c689edbbSJens Wiklander        "nodes",
4261*c689edbbSJens Wiklander        "orig_type",
4262*c689edbbSJens Wiklander        "ranges",
4263*c689edbbSJens Wiklander        "rev_dep",
4264*c689edbbSJens Wiklander        "selects",
4265*c689edbbSJens Wiklander        "user_value",
4266*c689edbbSJens Wiklander        "weak_rev_dep",
4267*c689edbbSJens Wiklander    )
4268*c689edbbSJens Wiklander
4269*c689edbbSJens Wiklander    #
4270*c689edbbSJens Wiklander    # Public interface
4271*c689edbbSJens Wiklander    #
4272*c689edbbSJens Wiklander
4273*c689edbbSJens Wiklander    @property
4274*c689edbbSJens Wiklander    def type(self):
4275*c689edbbSJens Wiklander        """
4276*c689edbbSJens Wiklander        See the class documentation.
4277*c689edbbSJens Wiklander        """
4278*c689edbbSJens Wiklander        if self.orig_type is TRISTATE and \
4279*c689edbbSJens Wiklander           (self.choice and self.choice.tri_value == 2 or
4280*c689edbbSJens Wiklander            not self.kconfig.modules.tri_value):
4281*c689edbbSJens Wiklander
4282*c689edbbSJens Wiklander            return BOOL
4283*c689edbbSJens Wiklander
4284*c689edbbSJens Wiklander        return self.orig_type
4285*c689edbbSJens Wiklander
4286*c689edbbSJens Wiklander    @property
4287*c689edbbSJens Wiklander    def str_value(self):
4288*c689edbbSJens Wiklander        """
4289*c689edbbSJens Wiklander        See the class documentation.
4290*c689edbbSJens Wiklander        """
4291*c689edbbSJens Wiklander        if self._cached_str_val is not None:
4292*c689edbbSJens Wiklander            return self._cached_str_val
4293*c689edbbSJens Wiklander
4294*c689edbbSJens Wiklander        if self.orig_type in _BOOL_TRISTATE:
4295*c689edbbSJens Wiklander            # Also calculates the visibility, so invalidation safe
4296*c689edbbSJens Wiklander            self._cached_str_val = TRI_TO_STR[self.tri_value]
4297*c689edbbSJens Wiklander            return self._cached_str_val
4298*c689edbbSJens Wiklander
4299*c689edbbSJens Wiklander        # As a quirk of Kconfig, undefined symbols get their name as their
4300*c689edbbSJens Wiklander        # string value. This is why things like "FOO = bar" work for seeing if
4301*c689edbbSJens Wiklander        # FOO has the value "bar".
4302*c689edbbSJens Wiklander        if not self.orig_type:  # UNKNOWN
4303*c689edbbSJens Wiklander            self._cached_str_val = self.name
4304*c689edbbSJens Wiklander            return self.name
4305*c689edbbSJens Wiklander
4306*c689edbbSJens Wiklander        val = ""
4307*c689edbbSJens Wiklander        # Warning: See Symbol._rec_invalidate(), and note that this is a hidden
4308*c689edbbSJens Wiklander        # function call (property magic)
4309*c689edbbSJens Wiklander        vis = self.visibility
4310*c689edbbSJens Wiklander
4311*c689edbbSJens Wiklander        self._write_to_conf = (vis != 0)
4312*c689edbbSJens Wiklander
4313*c689edbbSJens Wiklander        if self.orig_type in _INT_HEX:
4314*c689edbbSJens Wiklander            # The C implementation checks the user value against the range in a
4315*c689edbbSJens Wiklander            # separate code path (post-processing after loading a .config).
4316*c689edbbSJens Wiklander            # Checking all values here instead makes more sense for us. It
4317*c689edbbSJens Wiklander            # requires that we check for a range first.
4318*c689edbbSJens Wiklander
4319*c689edbbSJens Wiklander            base = _TYPE_TO_BASE[self.orig_type]
4320*c689edbbSJens Wiklander
4321*c689edbbSJens Wiklander            # Check if a range is in effect
4322*c689edbbSJens Wiklander            for low_expr, high_expr, cond in self.ranges:
4323*c689edbbSJens Wiklander                if expr_value(cond):
4324*c689edbbSJens Wiklander                    has_active_range = True
4325*c689edbbSJens Wiklander
4326*c689edbbSJens Wiklander                    # The zeros are from the C implementation running strtoll()
4327*c689edbbSJens Wiklander                    # on empty strings
4328*c689edbbSJens Wiklander                    low = int(low_expr.str_value, base) if \
4329*c689edbbSJens Wiklander                      _is_base_n(low_expr.str_value, base) else 0
4330*c689edbbSJens Wiklander                    high = int(high_expr.str_value, base) if \
4331*c689edbbSJens Wiklander                      _is_base_n(high_expr.str_value, base) else 0
4332*c689edbbSJens Wiklander
4333*c689edbbSJens Wiklander                    break
4334*c689edbbSJens Wiklander            else:
4335*c689edbbSJens Wiklander                has_active_range = False
4336*c689edbbSJens Wiklander
4337*c689edbbSJens Wiklander            # Defaults are used if the symbol is invisible, lacks a user value,
4338*c689edbbSJens Wiklander            # or has an out-of-range user value
4339*c689edbbSJens Wiklander            use_defaults = True
4340*c689edbbSJens Wiklander
4341*c689edbbSJens Wiklander            if vis and self.user_value:
4342*c689edbbSJens Wiklander                user_val = int(self.user_value, base)
4343*c689edbbSJens Wiklander                if has_active_range and not low <= user_val <= high:
4344*c689edbbSJens Wiklander                    num2str = str if base == 10 else hex
4345*c689edbbSJens Wiklander                    self.kconfig._warn(
4346*c689edbbSJens Wiklander                        "user value {} on the {} symbol {} ignored due to "
4347*c689edbbSJens Wiklander                        "being outside the active range ([{}, {}]) -- falling "
4348*c689edbbSJens Wiklander                        "back on defaults"
4349*c689edbbSJens Wiklander                        .format(num2str(user_val), TYPE_TO_STR[self.orig_type],
4350*c689edbbSJens Wiklander                                self.name_and_loc,
4351*c689edbbSJens Wiklander                                num2str(low), num2str(high)))
4352*c689edbbSJens Wiklander                else:
4353*c689edbbSJens Wiklander                    # If the user value is well-formed and satisfies range
4354*c689edbbSJens Wiklander                    # contraints, it is stored in exactly the same form as
4355*c689edbbSJens Wiklander                    # specified in the assignment (with or without "0x", etc.)
4356*c689edbbSJens Wiklander                    val = self.user_value
4357*c689edbbSJens Wiklander                    use_defaults = False
4358*c689edbbSJens Wiklander
4359*c689edbbSJens Wiklander            if use_defaults:
4360*c689edbbSJens Wiklander                # No user value or invalid user value. Look at defaults.
4361*c689edbbSJens Wiklander
4362*c689edbbSJens Wiklander                # Used to implement the warning below
4363*c689edbbSJens Wiklander                has_default = False
4364*c689edbbSJens Wiklander
4365*c689edbbSJens Wiklander                for sym, cond in self.defaults:
4366*c689edbbSJens Wiklander                    if expr_value(cond):
4367*c689edbbSJens Wiklander                        has_default = self._write_to_conf = True
4368*c689edbbSJens Wiklander
4369*c689edbbSJens Wiklander                        val = sym.str_value
4370*c689edbbSJens Wiklander
4371*c689edbbSJens Wiklander                        if _is_base_n(val, base):
4372*c689edbbSJens Wiklander                            val_num = int(val, base)
4373*c689edbbSJens Wiklander                        else:
4374*c689edbbSJens Wiklander                            val_num = 0  # strtoll() on empty string
4375*c689edbbSJens Wiklander
4376*c689edbbSJens Wiklander                        break
4377*c689edbbSJens Wiklander                else:
4378*c689edbbSJens Wiklander                    val_num = 0  # strtoll() on empty string
4379*c689edbbSJens Wiklander
4380*c689edbbSJens Wiklander                # This clamping procedure runs even if there's no default
4381*c689edbbSJens Wiklander                if has_active_range:
4382*c689edbbSJens Wiklander                    clamp = None
4383*c689edbbSJens Wiklander                    if val_num < low:
4384*c689edbbSJens Wiklander                        clamp = low
4385*c689edbbSJens Wiklander                    elif val_num > high:
4386*c689edbbSJens Wiklander                        clamp = high
4387*c689edbbSJens Wiklander
4388*c689edbbSJens Wiklander                    if clamp is not None:
4389*c689edbbSJens Wiklander                        # The value is rewritten to a standard form if it is
4390*c689edbbSJens Wiklander                        # clamped
4391*c689edbbSJens Wiklander                        val = str(clamp) \
4392*c689edbbSJens Wiklander                              if self.orig_type is INT else \
4393*c689edbbSJens Wiklander                              hex(clamp)
4394*c689edbbSJens Wiklander
4395*c689edbbSJens Wiklander                        if has_default:
4396*c689edbbSJens Wiklander                            num2str = str if base == 10 else hex
4397*c689edbbSJens Wiklander                            self.kconfig._warn(
4398*c689edbbSJens Wiklander                                "default value {} on {} clamped to {} due to "
4399*c689edbbSJens Wiklander                                "being outside the active range ([{}, {}])"
4400*c689edbbSJens Wiklander                                .format(val_num, self.name_and_loc,
4401*c689edbbSJens Wiklander                                        num2str(clamp), num2str(low),
4402*c689edbbSJens Wiklander                                        num2str(high)))
4403*c689edbbSJens Wiklander
4404*c689edbbSJens Wiklander        elif self.orig_type is STRING:
4405*c689edbbSJens Wiklander            if vis and self.user_value is not None:
4406*c689edbbSJens Wiklander                # If the symbol is visible and has a user value, use that
4407*c689edbbSJens Wiklander                val = self.user_value
4408*c689edbbSJens Wiklander            else:
4409*c689edbbSJens Wiklander                # Otherwise, look at defaults
4410*c689edbbSJens Wiklander                for sym, cond in self.defaults:
4411*c689edbbSJens Wiklander                    if expr_value(cond):
4412*c689edbbSJens Wiklander                        val = sym.str_value
4413*c689edbbSJens Wiklander                        self._write_to_conf = True
4414*c689edbbSJens Wiklander                        break
4415*c689edbbSJens Wiklander
4416*c689edbbSJens Wiklander        # env_var corresponds to SYMBOL_AUTO in the C implementation, and is
4417*c689edbbSJens Wiklander        # also set on the defconfig_list symbol there. Test for the
4418*c689edbbSJens Wiklander        # defconfig_list symbol explicitly instead here, to avoid a nonsensical
4419*c689edbbSJens Wiklander        # env_var setting and the defconfig_list symbol being printed
4420*c689edbbSJens Wiklander        # incorrectly. This code is pretty cold anyway.
4421*c689edbbSJens Wiklander        if self.env_var is not None or self is self.kconfig.defconfig_list:
4422*c689edbbSJens Wiklander            self._write_to_conf = False
4423*c689edbbSJens Wiklander
4424*c689edbbSJens Wiklander        self._cached_str_val = val
4425*c689edbbSJens Wiklander        return val
4426*c689edbbSJens Wiklander
4427*c689edbbSJens Wiklander    @property
4428*c689edbbSJens Wiklander    def tri_value(self):
4429*c689edbbSJens Wiklander        """
4430*c689edbbSJens Wiklander        See the class documentation.
4431*c689edbbSJens Wiklander        """
4432*c689edbbSJens Wiklander        if self._cached_tri_val is not None:
4433*c689edbbSJens Wiklander            return self._cached_tri_val
4434*c689edbbSJens Wiklander
4435*c689edbbSJens Wiklander        if self.orig_type not in _BOOL_TRISTATE:
4436*c689edbbSJens Wiklander            if self.orig_type:  # != UNKNOWN
4437*c689edbbSJens Wiklander                # Would take some work to give the location here
4438*c689edbbSJens Wiklander                self.kconfig._warn(
4439*c689edbbSJens Wiklander                    "The {} symbol {} is being evaluated in a logical context "
4440*c689edbbSJens Wiklander                    "somewhere. It will always evaluate to n."
4441*c689edbbSJens Wiklander                    .format(TYPE_TO_STR[self.orig_type], self.name_and_loc))
4442*c689edbbSJens Wiklander
4443*c689edbbSJens Wiklander            self._cached_tri_val = 0
4444*c689edbbSJens Wiklander            return 0
4445*c689edbbSJens Wiklander
4446*c689edbbSJens Wiklander        # Warning: See Symbol._rec_invalidate(), and note that this is a hidden
4447*c689edbbSJens Wiklander        # function call (property magic)
4448*c689edbbSJens Wiklander        vis = self.visibility
4449*c689edbbSJens Wiklander        self._write_to_conf = (vis != 0)
4450*c689edbbSJens Wiklander
4451*c689edbbSJens Wiklander        val = 0
4452*c689edbbSJens Wiklander
4453*c689edbbSJens Wiklander        if not self.choice:
4454*c689edbbSJens Wiklander            # Non-choice symbol
4455*c689edbbSJens Wiklander
4456*c689edbbSJens Wiklander            if vis and self.user_value is not None:
4457*c689edbbSJens Wiklander                # If the symbol is visible and has a user value, use that
4458*c689edbbSJens Wiklander                val = min(self.user_value, vis)
4459*c689edbbSJens Wiklander
4460*c689edbbSJens Wiklander            else:
4461*c689edbbSJens Wiklander                # Otherwise, look at defaults and weak reverse dependencies
4462*c689edbbSJens Wiklander                # (implies)
4463*c689edbbSJens Wiklander
4464*c689edbbSJens Wiklander                for default, cond in self.defaults:
4465*c689edbbSJens Wiklander                    dep_val = expr_value(cond)
4466*c689edbbSJens Wiklander                    if dep_val:
4467*c689edbbSJens Wiklander                        val = min(expr_value(default), dep_val)
4468*c689edbbSJens Wiklander                        if val:
4469*c689edbbSJens Wiklander                            self._write_to_conf = True
4470*c689edbbSJens Wiklander                        break
4471*c689edbbSJens Wiklander
4472*c689edbbSJens Wiklander                # Weak reverse dependencies are only considered if our
4473*c689edbbSJens Wiklander                # direct dependencies are met
4474*c689edbbSJens Wiklander                dep_val = expr_value(self.weak_rev_dep)
4475*c689edbbSJens Wiklander                if dep_val and expr_value(self.direct_dep):
4476*c689edbbSJens Wiklander                    val = max(dep_val, val)
4477*c689edbbSJens Wiklander                    self._write_to_conf = True
4478*c689edbbSJens Wiklander
4479*c689edbbSJens Wiklander            # Reverse (select-related) dependencies take precedence
4480*c689edbbSJens Wiklander            dep_val = expr_value(self.rev_dep)
4481*c689edbbSJens Wiklander            if dep_val:
4482*c689edbbSJens Wiklander                if expr_value(self.direct_dep) < dep_val:
4483*c689edbbSJens Wiklander                    self._warn_select_unsatisfied_deps()
4484*c689edbbSJens Wiklander
4485*c689edbbSJens Wiklander                val = max(dep_val, val)
4486*c689edbbSJens Wiklander                self._write_to_conf = True
4487*c689edbbSJens Wiklander
4488*c689edbbSJens Wiklander            # m is promoted to y for (1) bool symbols and (2) symbols with a
4489*c689edbbSJens Wiklander            # weak_rev_dep (from imply) of y
4490*c689edbbSJens Wiklander            if val == 1 and \
4491*c689edbbSJens Wiklander               (self.type is BOOL or expr_value(self.weak_rev_dep) == 2):
4492*c689edbbSJens Wiklander                val = 2
4493*c689edbbSJens Wiklander
4494*c689edbbSJens Wiklander        elif vis == 2:
4495*c689edbbSJens Wiklander            # Visible choice symbol in y-mode choice. The choice mode limits
4496*c689edbbSJens Wiklander            # the visibility of choice symbols, so it's sufficient to just
4497*c689edbbSJens Wiklander            # check the visibility of the choice symbols themselves.
4498*c689edbbSJens Wiklander            val = 2 if self.choice.selection is self else 0
4499*c689edbbSJens Wiklander
4500*c689edbbSJens Wiklander        elif vis and self.user_value:
4501*c689edbbSJens Wiklander            # Visible choice symbol in m-mode choice, with set non-0 user value
4502*c689edbbSJens Wiklander            val = 1
4503*c689edbbSJens Wiklander
4504*c689edbbSJens Wiklander        self._cached_tri_val = val
4505*c689edbbSJens Wiklander        return val
4506*c689edbbSJens Wiklander
4507*c689edbbSJens Wiklander    @property
4508*c689edbbSJens Wiklander    def assignable(self):
4509*c689edbbSJens Wiklander        """
4510*c689edbbSJens Wiklander        See the class documentation.
4511*c689edbbSJens Wiklander        """
4512*c689edbbSJens Wiklander        if self._cached_assignable is None:
4513*c689edbbSJens Wiklander            self._cached_assignable = self._assignable()
4514*c689edbbSJens Wiklander        return self._cached_assignable
4515*c689edbbSJens Wiklander
4516*c689edbbSJens Wiklander    @property
4517*c689edbbSJens Wiklander    def visibility(self):
4518*c689edbbSJens Wiklander        """
4519*c689edbbSJens Wiklander        See the class documentation.
4520*c689edbbSJens Wiklander        """
4521*c689edbbSJens Wiklander        if self._cached_vis is None:
4522*c689edbbSJens Wiklander            self._cached_vis = _visibility(self)
4523*c689edbbSJens Wiklander        return self._cached_vis
4524*c689edbbSJens Wiklander
4525*c689edbbSJens Wiklander    @property
4526*c689edbbSJens Wiklander    def config_string(self):
4527*c689edbbSJens Wiklander        """
4528*c689edbbSJens Wiklander        See the class documentation.
4529*c689edbbSJens Wiklander        """
4530*c689edbbSJens Wiklander        # _write_to_conf is determined when the value is calculated. This is a
4531*c689edbbSJens Wiklander        # hidden function call due to property magic.
4532*c689edbbSJens Wiklander        val = self.str_value
4533*c689edbbSJens Wiklander        if not self._write_to_conf:
4534*c689edbbSJens Wiklander            return ""
4535*c689edbbSJens Wiklander
4536*c689edbbSJens Wiklander        if self.orig_type in _BOOL_TRISTATE:
4537*c689edbbSJens Wiklander            return "{}{}={}\n" \
4538*c689edbbSJens Wiklander                   .format(self.kconfig.config_prefix, self.name, val) \
4539*c689edbbSJens Wiklander                   if val != "n" else \
4540*c689edbbSJens Wiklander                   "# {}{} is not set\n" \
4541*c689edbbSJens Wiklander                   .format(self.kconfig.config_prefix, self.name)
4542*c689edbbSJens Wiklander
4543*c689edbbSJens Wiklander        if self.orig_type in _INT_HEX:
4544*c689edbbSJens Wiklander            return "{}{}={}\n" \
4545*c689edbbSJens Wiklander                   .format(self.kconfig.config_prefix, self.name, val)
4546*c689edbbSJens Wiklander
4547*c689edbbSJens Wiklander        # sym.orig_type is STRING
4548*c689edbbSJens Wiklander        return '{}{}="{}"\n' \
4549*c689edbbSJens Wiklander               .format(self.kconfig.config_prefix, self.name, escape(val))
4550*c689edbbSJens Wiklander
4551*c689edbbSJens Wiklander    @property
4552*c689edbbSJens Wiklander    def name_and_loc(self):
4553*c689edbbSJens Wiklander        """
4554*c689edbbSJens Wiklander        See the class documentation.
4555*c689edbbSJens Wiklander        """
4556*c689edbbSJens Wiklander        return self.name + " " + _locs(self)
4557*c689edbbSJens Wiklander
4558*c689edbbSJens Wiklander    def set_value(self, value):
4559*c689edbbSJens Wiklander        """
4560*c689edbbSJens Wiklander        Sets the user value of the symbol.
4561*c689edbbSJens Wiklander
4562*c689edbbSJens Wiklander        Equal in effect to assigning the value to the symbol within a .config
4563*c689edbbSJens Wiklander        file. For bool and tristate symbols, use the 'assignable' attribute to
4564*c689edbbSJens Wiklander        check which values can currently be assigned. Setting values outside
4565*c689edbbSJens Wiklander        'assignable' will cause Symbol.user_value to differ from
4566*c689edbbSJens Wiklander        Symbol.str/tri_value (be truncated down or up).
4567*c689edbbSJens Wiklander
4568*c689edbbSJens Wiklander        Setting a choice symbol to 2 (y) sets Choice.user_selection to the
4569*c689edbbSJens Wiklander        choice symbol in addition to setting Symbol.user_value.
4570*c689edbbSJens Wiklander        Choice.user_selection is considered when the choice is in y mode (the
4571*c689edbbSJens Wiklander        "normal" mode).
4572*c689edbbSJens Wiklander
4573*c689edbbSJens Wiklander        Other symbols that depend (possibly indirectly) on this symbol are
4574*c689edbbSJens Wiklander        automatically recalculated to reflect the assigned value.
4575*c689edbbSJens Wiklander
4576*c689edbbSJens Wiklander        value:
4577*c689edbbSJens Wiklander          The user value to give to the symbol. For bool and tristate symbols,
4578*c689edbbSJens Wiklander          n/m/y can be specified either as 0/1/2 (the usual format for tristate
4579*c689edbbSJens Wiklander          values in Kconfiglib) or as one of the strings "n", "m", or "y". For
4580*c689edbbSJens Wiklander          other symbol types, pass a string.
4581*c689edbbSJens Wiklander
4582*c689edbbSJens Wiklander          Note that the value for an int/hex symbol is passed as a string, e.g.
4583*c689edbbSJens Wiklander          "123" or "0x0123". The format of this string is preserved in the
4584*c689edbbSJens Wiklander          output.
4585*c689edbbSJens Wiklander
4586*c689edbbSJens Wiklander          Values that are invalid for the type (such as "foo" or 1 (m) for a
4587*c689edbbSJens Wiklander          BOOL or "0x123" for an INT) are ignored and won't be stored in
4588*c689edbbSJens Wiklander          Symbol.user_value. Kconfiglib will print a warning by default for
4589*c689edbbSJens Wiklander          invalid assignments, and set_value() will return False.
4590*c689edbbSJens Wiklander
4591*c689edbbSJens Wiklander        Returns True if the value is valid for the type of the symbol, and
4592*c689edbbSJens Wiklander        False otherwise. This only looks at the form of the value. For BOOL and
4593*c689edbbSJens Wiklander        TRISTATE symbols, check the Symbol.assignable attribute to see what
4594*c689edbbSJens Wiklander        values are currently in range and would actually be reflected in the
4595*c689edbbSJens Wiklander        value of the symbol. For other symbol types, check whether the
4596*c689edbbSJens Wiklander        visibility is non-n.
4597*c689edbbSJens Wiklander        """
4598*c689edbbSJens Wiklander        if self.orig_type in _BOOL_TRISTATE and value in STR_TO_TRI:
4599*c689edbbSJens Wiklander            value = STR_TO_TRI[value]
4600*c689edbbSJens Wiklander
4601*c689edbbSJens Wiklander        # If the new user value matches the old, nothing changes, and we can
4602*c689edbbSJens Wiklander        # avoid invalidating cached values.
4603*c689edbbSJens Wiklander        #
4604*c689edbbSJens Wiklander        # This optimization is skipped for choice symbols: Setting a choice
4605*c689edbbSJens Wiklander        # symbol's user value to y might change the state of the choice, so it
4606*c689edbbSJens Wiklander        # wouldn't be safe (symbol user values always match the values set in a
4607*c689edbbSJens Wiklander        # .config file or via set_value(), and are never implicitly updated).
4608*c689edbbSJens Wiklander        if value == self.user_value and not self.choice:
4609*c689edbbSJens Wiklander            self._was_set = True
4610*c689edbbSJens Wiklander            return True
4611*c689edbbSJens Wiklander
4612*c689edbbSJens Wiklander        # Check if the value is valid for our type
4613*c689edbbSJens Wiklander        if not (self.orig_type is BOOL     and value in (2, 0)     or
4614*c689edbbSJens Wiklander                self.orig_type is TRISTATE and value in TRI_TO_STR or
4615*c689edbbSJens Wiklander                value.__class__ is str and
4616*c689edbbSJens Wiklander                (self.orig_type is STRING                        or
4617*c689edbbSJens Wiklander                 self.orig_type is INT and _is_base_n(value, 10) or
4618*c689edbbSJens Wiklander                 self.orig_type is HEX and _is_base_n(value, 16)
4619*c689edbbSJens Wiklander                                       and int(value, 16) >= 0)):
4620*c689edbbSJens Wiklander
4621*c689edbbSJens Wiklander            # Display tristate values as n, m, y in the warning
4622*c689edbbSJens Wiklander            self.kconfig._warn(
4623*c689edbbSJens Wiklander                "the value {} is invalid for {}, which has type {} -- "
4624*c689edbbSJens Wiklander                "assignment ignored"
4625*c689edbbSJens Wiklander                .format(TRI_TO_STR[value] if value in TRI_TO_STR else
4626*c689edbbSJens Wiklander                            "'{}'".format(value),
4627*c689edbbSJens Wiklander                        self.name_and_loc, TYPE_TO_STR[self.orig_type]))
4628*c689edbbSJens Wiklander
4629*c689edbbSJens Wiklander            return False
4630*c689edbbSJens Wiklander
4631*c689edbbSJens Wiklander        self.user_value = value
4632*c689edbbSJens Wiklander        self._was_set = True
4633*c689edbbSJens Wiklander
4634*c689edbbSJens Wiklander        if self.choice and value == 2:
4635*c689edbbSJens Wiklander            # Setting a choice symbol to y makes it the user selection of the
4636*c689edbbSJens Wiklander            # choice. Like for symbol user values, the user selection is not
4637*c689edbbSJens Wiklander            # guaranteed to match the actual selection of the choice, as
4638*c689edbbSJens Wiklander            # dependencies come into play.
4639*c689edbbSJens Wiklander            self.choice.user_selection = self
4640*c689edbbSJens Wiklander            self.choice._was_set = True
4641*c689edbbSJens Wiklander            self.choice._rec_invalidate()
4642*c689edbbSJens Wiklander        else:
4643*c689edbbSJens Wiklander            self._rec_invalidate_if_has_prompt()
4644*c689edbbSJens Wiklander
4645*c689edbbSJens Wiklander        return True
4646*c689edbbSJens Wiklander
4647*c689edbbSJens Wiklander    def unset_value(self):
4648*c689edbbSJens Wiklander        """
4649*c689edbbSJens Wiklander        Removes any user value from the symbol, as if the symbol had never
4650*c689edbbSJens Wiklander        gotten a user value via Kconfig.load_config() or Symbol.set_value().
4651*c689edbbSJens Wiklander        """
4652*c689edbbSJens Wiklander        if self.user_value is not None:
4653*c689edbbSJens Wiklander            self.user_value = None
4654*c689edbbSJens Wiklander            self._rec_invalidate_if_has_prompt()
4655*c689edbbSJens Wiklander
4656*c689edbbSJens Wiklander    @property
4657*c689edbbSJens Wiklander    def referenced(self):
4658*c689edbbSJens Wiklander        """
4659*c689edbbSJens Wiklander        See the class documentation.
4660*c689edbbSJens Wiklander        """
4661*c689edbbSJens Wiklander        return {item for node in self.nodes for item in node.referenced}
4662*c689edbbSJens Wiklander
4663*c689edbbSJens Wiklander    @property
4664*c689edbbSJens Wiklander    def orig_defaults(self):
4665*c689edbbSJens Wiklander        """
4666*c689edbbSJens Wiklander        See the class documentation.
4667*c689edbbSJens Wiklander        """
4668*c689edbbSJens Wiklander        return [d for node in self.nodes for d in node.orig_defaults]
4669*c689edbbSJens Wiklander
4670*c689edbbSJens Wiklander    @property
4671*c689edbbSJens Wiklander    def orig_selects(self):
4672*c689edbbSJens Wiklander        """
4673*c689edbbSJens Wiklander        See the class documentation.
4674*c689edbbSJens Wiklander        """
4675*c689edbbSJens Wiklander        return [s for node in self.nodes for s in node.orig_selects]
4676*c689edbbSJens Wiklander
4677*c689edbbSJens Wiklander    @property
4678*c689edbbSJens Wiklander    def orig_implies(self):
4679*c689edbbSJens Wiklander        """
4680*c689edbbSJens Wiklander        See the class documentation.
4681*c689edbbSJens Wiklander        """
4682*c689edbbSJens Wiklander        return [i for node in self.nodes for i in node.orig_implies]
4683*c689edbbSJens Wiklander
4684*c689edbbSJens Wiklander    @property
4685*c689edbbSJens Wiklander    def orig_ranges(self):
4686*c689edbbSJens Wiklander        """
4687*c689edbbSJens Wiklander        See the class documentation.
4688*c689edbbSJens Wiklander        """
4689*c689edbbSJens Wiklander        return [r for node in self.nodes for r in node.orig_ranges]
4690*c689edbbSJens Wiklander
4691*c689edbbSJens Wiklander    def __repr__(self):
4692*c689edbbSJens Wiklander        """
4693*c689edbbSJens Wiklander        Returns a string with information about the symbol (including its name,
4694*c689edbbSJens Wiklander        value, visibility, and location(s)) when it is evaluated on e.g. the
4695*c689edbbSJens Wiklander        interactive Python prompt.
4696*c689edbbSJens Wiklander        """
4697*c689edbbSJens Wiklander        fields = ["symbol " + self.name, TYPE_TO_STR[self.type]]
4698*c689edbbSJens Wiklander        add = fields.append
4699*c689edbbSJens Wiklander
4700*c689edbbSJens Wiklander        for node in self.nodes:
4701*c689edbbSJens Wiklander            if node.prompt:
4702*c689edbbSJens Wiklander                add('"{}"'.format(node.prompt[0]))
4703*c689edbbSJens Wiklander
4704*c689edbbSJens Wiklander        # Only add quotes for non-bool/tristate symbols
4705*c689edbbSJens Wiklander        add("value " + (self.str_value if self.orig_type in _BOOL_TRISTATE
4706*c689edbbSJens Wiklander                        else '"{}"'.format(self.str_value)))
4707*c689edbbSJens Wiklander
4708*c689edbbSJens Wiklander        if not self.is_constant:
4709*c689edbbSJens Wiklander            # These aren't helpful to show for constant symbols
4710*c689edbbSJens Wiklander
4711*c689edbbSJens Wiklander            if self.user_value is not None:
4712*c689edbbSJens Wiklander                # Only add quotes for non-bool/tristate symbols
4713*c689edbbSJens Wiklander                add("user value " + (TRI_TO_STR[self.user_value]
4714*c689edbbSJens Wiklander                                     if self.orig_type in _BOOL_TRISTATE
4715*c689edbbSJens Wiklander                                     else '"{}"'.format(self.user_value)))
4716*c689edbbSJens Wiklander
4717*c689edbbSJens Wiklander            add("visibility " + TRI_TO_STR[self.visibility])
4718*c689edbbSJens Wiklander
4719*c689edbbSJens Wiklander            if self.choice:
4720*c689edbbSJens Wiklander                add("choice symbol")
4721*c689edbbSJens Wiklander
4722*c689edbbSJens Wiklander            if self.is_allnoconfig_y:
4723*c689edbbSJens Wiklander                add("allnoconfig_y")
4724*c689edbbSJens Wiklander
4725*c689edbbSJens Wiklander            if self is self.kconfig.defconfig_list:
4726*c689edbbSJens Wiklander                add("is the defconfig_list symbol")
4727*c689edbbSJens Wiklander
4728*c689edbbSJens Wiklander            if self.env_var is not None:
4729*c689edbbSJens Wiklander                add("from environment variable " + self.env_var)
4730*c689edbbSJens Wiklander
4731*c689edbbSJens Wiklander            if self is self.kconfig.modules:
4732*c689edbbSJens Wiklander                add("is the modules symbol")
4733*c689edbbSJens Wiklander
4734*c689edbbSJens Wiklander            add("direct deps " + TRI_TO_STR[expr_value(self.direct_dep)])
4735*c689edbbSJens Wiklander
4736*c689edbbSJens Wiklander        if self.nodes:
4737*c689edbbSJens Wiklander            for node in self.nodes:
4738*c689edbbSJens Wiklander                add("{}:{}".format(node.filename, node.linenr))
4739*c689edbbSJens Wiklander        else:
4740*c689edbbSJens Wiklander            add("constant" if self.is_constant else "undefined")
4741*c689edbbSJens Wiklander
4742*c689edbbSJens Wiklander        return "<{}>".format(", ".join(fields))
4743*c689edbbSJens Wiklander
4744*c689edbbSJens Wiklander    def __str__(self):
4745*c689edbbSJens Wiklander        """
4746*c689edbbSJens Wiklander        Returns a string representation of the symbol when it is printed.
4747*c689edbbSJens Wiklander        Matches the Kconfig format, with any parent dependencies propagated to
4748*c689edbbSJens Wiklander        the 'depends on' condition.
4749*c689edbbSJens Wiklander
4750*c689edbbSJens Wiklander        The string is constructed by joining the strings returned by
4751*c689edbbSJens Wiklander        MenuNode.__str__() for each of the symbol's menu nodes, so symbols
4752*c689edbbSJens Wiklander        defined in multiple locations will return a string with all
4753*c689edbbSJens Wiklander        definitions.
4754*c689edbbSJens Wiklander
4755*c689edbbSJens Wiklander        The returned string does not end in a newline. An empty string is
4756*c689edbbSJens Wiklander        returned for undefined and constant symbols.
4757*c689edbbSJens Wiklander        """
4758*c689edbbSJens Wiklander        return self.custom_str(standard_sc_expr_str)
4759*c689edbbSJens Wiklander
4760*c689edbbSJens Wiklander    def custom_str(self, sc_expr_str_fn):
4761*c689edbbSJens Wiklander        """
4762*c689edbbSJens Wiklander        Works like Symbol.__str__(), but allows a custom format to be used for
4763*c689edbbSJens Wiklander        all symbol/choice references. See expr_str().
4764*c689edbbSJens Wiklander        """
4765*c689edbbSJens Wiklander        return "\n\n".join(node.custom_str(sc_expr_str_fn)
4766*c689edbbSJens Wiklander                           for node in self.nodes)
4767*c689edbbSJens Wiklander
4768*c689edbbSJens Wiklander    #
4769*c689edbbSJens Wiklander    # Private methods
4770*c689edbbSJens Wiklander    #
4771*c689edbbSJens Wiklander
4772*c689edbbSJens Wiklander    def __init__(self):
4773*c689edbbSJens Wiklander        """
4774*c689edbbSJens Wiklander        Symbol constructor -- not intended to be called directly by Kconfiglib
4775*c689edbbSJens Wiklander        clients.
4776*c689edbbSJens Wiklander        """
4777*c689edbbSJens Wiklander        # These attributes are always set on the instance from outside and
4778*c689edbbSJens Wiklander        # don't need defaults:
4779*c689edbbSJens Wiklander        #   kconfig
4780*c689edbbSJens Wiklander        #   direct_dep
4781*c689edbbSJens Wiklander        #   is_constant
4782*c689edbbSJens Wiklander        #   name
4783*c689edbbSJens Wiklander        #   rev_dep
4784*c689edbbSJens Wiklander        #   weak_rev_dep
4785*c689edbbSJens Wiklander
4786*c689edbbSJens Wiklander        # - UNKNOWN == 0
4787*c689edbbSJens Wiklander        # - _visited is used during tree iteration and dep. loop detection
4788*c689edbbSJens Wiklander        self.orig_type = self._visited = 0
4789*c689edbbSJens Wiklander
4790*c689edbbSJens Wiklander        self.nodes = []
4791*c689edbbSJens Wiklander
4792*c689edbbSJens Wiklander        self.defaults = []
4793*c689edbbSJens Wiklander        self.selects = []
4794*c689edbbSJens Wiklander        self.implies = []
4795*c689edbbSJens Wiklander        self.ranges = []
4796*c689edbbSJens Wiklander
4797*c689edbbSJens Wiklander        self.user_value = \
4798*c689edbbSJens Wiklander        self.choice = \
4799*c689edbbSJens Wiklander        self.env_var = \
4800*c689edbbSJens Wiklander        self._cached_str_val = self._cached_tri_val = self._cached_vis = \
4801*c689edbbSJens Wiklander        self._cached_assignable = None
4802*c689edbbSJens Wiklander
4803*c689edbbSJens Wiklander        # _write_to_conf is calculated along with the value. If True, the
4804*c689edbbSJens Wiklander        # Symbol gets a .config entry.
4805*c689edbbSJens Wiklander
4806*c689edbbSJens Wiklander        self.is_allnoconfig_y = \
4807*c689edbbSJens Wiklander        self._was_set = \
4808*c689edbbSJens Wiklander        self._write_to_conf = False
4809*c689edbbSJens Wiklander
4810*c689edbbSJens Wiklander        # See Kconfig._build_dep()
4811*c689edbbSJens Wiklander        self._dependents = set()
4812*c689edbbSJens Wiklander
4813*c689edbbSJens Wiklander    def _assignable(self):
4814*c689edbbSJens Wiklander        # Worker function for the 'assignable' attribute
4815*c689edbbSJens Wiklander
4816*c689edbbSJens Wiklander        if self.orig_type not in _BOOL_TRISTATE:
4817*c689edbbSJens Wiklander            return ()
4818*c689edbbSJens Wiklander
4819*c689edbbSJens Wiklander        # Warning: See Symbol._rec_invalidate(), and note that this is a hidden
4820*c689edbbSJens Wiklander        # function call (property magic)
4821*c689edbbSJens Wiklander        vis = self.visibility
4822*c689edbbSJens Wiklander        if not vis:
4823*c689edbbSJens Wiklander            return ()
4824*c689edbbSJens Wiklander
4825*c689edbbSJens Wiklander        rev_dep_val = expr_value(self.rev_dep)
4826*c689edbbSJens Wiklander
4827*c689edbbSJens Wiklander        if vis == 2:
4828*c689edbbSJens Wiklander            if self.choice:
4829*c689edbbSJens Wiklander                return (2,)
4830*c689edbbSJens Wiklander
4831*c689edbbSJens Wiklander            if not rev_dep_val:
4832*c689edbbSJens Wiklander                if self.type is BOOL or expr_value(self.weak_rev_dep) == 2:
4833*c689edbbSJens Wiklander                    return (0, 2)
4834*c689edbbSJens Wiklander                return (0, 1, 2)
4835*c689edbbSJens Wiklander
4836*c689edbbSJens Wiklander            if rev_dep_val == 2:
4837*c689edbbSJens Wiklander                return (2,)
4838*c689edbbSJens Wiklander
4839*c689edbbSJens Wiklander            # rev_dep_val == 1
4840*c689edbbSJens Wiklander
4841*c689edbbSJens Wiklander            if self.type is BOOL or expr_value(self.weak_rev_dep) == 2:
4842*c689edbbSJens Wiklander                return (2,)
4843*c689edbbSJens Wiklander            return (1, 2)
4844*c689edbbSJens Wiklander
4845*c689edbbSJens Wiklander        # vis == 1
4846*c689edbbSJens Wiklander
4847*c689edbbSJens Wiklander        # Must be a tristate here, because bool m visibility gets promoted to y
4848*c689edbbSJens Wiklander
4849*c689edbbSJens Wiklander        if not rev_dep_val:
4850*c689edbbSJens Wiklander            return (0, 1) if expr_value(self.weak_rev_dep) != 2 else (0, 2)
4851*c689edbbSJens Wiklander
4852*c689edbbSJens Wiklander        if rev_dep_val == 2:
4853*c689edbbSJens Wiklander            return (2,)
4854*c689edbbSJens Wiklander
4855*c689edbbSJens Wiklander        # vis == rev_dep_val == 1
4856*c689edbbSJens Wiklander
4857*c689edbbSJens Wiklander        return (1,)
4858*c689edbbSJens Wiklander
4859*c689edbbSJens Wiklander    def _invalidate(self):
4860*c689edbbSJens Wiklander        # Marks the symbol as needing to be recalculated
4861*c689edbbSJens Wiklander
4862*c689edbbSJens Wiklander        self._cached_str_val = self._cached_tri_val = self._cached_vis = \
4863*c689edbbSJens Wiklander        self._cached_assignable = None
4864*c689edbbSJens Wiklander
4865*c689edbbSJens Wiklander    def _rec_invalidate(self):
4866*c689edbbSJens Wiklander        # Invalidates the symbol and all items that (possibly) depend on it
4867*c689edbbSJens Wiklander
4868*c689edbbSJens Wiklander        if self is self.kconfig.modules:
4869*c689edbbSJens Wiklander            # Invalidating MODULES has wide-ranging effects
4870*c689edbbSJens Wiklander            self.kconfig._invalidate_all()
4871*c689edbbSJens Wiklander        else:
4872*c689edbbSJens Wiklander            self._invalidate()
4873*c689edbbSJens Wiklander
4874*c689edbbSJens Wiklander            for item in self._dependents:
4875*c689edbbSJens Wiklander                # _cached_vis doubles as a flag that tells us whether 'item'
4876*c689edbbSJens Wiklander                # has cached values, because it's calculated as a side effect
4877*c689edbbSJens Wiklander                # of calculating all other (non-constant) cached values.
4878*c689edbbSJens Wiklander                #
4879*c689edbbSJens Wiklander                # If item._cached_vis is None, it means there can't be cached
4880*c689edbbSJens Wiklander                # values on other items that depend on 'item', because if there
4881*c689edbbSJens Wiklander                # were, some value on 'item' would have been calculated and
4882*c689edbbSJens Wiklander                # item._cached_vis set as a side effect. It's therefore safe to
4883*c689edbbSJens Wiklander                # stop the invalidation at symbols with _cached_vis None.
4884*c689edbbSJens Wiklander                #
4885*c689edbbSJens Wiklander                # This approach massively speeds up scripts that set a lot of
4886*c689edbbSJens Wiklander                # values, vs simply invalidating all possibly dependent symbols
4887*c689edbbSJens Wiklander                # (even when you already have a list of all the dependent
4888*c689edbbSJens Wiklander                # symbols, because some symbols get huge dependency trees).
4889*c689edbbSJens Wiklander                #
4890*c689edbbSJens Wiklander                # This gracefully handles dependency loops too, which is nice
4891*c689edbbSJens Wiklander                # for choices, where the choice depends on the choice symbols
4892*c689edbbSJens Wiklander                # and vice versa.
4893*c689edbbSJens Wiklander                if item._cached_vis is not None:
4894*c689edbbSJens Wiklander                    item._rec_invalidate()
4895*c689edbbSJens Wiklander
4896*c689edbbSJens Wiklander    def _rec_invalidate_if_has_prompt(self):
4897*c689edbbSJens Wiklander        # Invalidates the symbol and its dependent symbols, but only if the
4898*c689edbbSJens Wiklander        # symbol has a prompt. User values never have an effect on promptless
4899*c689edbbSJens Wiklander        # symbols, so we skip invalidation for them as an optimization.
4900*c689edbbSJens Wiklander        #
4901*c689edbbSJens Wiklander        # This also prevents constant (quoted) symbols from being invalidated
4902*c689edbbSJens Wiklander        # if set_value() is called on them, which would make them lose their
4903*c689edbbSJens Wiklander        # value and break things.
4904*c689edbbSJens Wiklander        #
4905*c689edbbSJens Wiklander        # Prints a warning if the symbol has no prompt. In some contexts (e.g.
4906*c689edbbSJens Wiklander        # when loading a .config files) assignments to promptless symbols are
4907*c689edbbSJens Wiklander        # normal and expected, so the warning can be disabled.
4908*c689edbbSJens Wiklander
4909*c689edbbSJens Wiklander        for node in self.nodes:
4910*c689edbbSJens Wiklander            if node.prompt:
4911*c689edbbSJens Wiklander                self._rec_invalidate()
4912*c689edbbSJens Wiklander                return
4913*c689edbbSJens Wiklander
4914*c689edbbSJens Wiklander        if self.kconfig._warn_assign_no_prompt:
4915*c689edbbSJens Wiklander            self.kconfig._warn(self.name_and_loc + " has no prompt, meaning "
4916*c689edbbSJens Wiklander                               "user values have no effect on it")
4917*c689edbbSJens Wiklander
4918*c689edbbSJens Wiklander    def _str_default(self):
4919*c689edbbSJens Wiklander        # write_min_config() helper function. Returns the value the symbol
4920*c689edbbSJens Wiklander        # would get from defaults if it didn't have a user value. Uses exactly
4921*c689edbbSJens Wiklander        # the same algorithm as the C implementation (though a bit cleaned up),
4922*c689edbbSJens Wiklander        # for compatibility.
4923*c689edbbSJens Wiklander
4924*c689edbbSJens Wiklander        if self.orig_type in _BOOL_TRISTATE:
4925*c689edbbSJens Wiklander            val = 0
4926*c689edbbSJens Wiklander
4927*c689edbbSJens Wiklander            # Defaults, selects, and implies do not affect choice symbols
4928*c689edbbSJens Wiklander            if not self.choice:
4929*c689edbbSJens Wiklander                for default, cond in self.defaults:
4930*c689edbbSJens Wiklander                    cond_val = expr_value(cond)
4931*c689edbbSJens Wiklander                    if cond_val:
4932*c689edbbSJens Wiklander                        val = min(expr_value(default), cond_val)
4933*c689edbbSJens Wiklander                        break
4934*c689edbbSJens Wiklander
4935*c689edbbSJens Wiklander                val = max(expr_value(self.rev_dep),
4936*c689edbbSJens Wiklander                          expr_value(self.weak_rev_dep),
4937*c689edbbSJens Wiklander                          val)
4938*c689edbbSJens Wiklander
4939*c689edbbSJens Wiklander                # Transpose mod to yes if type is bool (possibly due to modules
4940*c689edbbSJens Wiklander                # being disabled)
4941*c689edbbSJens Wiklander                if val == 1 and self.type is BOOL:
4942*c689edbbSJens Wiklander                    val = 2
4943*c689edbbSJens Wiklander
4944*c689edbbSJens Wiklander            return TRI_TO_STR[val]
4945*c689edbbSJens Wiklander
4946*c689edbbSJens Wiklander        if self.orig_type:  # STRING/INT/HEX
4947*c689edbbSJens Wiklander            for default, cond in self.defaults:
4948*c689edbbSJens Wiklander                if expr_value(cond):
4949*c689edbbSJens Wiklander                    return default.str_value
4950*c689edbbSJens Wiklander
4951*c689edbbSJens Wiklander        return ""
4952*c689edbbSJens Wiklander
4953*c689edbbSJens Wiklander    def _warn_select_unsatisfied_deps(self):
4954*c689edbbSJens Wiklander        # Helper for printing an informative warning when a symbol with
4955*c689edbbSJens Wiklander        # unsatisfied direct dependencies (dependencies from 'depends on', ifs,
4956*c689edbbSJens Wiklander        # and menus) is selected by some other symbol. Also warn if a symbol
4957*c689edbbSJens Wiklander        # whose direct dependencies evaluate to m is selected to y.
4958*c689edbbSJens Wiklander
4959*c689edbbSJens Wiklander        msg = "{} has direct dependencies {} with value {}, but is " \
4960*c689edbbSJens Wiklander              "currently being {}-selected by the following symbols:" \
4961*c689edbbSJens Wiklander              .format(self.name_and_loc, expr_str(self.direct_dep),
4962*c689edbbSJens Wiklander                      TRI_TO_STR[expr_value(self.direct_dep)],
4963*c689edbbSJens Wiklander                      TRI_TO_STR[expr_value(self.rev_dep)])
4964*c689edbbSJens Wiklander
4965*c689edbbSJens Wiklander        # The reverse dependencies from each select are ORed together
4966*c689edbbSJens Wiklander        for select in split_expr(self.rev_dep, OR):
4967*c689edbbSJens Wiklander            if expr_value(select) <= expr_value(self.direct_dep):
4968*c689edbbSJens Wiklander                # Only include selects that exceed the direct dependencies
4969*c689edbbSJens Wiklander                continue
4970*c689edbbSJens Wiklander
4971*c689edbbSJens Wiklander            # - 'select A if B' turns into A && B
4972*c689edbbSJens Wiklander            # - 'select A' just turns into A
4973*c689edbbSJens Wiklander            #
4974*c689edbbSJens Wiklander            # In both cases, we can split on AND and pick the first operand
4975*c689edbbSJens Wiklander            selecting_sym = split_expr(select, AND)[0]
4976*c689edbbSJens Wiklander
4977*c689edbbSJens Wiklander            msg += "\n - {}, with value {}, direct dependencies {} " \
4978*c689edbbSJens Wiklander                   "(value: {})" \
4979*c689edbbSJens Wiklander                   .format(selecting_sym.name_and_loc,
4980*c689edbbSJens Wiklander                           selecting_sym.str_value,
4981*c689edbbSJens Wiklander                           expr_str(selecting_sym.direct_dep),
4982*c689edbbSJens Wiklander                           TRI_TO_STR[expr_value(selecting_sym.direct_dep)])
4983*c689edbbSJens Wiklander
4984*c689edbbSJens Wiklander            if select.__class__ is tuple:
4985*c689edbbSJens Wiklander                msg += ", and select condition {} (value: {})" \
4986*c689edbbSJens Wiklander                       .format(expr_str(select[2]),
4987*c689edbbSJens Wiklander                               TRI_TO_STR[expr_value(select[2])])
4988*c689edbbSJens Wiklander
4989*c689edbbSJens Wiklander        self.kconfig._warn(msg)
4990*c689edbbSJens Wiklander
4991*c689edbbSJens Wiklander
4992*c689edbbSJens Wiklanderclass Choice(object):
4993*c689edbbSJens Wiklander    """
4994*c689edbbSJens Wiklander    Represents a choice statement:
4995*c689edbbSJens Wiklander
4996*c689edbbSJens Wiklander      choice
4997*c689edbbSJens Wiklander          ...
4998*c689edbbSJens Wiklander      endchoice
4999*c689edbbSJens Wiklander
5000*c689edbbSJens Wiklander    The following attributes are available on Choice instances. They should be
5001*c689edbbSJens Wiklander    treated as read-only, and some are implemented through @property magic (but
5002*c689edbbSJens Wiklander    are still efficient to access due to internal caching).
5003*c689edbbSJens Wiklander
5004*c689edbbSJens Wiklander    Note: Prompts, help texts, and locations are stored in the Choice's
5005*c689edbbSJens Wiklander    MenuNode(s) rather than in the Choice itself. Check the MenuNode class and
5006*c689edbbSJens Wiklander    the Choice.nodes attribute. This organization matches the C tools.
5007*c689edbbSJens Wiklander
5008*c689edbbSJens Wiklander    name:
5009*c689edbbSJens Wiklander      The name of the choice, e.g. "FOO" for 'choice FOO', or None if the
5010*c689edbbSJens Wiklander      Choice has no name.
5011*c689edbbSJens Wiklander
5012*c689edbbSJens Wiklander    type:
5013*c689edbbSJens Wiklander      The type of the choice. One of BOOL, TRISTATE, UNKNOWN. UNKNOWN is for
5014*c689edbbSJens Wiklander      choices defined without a type where none of the contained symbols have a
5015*c689edbbSJens Wiklander      type either (otherwise the choice inherits the type of the first symbol
5016*c689edbbSJens Wiklander      defined with a type).
5017*c689edbbSJens Wiklander
5018*c689edbbSJens Wiklander      When running without modules (CONFIG_MODULES=n), TRISTATE choices
5019*c689edbbSJens Wiklander      magically change type to BOOL. This matches the C tools, and makes sense
5020*c689edbbSJens Wiklander      for menuconfig-like functionality.
5021*c689edbbSJens Wiklander
5022*c689edbbSJens Wiklander    orig_type:
5023*c689edbbSJens Wiklander      The type as given in the Kconfig file, without any magic applied. Used
5024*c689edbbSJens Wiklander      when printing the choice.
5025*c689edbbSJens Wiklander
5026*c689edbbSJens Wiklander    tri_value:
5027*c689edbbSJens Wiklander      The tristate value (mode) of the choice. A choice can be in one of three
5028*c689edbbSJens Wiklander      modes:
5029*c689edbbSJens Wiklander
5030*c689edbbSJens Wiklander        0 (n) - The choice is disabled and no symbols can be selected. For
5031*c689edbbSJens Wiklander                visible choices, this mode is only possible for choices with
5032*c689edbbSJens Wiklander                the 'optional' flag set (see kconfig-language.txt).
5033*c689edbbSJens Wiklander
5034*c689edbbSJens Wiklander        1 (m) - Any number of choice symbols can be set to m, the rest will
5035*c689edbbSJens Wiklander                be n.
5036*c689edbbSJens Wiklander
5037*c689edbbSJens Wiklander        2 (y) - One symbol will be y, the rest n.
5038*c689edbbSJens Wiklander
5039*c689edbbSJens Wiklander      Only tristate choices can be in m mode. The visibility of the choice is
5040*c689edbbSJens Wiklander      an upper bound on the mode, and the mode in turn is an upper bound on the
5041*c689edbbSJens Wiklander      visibility of the choice symbols.
5042*c689edbbSJens Wiklander
5043*c689edbbSJens Wiklander      To change the mode, use Choice.set_value().
5044*c689edbbSJens Wiklander
5045*c689edbbSJens Wiklander      Implementation note:
5046*c689edbbSJens Wiklander        The C tools internally represent choices as a type of symbol, with
5047*c689edbbSJens Wiklander        special-casing in many code paths. This is why there is a lot of
5048*c689edbbSJens Wiklander        similarity to Symbol. The value (mode) of a choice is really just a
5049*c689edbbSJens Wiklander        normal symbol value, and an implicit reverse dependency forces its
5050*c689edbbSJens Wiklander        lower bound to m for visible non-optional choices (the reverse
5051*c689edbbSJens Wiklander        dependency is 'm && <visibility>').
5052*c689edbbSJens Wiklander
5053*c689edbbSJens Wiklander        Symbols within choices get the choice propagated as a dependency to
5054*c689edbbSJens Wiklander        their properties. This turns the mode of the choice into an upper bound
5055*c689edbbSJens Wiklander        on e.g. the visibility of choice symbols, and explains the gotcha
5056*c689edbbSJens Wiklander        related to printing choice symbols mentioned in the module docstring.
5057*c689edbbSJens Wiklander
5058*c689edbbSJens Wiklander        Kconfiglib uses a separate Choice class only because it makes the code
5059*c689edbbSJens Wiklander        and interface less confusing (especially in a user-facing interface).
5060*c689edbbSJens Wiklander        Corresponding attributes have the same name in the Symbol and Choice
5061*c689edbbSJens Wiklander        classes, for consistency and compatibility.
5062*c689edbbSJens Wiklander
5063*c689edbbSJens Wiklander    str_value:
5064*c689edbbSJens Wiklander      Like choice.tri_value, but gives the value as one of the strings
5065*c689edbbSJens Wiklander      "n", "m", or "y"
5066*c689edbbSJens Wiklander
5067*c689edbbSJens Wiklander    user_value:
5068*c689edbbSJens Wiklander      The value (mode) selected by the user through Choice.set_value(). Either
5069*c689edbbSJens Wiklander      0, 1, or 2, or None if the user hasn't selected a mode. See
5070*c689edbbSJens Wiklander      Symbol.user_value.
5071*c689edbbSJens Wiklander
5072*c689edbbSJens Wiklander      WARNING: Do not assign directly to this. It will break things. Use
5073*c689edbbSJens Wiklander      Choice.set_value() instead.
5074*c689edbbSJens Wiklander
5075*c689edbbSJens Wiklander    assignable:
5076*c689edbbSJens Wiklander      See the symbol class documentation. Gives the assignable values (modes).
5077*c689edbbSJens Wiklander
5078*c689edbbSJens Wiklander    selection:
5079*c689edbbSJens Wiklander      The Symbol instance of the currently selected symbol. None if the Choice
5080*c689edbbSJens Wiklander      is not in y mode or has no selected symbol (due to unsatisfied
5081*c689edbbSJens Wiklander      dependencies on choice symbols).
5082*c689edbbSJens Wiklander
5083*c689edbbSJens Wiklander      WARNING: Do not assign directly to this. It will break things. Call
5084*c689edbbSJens Wiklander      sym.set_value(2) on the choice symbol you want to select instead.
5085*c689edbbSJens Wiklander
5086*c689edbbSJens Wiklander    user_selection:
5087*c689edbbSJens Wiklander      The symbol selected by the user (by setting it to y). Ignored if the
5088*c689edbbSJens Wiklander      choice is not in y mode, but still remembered so that the choice "snaps
5089*c689edbbSJens Wiklander      back" to the user selection if the mode is changed back to y. This might
5090*c689edbbSJens Wiklander      differ from 'selection' due to unsatisfied dependencies.
5091*c689edbbSJens Wiklander
5092*c689edbbSJens Wiklander      WARNING: Do not assign directly to this. It will break things. Call
5093*c689edbbSJens Wiklander      sym.set_value(2) on the choice symbol to be selected instead.
5094*c689edbbSJens Wiklander
5095*c689edbbSJens Wiklander    visibility:
5096*c689edbbSJens Wiklander      See the Symbol class documentation. Acts on the value (mode).
5097*c689edbbSJens Wiklander
5098*c689edbbSJens Wiklander    name_and_loc:
5099*c689edbbSJens Wiklander      Holds a string like
5100*c689edbbSJens Wiklander
5101*c689edbbSJens Wiklander        "<choice MY_CHOICE> (defined at foo/Kconfig:12)"
5102*c689edbbSJens Wiklander
5103*c689edbbSJens Wiklander      , giving the name of the choice and its definition location(s). If the
5104*c689edbbSJens Wiklander      choice has no name (isn't defined with 'choice MY_CHOICE'), then it will
5105*c689edbbSJens Wiklander      be shown as "<choice>" before the list of locations (always a single one
5106*c689edbbSJens Wiklander      in that case).
5107*c689edbbSJens Wiklander
5108*c689edbbSJens Wiklander    syms:
5109*c689edbbSJens Wiklander      List of symbols contained in the choice.
5110*c689edbbSJens Wiklander
5111*c689edbbSJens Wiklander      Obscure gotcha: If a symbol depends on the previous symbol within a
5112*c689edbbSJens Wiklander      choice so that an implicit menu is created, it won't be a choice symbol,
5113*c689edbbSJens Wiklander      and won't be included in 'syms'.
5114*c689edbbSJens Wiklander
5115*c689edbbSJens Wiklander    nodes:
5116*c689edbbSJens Wiklander      A list of MenuNodes for this choice. In practice, the list will probably
5117*c689edbbSJens Wiklander      always contain a single MenuNode, but it is possible to give a choice a
5118*c689edbbSJens Wiklander      name and define it in multiple locations.
5119*c689edbbSJens Wiklander
5120*c689edbbSJens Wiklander    defaults:
5121*c689edbbSJens Wiklander      List of (symbol, cond) tuples for the choice's 'defaults' properties. For
5122*c689edbbSJens Wiklander      example, 'default A if B && C' is represented as (A, (AND, B, C)). If
5123*c689edbbSJens Wiklander      there is no condition, 'cond' is self.kconfig.y.
5124*c689edbbSJens Wiklander
5125*c689edbbSJens Wiklander      Note that 'depends on' and parent dependencies are propagated to
5126*c689edbbSJens Wiklander      'default' conditions.
5127*c689edbbSJens Wiklander
5128*c689edbbSJens Wiklander    orig_defaults:
5129*c689edbbSJens Wiklander      See the corresponding attribute on the MenuNode class.
5130*c689edbbSJens Wiklander
5131*c689edbbSJens Wiklander    direct_dep:
5132*c689edbbSJens Wiklander      See Symbol.direct_dep.
5133*c689edbbSJens Wiklander
5134*c689edbbSJens Wiklander    referenced:
5135*c689edbbSJens Wiklander      A set() with all symbols referenced in the properties and property
5136*c689edbbSJens Wiklander      conditions of the choice.
5137*c689edbbSJens Wiklander
5138*c689edbbSJens Wiklander      Also includes dependencies from surrounding menus and ifs, because those
5139*c689edbbSJens Wiklander      get propagated to the choice (see the 'Intro to symbol values' section in
5140*c689edbbSJens Wiklander      the module docstring).
5141*c689edbbSJens Wiklander
5142*c689edbbSJens Wiklander    is_optional:
5143*c689edbbSJens Wiklander      True if the choice has the 'optional' flag set on it and can be in
5144*c689edbbSJens Wiklander      n mode.
5145*c689edbbSJens Wiklander
5146*c689edbbSJens Wiklander    kconfig:
5147*c689edbbSJens Wiklander      The Kconfig instance this choice is from.
5148*c689edbbSJens Wiklander    """
5149*c689edbbSJens Wiklander    __slots__ = (
5150*c689edbbSJens Wiklander        "_cached_assignable",
5151*c689edbbSJens Wiklander        "_cached_selection",
5152*c689edbbSJens Wiklander        "_cached_vis",
5153*c689edbbSJens Wiklander        "_dependents",
5154*c689edbbSJens Wiklander        "_visited",
5155*c689edbbSJens Wiklander        "_was_set",
5156*c689edbbSJens Wiklander        "defaults",
5157*c689edbbSJens Wiklander        "direct_dep",
5158*c689edbbSJens Wiklander        "is_constant",
5159*c689edbbSJens Wiklander        "is_optional",
5160*c689edbbSJens Wiklander        "kconfig",
5161*c689edbbSJens Wiklander        "name",
5162*c689edbbSJens Wiklander        "nodes",
5163*c689edbbSJens Wiklander        "orig_type",
5164*c689edbbSJens Wiklander        "syms",
5165*c689edbbSJens Wiklander        "user_selection",
5166*c689edbbSJens Wiklander        "user_value",
5167*c689edbbSJens Wiklander    )
5168*c689edbbSJens Wiklander
5169*c689edbbSJens Wiklander    #
5170*c689edbbSJens Wiklander    # Public interface
5171*c689edbbSJens Wiklander    #
5172*c689edbbSJens Wiklander
5173*c689edbbSJens Wiklander    @property
5174*c689edbbSJens Wiklander    def type(self):
5175*c689edbbSJens Wiklander        """
5176*c689edbbSJens Wiklander        Returns the type of the choice. See Symbol.type.
5177*c689edbbSJens Wiklander        """
5178*c689edbbSJens Wiklander        if self.orig_type is TRISTATE and not self.kconfig.modules.tri_value:
5179*c689edbbSJens Wiklander            return BOOL
5180*c689edbbSJens Wiklander        return self.orig_type
5181*c689edbbSJens Wiklander
5182*c689edbbSJens Wiklander    @property
5183*c689edbbSJens Wiklander    def str_value(self):
5184*c689edbbSJens Wiklander        """
5185*c689edbbSJens Wiklander        See the class documentation.
5186*c689edbbSJens Wiklander        """
5187*c689edbbSJens Wiklander        return TRI_TO_STR[self.tri_value]
5188*c689edbbSJens Wiklander
5189*c689edbbSJens Wiklander    @property
5190*c689edbbSJens Wiklander    def tri_value(self):
5191*c689edbbSJens Wiklander        """
5192*c689edbbSJens Wiklander        See the class documentation.
5193*c689edbbSJens Wiklander        """
5194*c689edbbSJens Wiklander        # This emulates a reverse dependency of 'm && visibility' for
5195*c689edbbSJens Wiklander        # non-optional choices, which is how the C implementation does it
5196*c689edbbSJens Wiklander
5197*c689edbbSJens Wiklander        val = 0 if self.is_optional else 1
5198*c689edbbSJens Wiklander
5199*c689edbbSJens Wiklander        if self.user_value is not None:
5200*c689edbbSJens Wiklander            val = max(val, self.user_value)
5201*c689edbbSJens Wiklander
5202*c689edbbSJens Wiklander        # Warning: See Symbol._rec_invalidate(), and note that this is a hidden
5203*c689edbbSJens Wiklander        # function call (property magic)
5204*c689edbbSJens Wiklander        val = min(val, self.visibility)
5205*c689edbbSJens Wiklander
5206*c689edbbSJens Wiklander        # Promote m to y for boolean choices
5207*c689edbbSJens Wiklander        return 2 if val == 1 and self.type is BOOL else val
5208*c689edbbSJens Wiklander
5209*c689edbbSJens Wiklander    @property
5210*c689edbbSJens Wiklander    def assignable(self):
5211*c689edbbSJens Wiklander        """
5212*c689edbbSJens Wiklander        See the class documentation.
5213*c689edbbSJens Wiklander        """
5214*c689edbbSJens Wiklander        if self._cached_assignable is None:
5215*c689edbbSJens Wiklander            self._cached_assignable = self._assignable()
5216*c689edbbSJens Wiklander        return self._cached_assignable
5217*c689edbbSJens Wiklander
5218*c689edbbSJens Wiklander    @property
5219*c689edbbSJens Wiklander    def visibility(self):
5220*c689edbbSJens Wiklander        """
5221*c689edbbSJens Wiklander        See the class documentation.
5222*c689edbbSJens Wiklander        """
5223*c689edbbSJens Wiklander        if self._cached_vis is None:
5224*c689edbbSJens Wiklander            self._cached_vis = _visibility(self)
5225*c689edbbSJens Wiklander        return self._cached_vis
5226*c689edbbSJens Wiklander
5227*c689edbbSJens Wiklander    @property
5228*c689edbbSJens Wiklander    def name_and_loc(self):
5229*c689edbbSJens Wiklander        """
5230*c689edbbSJens Wiklander        See the class documentation.
5231*c689edbbSJens Wiklander        """
5232*c689edbbSJens Wiklander        # Reuse the expression format, which is '<choice (name, if any)>'.
5233*c689edbbSJens Wiklander        return standard_sc_expr_str(self) + " " + _locs(self)
5234*c689edbbSJens Wiklander
5235*c689edbbSJens Wiklander    @property
5236*c689edbbSJens Wiklander    def selection(self):
5237*c689edbbSJens Wiklander        """
5238*c689edbbSJens Wiklander        See the class documentation.
5239*c689edbbSJens Wiklander        """
5240*c689edbbSJens Wiklander        if self._cached_selection is _NO_CACHED_SELECTION:
5241*c689edbbSJens Wiklander            self._cached_selection = self._selection()
5242*c689edbbSJens Wiklander        return self._cached_selection
5243*c689edbbSJens Wiklander
5244*c689edbbSJens Wiklander    def set_value(self, value):
5245*c689edbbSJens Wiklander        """
5246*c689edbbSJens Wiklander        Sets the user value (mode) of the choice. Like for Symbol.set_value(),
5247*c689edbbSJens Wiklander        the visibility might truncate the value. Choices without the 'optional'
5248*c689edbbSJens Wiklander        attribute (is_optional) can never be in n mode, but 0/"n" is still
5249*c689edbbSJens Wiklander        accepted since it's not a malformed value (though it will have no
5250*c689edbbSJens Wiklander        effect).
5251*c689edbbSJens Wiklander
5252*c689edbbSJens Wiklander        Returns True if the value is valid for the type of the choice, and
5253*c689edbbSJens Wiklander        False otherwise. This only looks at the form of the value. Check the
5254*c689edbbSJens Wiklander        Choice.assignable attribute to see what values are currently in range
5255*c689edbbSJens Wiklander        and would actually be reflected in the mode of the choice.
5256*c689edbbSJens Wiklander        """
5257*c689edbbSJens Wiklander        if value in STR_TO_TRI:
5258*c689edbbSJens Wiklander            value = STR_TO_TRI[value]
5259*c689edbbSJens Wiklander
5260*c689edbbSJens Wiklander        if value == self.user_value:
5261*c689edbbSJens Wiklander            # We know the value must be valid if it was successfully set
5262*c689edbbSJens Wiklander            # previously
5263*c689edbbSJens Wiklander            self._was_set = True
5264*c689edbbSJens Wiklander            return True
5265*c689edbbSJens Wiklander
5266*c689edbbSJens Wiklander        if not (self.orig_type is BOOL     and value in (2, 0) or
5267*c689edbbSJens Wiklander                self.orig_type is TRISTATE and value in TRI_TO_STR):
5268*c689edbbSJens Wiklander
5269*c689edbbSJens Wiklander            # Display tristate values as n, m, y in the warning
5270*c689edbbSJens Wiklander            self.kconfig._warn(
5271*c689edbbSJens Wiklander                "the value {} is invalid for {}, which has type {} -- "
5272*c689edbbSJens Wiklander                "assignment ignored"
5273*c689edbbSJens Wiklander                .format(TRI_TO_STR[value] if value in TRI_TO_STR else
5274*c689edbbSJens Wiklander                            "'{}'".format(value),
5275*c689edbbSJens Wiklander                        self.name_and_loc, TYPE_TO_STR[self.orig_type]))
5276*c689edbbSJens Wiklander
5277*c689edbbSJens Wiklander            return False
5278*c689edbbSJens Wiklander
5279*c689edbbSJens Wiklander        self.user_value = value
5280*c689edbbSJens Wiklander        self._was_set = True
5281*c689edbbSJens Wiklander        self._rec_invalidate()
5282*c689edbbSJens Wiklander
5283*c689edbbSJens Wiklander        return True
5284*c689edbbSJens Wiklander
5285*c689edbbSJens Wiklander    def unset_value(self):
5286*c689edbbSJens Wiklander        """
5287*c689edbbSJens Wiklander        Resets the user value (mode) and user selection of the Choice, as if
5288*c689edbbSJens Wiklander        the user had never touched the mode or any of the choice symbols.
5289*c689edbbSJens Wiklander        """
5290*c689edbbSJens Wiklander        if self.user_value is not None or self.user_selection:
5291*c689edbbSJens Wiklander            self.user_value = self.user_selection = None
5292*c689edbbSJens Wiklander            self._rec_invalidate()
5293*c689edbbSJens Wiklander
5294*c689edbbSJens Wiklander    @property
5295*c689edbbSJens Wiklander    def referenced(self):
5296*c689edbbSJens Wiklander        """
5297*c689edbbSJens Wiklander        See the class documentation.
5298*c689edbbSJens Wiklander        """
5299*c689edbbSJens Wiklander        return {item for node in self.nodes for item in node.referenced}
5300*c689edbbSJens Wiklander
5301*c689edbbSJens Wiklander    @property
5302*c689edbbSJens Wiklander    def orig_defaults(self):
5303*c689edbbSJens Wiklander        """
5304*c689edbbSJens Wiklander        See the class documentation.
5305*c689edbbSJens Wiklander        """
5306*c689edbbSJens Wiklander        return [d for node in self.nodes for d in node.orig_defaults]
5307*c689edbbSJens Wiklander
5308*c689edbbSJens Wiklander    def __repr__(self):
5309*c689edbbSJens Wiklander        """
5310*c689edbbSJens Wiklander        Returns a string with information about the choice when it is evaluated
5311*c689edbbSJens Wiklander        on e.g. the interactive Python prompt.
5312*c689edbbSJens Wiklander        """
5313*c689edbbSJens Wiklander        fields = ["choice " + self.name if self.name else "choice",
5314*c689edbbSJens Wiklander                  TYPE_TO_STR[self.type]]
5315*c689edbbSJens Wiklander        add = fields.append
5316*c689edbbSJens Wiklander
5317*c689edbbSJens Wiklander        for node in self.nodes:
5318*c689edbbSJens Wiklander            if node.prompt:
5319*c689edbbSJens Wiklander                add('"{}"'.format(node.prompt[0]))
5320*c689edbbSJens Wiklander
5321*c689edbbSJens Wiklander        add("mode " + self.str_value)
5322*c689edbbSJens Wiklander
5323*c689edbbSJens Wiklander        if self.user_value is not None:
5324*c689edbbSJens Wiklander            add('user mode {}'.format(TRI_TO_STR[self.user_value]))
5325*c689edbbSJens Wiklander
5326*c689edbbSJens Wiklander        if self.selection:
5327*c689edbbSJens Wiklander            add("{} selected".format(self.selection.name))
5328*c689edbbSJens Wiklander
5329*c689edbbSJens Wiklander        if self.user_selection:
5330*c689edbbSJens Wiklander            user_sel_str = "{} selected by user" \
5331*c689edbbSJens Wiklander                           .format(self.user_selection.name)
5332*c689edbbSJens Wiklander
5333*c689edbbSJens Wiklander            if self.selection is not self.user_selection:
5334*c689edbbSJens Wiklander                user_sel_str += " (overridden)"
5335*c689edbbSJens Wiklander
5336*c689edbbSJens Wiklander            add(user_sel_str)
5337*c689edbbSJens Wiklander
5338*c689edbbSJens Wiklander        add("visibility " + TRI_TO_STR[self.visibility])
5339*c689edbbSJens Wiklander
5340*c689edbbSJens Wiklander        if self.is_optional:
5341*c689edbbSJens Wiklander            add("optional")
5342*c689edbbSJens Wiklander
5343*c689edbbSJens Wiklander        for node in self.nodes:
5344*c689edbbSJens Wiklander            add("{}:{}".format(node.filename, node.linenr))
5345*c689edbbSJens Wiklander
5346*c689edbbSJens Wiklander        return "<{}>".format(", ".join(fields))
5347*c689edbbSJens Wiklander
5348*c689edbbSJens Wiklander    def __str__(self):
5349*c689edbbSJens Wiklander        """
5350*c689edbbSJens Wiklander        Returns a string representation of the choice when it is printed.
5351*c689edbbSJens Wiklander        Matches the Kconfig format (though without the contained choice
5352*c689edbbSJens Wiklander        symbols), with any parent dependencies propagated to the 'depends on'
5353*c689edbbSJens Wiklander        condition.
5354*c689edbbSJens Wiklander
5355*c689edbbSJens Wiklander        The returned string does not end in a newline.
5356*c689edbbSJens Wiklander
5357*c689edbbSJens Wiklander        See Symbol.__str__() as well.
5358*c689edbbSJens Wiklander        """
5359*c689edbbSJens Wiklander        return self.custom_str(standard_sc_expr_str)
5360*c689edbbSJens Wiklander
5361*c689edbbSJens Wiklander    def custom_str(self, sc_expr_str_fn):
5362*c689edbbSJens Wiklander        """
5363*c689edbbSJens Wiklander        Works like Choice.__str__(), but allows a custom format to be used for
5364*c689edbbSJens Wiklander        all symbol/choice references. See expr_str().
5365*c689edbbSJens Wiklander        """
5366*c689edbbSJens Wiklander        return "\n\n".join(node.custom_str(sc_expr_str_fn)
5367*c689edbbSJens Wiklander                           for node in self.nodes)
5368*c689edbbSJens Wiklander
5369*c689edbbSJens Wiklander    #
5370*c689edbbSJens Wiklander    # Private methods
5371*c689edbbSJens Wiklander    #
5372*c689edbbSJens Wiklander
5373*c689edbbSJens Wiklander    def __init__(self):
5374*c689edbbSJens Wiklander        """
5375*c689edbbSJens Wiklander        Choice constructor -- not intended to be called directly by Kconfiglib
5376*c689edbbSJens Wiklander        clients.
5377*c689edbbSJens Wiklander        """
5378*c689edbbSJens Wiklander        # These attributes are always set on the instance from outside and
5379*c689edbbSJens Wiklander        # don't need defaults:
5380*c689edbbSJens Wiklander        #   direct_dep
5381*c689edbbSJens Wiklander        #   kconfig
5382*c689edbbSJens Wiklander
5383*c689edbbSJens Wiklander        # - UNKNOWN == 0
5384*c689edbbSJens Wiklander        # - _visited is used during dep. loop detection
5385*c689edbbSJens Wiklander        self.orig_type = self._visited = 0
5386*c689edbbSJens Wiklander
5387*c689edbbSJens Wiklander        self.nodes = []
5388*c689edbbSJens Wiklander
5389*c689edbbSJens Wiklander        self.syms = []
5390*c689edbbSJens Wiklander        self.defaults = []
5391*c689edbbSJens Wiklander
5392*c689edbbSJens Wiklander        self.name = \
5393*c689edbbSJens Wiklander        self.user_value = self.user_selection = \
5394*c689edbbSJens Wiklander        self._cached_vis = self._cached_assignable = None
5395*c689edbbSJens Wiklander
5396*c689edbbSJens Wiklander        self._cached_selection = _NO_CACHED_SELECTION
5397*c689edbbSJens Wiklander
5398*c689edbbSJens Wiklander        # is_constant is checked by _depend_on(). Just set it to avoid having
5399*c689edbbSJens Wiklander        # to special-case choices.
5400*c689edbbSJens Wiklander        self.is_constant = self.is_optional = False
5401*c689edbbSJens Wiklander
5402*c689edbbSJens Wiklander        # See Kconfig._build_dep()
5403*c689edbbSJens Wiklander        self._dependents = set()
5404*c689edbbSJens Wiklander
5405*c689edbbSJens Wiklander    def _assignable(self):
5406*c689edbbSJens Wiklander        # Worker function for the 'assignable' attribute
5407*c689edbbSJens Wiklander
5408*c689edbbSJens Wiklander        # Warning: See Symbol._rec_invalidate(), and note that this is a hidden
5409*c689edbbSJens Wiklander        # function call (property magic)
5410*c689edbbSJens Wiklander        vis = self.visibility
5411*c689edbbSJens Wiklander
5412*c689edbbSJens Wiklander        if not vis:
5413*c689edbbSJens Wiklander            return ()
5414*c689edbbSJens Wiklander
5415*c689edbbSJens Wiklander        if vis == 2:
5416*c689edbbSJens Wiklander            if not self.is_optional:
5417*c689edbbSJens Wiklander                return (2,) if self.type is BOOL else (1, 2)
5418*c689edbbSJens Wiklander            return (0, 2) if self.type is BOOL else (0, 1, 2)
5419*c689edbbSJens Wiklander
5420*c689edbbSJens Wiklander        # vis == 1
5421*c689edbbSJens Wiklander
5422*c689edbbSJens Wiklander        return (0, 1) if self.is_optional else (1,)
5423*c689edbbSJens Wiklander
5424*c689edbbSJens Wiklander    def _selection(self):
5425*c689edbbSJens Wiklander        # Worker function for the 'selection' attribute
5426*c689edbbSJens Wiklander
5427*c689edbbSJens Wiklander        # Warning: See Symbol._rec_invalidate(), and note that this is a hidden
5428*c689edbbSJens Wiklander        # function call (property magic)
5429*c689edbbSJens Wiklander        if self.tri_value != 2:
5430*c689edbbSJens Wiklander            # Not in y mode, so no selection
5431*c689edbbSJens Wiklander            return None
5432*c689edbbSJens Wiklander
5433*c689edbbSJens Wiklander        # Use the user selection if it's visible
5434*c689edbbSJens Wiklander        if self.user_selection and self.user_selection.visibility:
5435*c689edbbSJens Wiklander            return self.user_selection
5436*c689edbbSJens Wiklander
5437*c689edbbSJens Wiklander        # Otherwise, check if we have a default
5438*c689edbbSJens Wiklander        return self._selection_from_defaults()
5439*c689edbbSJens Wiklander
5440*c689edbbSJens Wiklander    def _selection_from_defaults(self):
5441*c689edbbSJens Wiklander        # Check if we have a default
5442*c689edbbSJens Wiklander        for sym, cond in self.defaults:
5443*c689edbbSJens Wiklander            # The default symbol must be visible too
5444*c689edbbSJens Wiklander            if expr_value(cond) and sym.visibility:
5445*c689edbbSJens Wiklander                return sym
5446*c689edbbSJens Wiklander
5447*c689edbbSJens Wiklander        # Otherwise, pick the first visible symbol, if any
5448*c689edbbSJens Wiklander        for sym in self.syms:
5449*c689edbbSJens Wiklander            if sym.visibility:
5450*c689edbbSJens Wiklander                return sym
5451*c689edbbSJens Wiklander
5452*c689edbbSJens Wiklander        # Couldn't find a selection
5453*c689edbbSJens Wiklander        return None
5454*c689edbbSJens Wiklander
5455*c689edbbSJens Wiklander    def _invalidate(self):
5456*c689edbbSJens Wiklander        self._cached_vis = self._cached_assignable = None
5457*c689edbbSJens Wiklander        self._cached_selection = _NO_CACHED_SELECTION
5458*c689edbbSJens Wiklander
5459*c689edbbSJens Wiklander    def _rec_invalidate(self):
5460*c689edbbSJens Wiklander        # See Symbol._rec_invalidate()
5461*c689edbbSJens Wiklander
5462*c689edbbSJens Wiklander        self._invalidate()
5463*c689edbbSJens Wiklander
5464*c689edbbSJens Wiklander        for item in self._dependents:
5465*c689edbbSJens Wiklander            if item._cached_vis is not None:
5466*c689edbbSJens Wiklander                item._rec_invalidate()
5467*c689edbbSJens Wiklander
5468*c689edbbSJens Wiklander
5469*c689edbbSJens Wiklanderclass MenuNode(object):
5470*c689edbbSJens Wiklander    """
5471*c689edbbSJens Wiklander    Represents a menu node in the configuration. This corresponds to an entry
5472*c689edbbSJens Wiklander    in e.g. the 'make menuconfig' interface, though non-visible choices, menus,
5473*c689edbbSJens Wiklander    and comments also get menu nodes. If a symbol or choice is defined in
5474*c689edbbSJens Wiklander    multiple locations, it gets one menu node for each location.
5475*c689edbbSJens Wiklander
5476*c689edbbSJens Wiklander    The top-level menu node, corresponding to the implicit top-level menu, is
5477*c689edbbSJens Wiklander    available in Kconfig.top_node.
5478*c689edbbSJens Wiklander
5479*c689edbbSJens Wiklander    The menu nodes for a Symbol or Choice can be found in the
5480*c689edbbSJens Wiklander    Symbol/Choice.nodes attribute. Menus and comments are represented as plain
5481*c689edbbSJens Wiklander    menu nodes, with their text stored in the prompt attribute (prompt[0]).
5482*c689edbbSJens Wiklander    This mirrors the C implementation.
5483*c689edbbSJens Wiklander
5484*c689edbbSJens Wiklander    The following attributes are available on MenuNode instances. They should
5485*c689edbbSJens Wiklander    be viewed as read-only.
5486*c689edbbSJens Wiklander
5487*c689edbbSJens Wiklander    item:
5488*c689edbbSJens Wiklander      Either a Symbol, a Choice, or one of the constants MENU and COMMENT.
5489*c689edbbSJens Wiklander      Menus and comments are represented as plain menu nodes. Ifs are collapsed
5490*c689edbbSJens Wiklander      (matching the C implementation) and do not appear in the final menu tree.
5491*c689edbbSJens Wiklander
5492*c689edbbSJens Wiklander    next:
5493*c689edbbSJens Wiklander      The following menu node. None if there is no following node.
5494*c689edbbSJens Wiklander
5495*c689edbbSJens Wiklander    list:
5496*c689edbbSJens Wiklander      The first child menu node. None if there are no children.
5497*c689edbbSJens Wiklander
5498*c689edbbSJens Wiklander      Choices and menus naturally have children, but Symbols can also have
5499*c689edbbSJens Wiklander      children because of menus created automatically from dependencies (see
5500*c689edbbSJens Wiklander      kconfig-language.txt).
5501*c689edbbSJens Wiklander
5502*c689edbbSJens Wiklander    parent:
5503*c689edbbSJens Wiklander      The parent menu node. None if there is no parent.
5504*c689edbbSJens Wiklander
5505*c689edbbSJens Wiklander    prompt:
5506*c689edbbSJens Wiklander      A (string, cond) tuple with the prompt for the menu node and its
5507*c689edbbSJens Wiklander      conditional expression (which is self.kconfig.y if there is no
5508*c689edbbSJens Wiklander      condition). None if there is no prompt.
5509*c689edbbSJens Wiklander
5510*c689edbbSJens Wiklander      For symbols and choices, the prompt is stored in the MenuNode rather than
5511*c689edbbSJens Wiklander      the Symbol or Choice instance. For menus and comments, the prompt holds
5512*c689edbbSJens Wiklander      the text.
5513*c689edbbSJens Wiklander
5514*c689edbbSJens Wiklander    defaults:
5515*c689edbbSJens Wiklander      The 'default' properties for this particular menu node. See
5516*c689edbbSJens Wiklander      symbol.defaults.
5517*c689edbbSJens Wiklander
5518*c689edbbSJens Wiklander      When evaluating defaults, you should use Symbol/Choice.defaults instead,
5519*c689edbbSJens Wiklander      as it include properties from all menu nodes (a symbol/choice can have
5520*c689edbbSJens Wiklander      multiple definition locations/menu nodes). MenuNode.defaults is meant for
5521*c689edbbSJens Wiklander      documentation generation.
5522*c689edbbSJens Wiklander
5523*c689edbbSJens Wiklander    selects:
5524*c689edbbSJens Wiklander      Like MenuNode.defaults, for selects.
5525*c689edbbSJens Wiklander
5526*c689edbbSJens Wiklander    implies:
5527*c689edbbSJens Wiklander      Like MenuNode.defaults, for implies.
5528*c689edbbSJens Wiklander
5529*c689edbbSJens Wiklander    ranges:
5530*c689edbbSJens Wiklander      Like MenuNode.defaults, for ranges.
5531*c689edbbSJens Wiklander
5532*c689edbbSJens Wiklander    orig_prompt:
5533*c689edbbSJens Wiklander    orig_defaults:
5534*c689edbbSJens Wiklander    orig_selects:
5535*c689edbbSJens Wiklander    orig_implies:
5536*c689edbbSJens Wiklander    orig_ranges:
5537*c689edbbSJens Wiklander      These work the like the corresponding attributes without orig_*, but omit
5538*c689edbbSJens Wiklander      any dependencies propagated from 'depends on' and surrounding 'if's (the
5539*c689edbbSJens Wiklander      direct dependencies, stored in MenuNode.dep).
5540*c689edbbSJens Wiklander
5541*c689edbbSJens Wiklander      One use for this is generating less cluttered documentation, by only
5542*c689edbbSJens Wiklander      showing the direct dependencies in one place.
5543*c689edbbSJens Wiklander
5544*c689edbbSJens Wiklander    help:
5545*c689edbbSJens Wiklander      The help text for the menu node for Symbols and Choices. None if there is
5546*c689edbbSJens Wiklander      no help text. Always stored in the node rather than the Symbol or Choice.
5547*c689edbbSJens Wiklander      It is possible to have a separate help text at each location if a symbol
5548*c689edbbSJens Wiklander      is defined in multiple locations.
5549*c689edbbSJens Wiklander
5550*c689edbbSJens Wiklander      Trailing whitespace (including a final newline) is stripped from the help
5551*c689edbbSJens Wiklander      text. This was not the case before Kconfiglib 10.21.0, where the format
5552*c689edbbSJens Wiklander      was undocumented.
5553*c689edbbSJens Wiklander
5554*c689edbbSJens Wiklander    dep:
5555*c689edbbSJens Wiklander      The direct ('depends on') dependencies for the menu node, or
5556*c689edbbSJens Wiklander      self.kconfig.y if there are no direct dependencies.
5557*c689edbbSJens Wiklander
5558*c689edbbSJens Wiklander      This attribute includes any dependencies from surrounding menus and ifs.
5559*c689edbbSJens Wiklander      Those get propagated to the direct dependencies, and the resulting direct
5560*c689edbbSJens Wiklander      dependencies in turn get propagated to the conditions of all properties.
5561*c689edbbSJens Wiklander
5562*c689edbbSJens Wiklander      If a symbol or choice is defined in multiple locations, only the
5563*c689edbbSJens Wiklander      properties defined at a particular location get the corresponding
5564*c689edbbSJens Wiklander      MenuNode.dep dependencies propagated to them.
5565*c689edbbSJens Wiklander
5566*c689edbbSJens Wiklander    visibility:
5567*c689edbbSJens Wiklander      The 'visible if' dependencies for the menu node (which must represent a
5568*c689edbbSJens Wiklander      menu), or self.kconfig.y if there are no 'visible if' dependencies.
5569*c689edbbSJens Wiklander      'visible if' dependencies are recursively propagated to the prompts of
5570*c689edbbSJens Wiklander      symbols and choices within the menu.
5571*c689edbbSJens Wiklander
5572*c689edbbSJens Wiklander    referenced:
5573*c689edbbSJens Wiklander      A set() with all symbols and choices referenced in the properties and
5574*c689edbbSJens Wiklander      property conditions of the menu node.
5575*c689edbbSJens Wiklander
5576*c689edbbSJens Wiklander      Also includes dependencies inherited from surrounding menus and ifs.
5577*c689edbbSJens Wiklander      Choices appear in the dependencies of choice symbols.
5578*c689edbbSJens Wiklander
5579*c689edbbSJens Wiklander    is_menuconfig:
5580*c689edbbSJens Wiklander      Set to True if the children of the menu node should be displayed in a
5581*c689edbbSJens Wiklander      separate menu. This is the case for the following items:
5582*c689edbbSJens Wiklander
5583*c689edbbSJens Wiklander        - Menus (node.item == MENU)
5584*c689edbbSJens Wiklander
5585*c689edbbSJens Wiklander        - Choices
5586*c689edbbSJens Wiklander
5587*c689edbbSJens Wiklander        - Symbols defined with the 'menuconfig' keyword. The children come from
5588*c689edbbSJens Wiklander          implicitly created submenus, and should be displayed in a separate
5589*c689edbbSJens Wiklander          menu rather than being indented.
5590*c689edbbSJens Wiklander
5591*c689edbbSJens Wiklander      'is_menuconfig' is just a hint on how to display the menu node. It's
5592*c689edbbSJens Wiklander      ignored internally by Kconfiglib, except when printing symbols.
5593*c689edbbSJens Wiklander
5594*c689edbbSJens Wiklander    filename/linenr:
5595*c689edbbSJens Wiklander      The location where the menu node appears. The filename is relative to
5596*c689edbbSJens Wiklander      $srctree (or to the current directory if $srctree isn't set), except
5597*c689edbbSJens Wiklander      absolute paths are used for paths outside $srctree.
5598*c689edbbSJens Wiklander
5599*c689edbbSJens Wiklander    include_path:
5600*c689edbbSJens Wiklander      A tuple of (filename, linenr) tuples, giving the locations of the
5601*c689edbbSJens Wiklander      'source' statements via which the Kconfig file containing this menu node
5602*c689edbbSJens Wiklander      was included. The first element is the location of the 'source' statement
5603*c689edbbSJens Wiklander      in the top-level Kconfig file passed to Kconfig.__init__(), etc.
5604*c689edbbSJens Wiklander
5605*c689edbbSJens Wiklander      Note that the Kconfig file of the menu node itself isn't included. Check
5606*c689edbbSJens Wiklander      'filename' and 'linenr' for that.
5607*c689edbbSJens Wiklander
5608*c689edbbSJens Wiklander    kconfig:
5609*c689edbbSJens Wiklander      The Kconfig instance the menu node is from.
5610*c689edbbSJens Wiklander    """
5611*c689edbbSJens Wiklander    __slots__ = (
5612*c689edbbSJens Wiklander        "dep",
5613*c689edbbSJens Wiklander        "filename",
5614*c689edbbSJens Wiklander        "help",
5615*c689edbbSJens Wiklander        "include_path",
5616*c689edbbSJens Wiklander        "is_menuconfig",
5617*c689edbbSJens Wiklander        "item",
5618*c689edbbSJens Wiklander        "kconfig",
5619*c689edbbSJens Wiklander        "linenr",
5620*c689edbbSJens Wiklander        "list",
5621*c689edbbSJens Wiklander        "next",
5622*c689edbbSJens Wiklander        "parent",
5623*c689edbbSJens Wiklander        "prompt",
5624*c689edbbSJens Wiklander        "visibility",
5625*c689edbbSJens Wiklander
5626*c689edbbSJens Wiklander        # Properties
5627*c689edbbSJens Wiklander        "defaults",
5628*c689edbbSJens Wiklander        "selects",
5629*c689edbbSJens Wiklander        "implies",
5630*c689edbbSJens Wiklander        "ranges",
5631*c689edbbSJens Wiklander    )
5632*c689edbbSJens Wiklander
5633*c689edbbSJens Wiklander    def __init__(self):
5634*c689edbbSJens Wiklander        # Properties defined on this particular menu node. A local 'depends on'
5635*c689edbbSJens Wiklander        # only applies to these, in case a symbol is defined in multiple
5636*c689edbbSJens Wiklander        # locations.
5637*c689edbbSJens Wiklander        self.defaults = []
5638*c689edbbSJens Wiklander        self.selects = []
5639*c689edbbSJens Wiklander        self.implies = []
5640*c689edbbSJens Wiklander        self.ranges = []
5641*c689edbbSJens Wiklander
5642*c689edbbSJens Wiklander    @property
5643*c689edbbSJens Wiklander    def orig_prompt(self):
5644*c689edbbSJens Wiklander        """
5645*c689edbbSJens Wiklander        See the class documentation.
5646*c689edbbSJens Wiklander        """
5647*c689edbbSJens Wiklander        if not self.prompt:
5648*c689edbbSJens Wiklander            return None
5649*c689edbbSJens Wiklander        return (self.prompt[0], self._strip_dep(self.prompt[1]))
5650*c689edbbSJens Wiklander
5651*c689edbbSJens Wiklander    @property
5652*c689edbbSJens Wiklander    def orig_defaults(self):
5653*c689edbbSJens Wiklander        """
5654*c689edbbSJens Wiklander        See the class documentation.
5655*c689edbbSJens Wiklander        """
5656*c689edbbSJens Wiklander        return [(default, self._strip_dep(cond))
5657*c689edbbSJens Wiklander                for default, cond in self.defaults]
5658*c689edbbSJens Wiklander
5659*c689edbbSJens Wiklander    @property
5660*c689edbbSJens Wiklander    def orig_selects(self):
5661*c689edbbSJens Wiklander        """
5662*c689edbbSJens Wiklander        See the class documentation.
5663*c689edbbSJens Wiklander        """
5664*c689edbbSJens Wiklander        return [(select, self._strip_dep(cond))
5665*c689edbbSJens Wiklander                for select, cond in self.selects]
5666*c689edbbSJens Wiklander
5667*c689edbbSJens Wiklander    @property
5668*c689edbbSJens Wiklander    def orig_implies(self):
5669*c689edbbSJens Wiklander        """
5670*c689edbbSJens Wiklander        See the class documentation.
5671*c689edbbSJens Wiklander        """
5672*c689edbbSJens Wiklander        return [(imply, self._strip_dep(cond))
5673*c689edbbSJens Wiklander                for imply, cond in self.implies]
5674*c689edbbSJens Wiklander
5675*c689edbbSJens Wiklander    @property
5676*c689edbbSJens Wiklander    def orig_ranges(self):
5677*c689edbbSJens Wiklander        """
5678*c689edbbSJens Wiklander        See the class documentation.
5679*c689edbbSJens Wiklander        """
5680*c689edbbSJens Wiklander        return [(low, high, self._strip_dep(cond))
5681*c689edbbSJens Wiklander                for low, high, cond in self.ranges]
5682*c689edbbSJens Wiklander
5683*c689edbbSJens Wiklander    @property
5684*c689edbbSJens Wiklander    def referenced(self):
5685*c689edbbSJens Wiklander        """
5686*c689edbbSJens Wiklander        See the class documentation.
5687*c689edbbSJens Wiklander        """
5688*c689edbbSJens Wiklander        # self.dep is included to catch dependencies from a lone 'depends on'
5689*c689edbbSJens Wiklander        # when there are no properties to propagate it to
5690*c689edbbSJens Wiklander        res = expr_items(self.dep)
5691*c689edbbSJens Wiklander
5692*c689edbbSJens Wiklander        if self.prompt:
5693*c689edbbSJens Wiklander            res |= expr_items(self.prompt[1])
5694*c689edbbSJens Wiklander
5695*c689edbbSJens Wiklander        if self.item is MENU:
5696*c689edbbSJens Wiklander            res |= expr_items(self.visibility)
5697*c689edbbSJens Wiklander
5698*c689edbbSJens Wiklander        for value, cond in self.defaults:
5699*c689edbbSJens Wiklander            res |= expr_items(value)
5700*c689edbbSJens Wiklander            res |= expr_items(cond)
5701*c689edbbSJens Wiklander
5702*c689edbbSJens Wiklander        for value, cond in self.selects:
5703*c689edbbSJens Wiklander            res.add(value)
5704*c689edbbSJens Wiklander            res |= expr_items(cond)
5705*c689edbbSJens Wiklander
5706*c689edbbSJens Wiklander        for value, cond in self.implies:
5707*c689edbbSJens Wiklander            res.add(value)
5708*c689edbbSJens Wiklander            res |= expr_items(cond)
5709*c689edbbSJens Wiklander
5710*c689edbbSJens Wiklander        for low, high, cond in self.ranges:
5711*c689edbbSJens Wiklander            res.add(low)
5712*c689edbbSJens Wiklander            res.add(high)
5713*c689edbbSJens Wiklander            res |= expr_items(cond)
5714*c689edbbSJens Wiklander
5715*c689edbbSJens Wiklander        return res
5716*c689edbbSJens Wiklander
5717*c689edbbSJens Wiklander    def __repr__(self):
5718*c689edbbSJens Wiklander        """
5719*c689edbbSJens Wiklander        Returns a string with information about the menu node when it is
5720*c689edbbSJens Wiklander        evaluated on e.g. the interactive Python prompt.
5721*c689edbbSJens Wiklander        """
5722*c689edbbSJens Wiklander        fields = []
5723*c689edbbSJens Wiklander        add = fields.append
5724*c689edbbSJens Wiklander
5725*c689edbbSJens Wiklander        if self.item.__class__ is Symbol:
5726*c689edbbSJens Wiklander            add("menu node for symbol " + self.item.name)
5727*c689edbbSJens Wiklander
5728*c689edbbSJens Wiklander        elif self.item.__class__ is Choice:
5729*c689edbbSJens Wiklander            s = "menu node for choice"
5730*c689edbbSJens Wiklander            if self.item.name is not None:
5731*c689edbbSJens Wiklander                s += " " + self.item.name
5732*c689edbbSJens Wiklander            add(s)
5733*c689edbbSJens Wiklander
5734*c689edbbSJens Wiklander        elif self.item is MENU:
5735*c689edbbSJens Wiklander            add("menu node for menu")
5736*c689edbbSJens Wiklander
5737*c689edbbSJens Wiklander        else:  # self.item is COMMENT
5738*c689edbbSJens Wiklander            add("menu node for comment")
5739*c689edbbSJens Wiklander
5740*c689edbbSJens Wiklander        if self.prompt:
5741*c689edbbSJens Wiklander            add('prompt "{}" (visibility {})'.format(
5742*c689edbbSJens Wiklander                self.prompt[0], TRI_TO_STR[expr_value(self.prompt[1])]))
5743*c689edbbSJens Wiklander
5744*c689edbbSJens Wiklander        if self.item.__class__ is Symbol and self.is_menuconfig:
5745*c689edbbSJens Wiklander            add("is menuconfig")
5746*c689edbbSJens Wiklander
5747*c689edbbSJens Wiklander        add("deps " + TRI_TO_STR[expr_value(self.dep)])
5748*c689edbbSJens Wiklander
5749*c689edbbSJens Wiklander        if self.item is MENU:
5750*c689edbbSJens Wiklander            add("'visible if' deps " + TRI_TO_STR[expr_value(self.visibility)])
5751*c689edbbSJens Wiklander
5752*c689edbbSJens Wiklander        if self.item.__class__ in _SYMBOL_CHOICE and self.help is not None:
5753*c689edbbSJens Wiklander            add("has help")
5754*c689edbbSJens Wiklander
5755*c689edbbSJens Wiklander        if self.list:
5756*c689edbbSJens Wiklander            add("has child")
5757*c689edbbSJens Wiklander
5758*c689edbbSJens Wiklander        if self.next:
5759*c689edbbSJens Wiklander            add("has next")
5760*c689edbbSJens Wiklander
5761*c689edbbSJens Wiklander        add("{}:{}".format(self.filename, self.linenr))
5762*c689edbbSJens Wiklander
5763*c689edbbSJens Wiklander        return "<{}>".format(", ".join(fields))
5764*c689edbbSJens Wiklander
5765*c689edbbSJens Wiklander    def __str__(self):
5766*c689edbbSJens Wiklander        """
5767*c689edbbSJens Wiklander        Returns a string representation of the menu node. Matches the Kconfig
5768*c689edbbSJens Wiklander        format, with any parent dependencies propagated to the 'depends on'
5769*c689edbbSJens Wiklander        condition.
5770*c689edbbSJens Wiklander
5771*c689edbbSJens Wiklander        The output could (almost) be fed back into a Kconfig parser to redefine
5772*c689edbbSJens Wiklander        the object associated with the menu node. See the module documentation
5773*c689edbbSJens Wiklander        for a gotcha related to choice symbols.
5774*c689edbbSJens Wiklander
5775*c689edbbSJens Wiklander        For symbols and choices with multiple menu nodes (multiple definition
5776*c689edbbSJens Wiklander        locations), properties that aren't associated with a particular menu
5777*c689edbbSJens Wiklander        node are shown on all menu nodes ('option env=...', 'optional' for
5778*c689edbbSJens Wiklander        choices, etc.).
5779*c689edbbSJens Wiklander
5780*c689edbbSJens Wiklander        The returned string does not end in a newline.
5781*c689edbbSJens Wiklander        """
5782*c689edbbSJens Wiklander        return self.custom_str(standard_sc_expr_str)
5783*c689edbbSJens Wiklander
5784*c689edbbSJens Wiklander    def custom_str(self, sc_expr_str_fn):
5785*c689edbbSJens Wiklander        """
5786*c689edbbSJens Wiklander        Works like MenuNode.__str__(), but allows a custom format to be used
5787*c689edbbSJens Wiklander        for all symbol/choice references. See expr_str().
5788*c689edbbSJens Wiklander        """
5789*c689edbbSJens Wiklander        return self._menu_comment_node_str(sc_expr_str_fn) \
5790*c689edbbSJens Wiklander               if self.item in _MENU_COMMENT else \
5791*c689edbbSJens Wiklander               self._sym_choice_node_str(sc_expr_str_fn)
5792*c689edbbSJens Wiklander
5793*c689edbbSJens Wiklander    def _menu_comment_node_str(self, sc_expr_str_fn):
5794*c689edbbSJens Wiklander        s = '{} "{}"'.format("menu" if self.item is MENU else "comment",
5795*c689edbbSJens Wiklander                             self.prompt[0])
5796*c689edbbSJens Wiklander
5797*c689edbbSJens Wiklander        if self.dep is not self.kconfig.y:
5798*c689edbbSJens Wiklander            s += "\n\tdepends on {}".format(expr_str(self.dep, sc_expr_str_fn))
5799*c689edbbSJens Wiklander
5800*c689edbbSJens Wiklander        if self.item is MENU and self.visibility is not self.kconfig.y:
5801*c689edbbSJens Wiklander            s += "\n\tvisible if {}".format(expr_str(self.visibility,
5802*c689edbbSJens Wiklander                                                     sc_expr_str_fn))
5803*c689edbbSJens Wiklander
5804*c689edbbSJens Wiklander        return s
5805*c689edbbSJens Wiklander
5806*c689edbbSJens Wiklander    def _sym_choice_node_str(self, sc_expr_str_fn):
5807*c689edbbSJens Wiklander        def indent_add(s):
5808*c689edbbSJens Wiklander            lines.append("\t" + s)
5809*c689edbbSJens Wiklander
5810*c689edbbSJens Wiklander        def indent_add_cond(s, cond):
5811*c689edbbSJens Wiklander            if cond is not self.kconfig.y:
5812*c689edbbSJens Wiklander                s += " if " + expr_str(cond, sc_expr_str_fn)
5813*c689edbbSJens Wiklander            indent_add(s)
5814*c689edbbSJens Wiklander
5815*c689edbbSJens Wiklander        sc = self.item
5816*c689edbbSJens Wiklander
5817*c689edbbSJens Wiklander        if sc.__class__ is Symbol:
5818*c689edbbSJens Wiklander            lines = [("menuconfig " if self.is_menuconfig else "config ")
5819*c689edbbSJens Wiklander                     + sc.name]
5820*c689edbbSJens Wiklander        else:
5821*c689edbbSJens Wiklander            lines = ["choice " + sc.name if sc.name else "choice"]
5822*c689edbbSJens Wiklander
5823*c689edbbSJens Wiklander        if sc.orig_type and not self.prompt:  # sc.orig_type != UNKNOWN
5824*c689edbbSJens Wiklander            # If there's a prompt, we'll use the '<type> "prompt"' shorthand
5825*c689edbbSJens Wiklander            # instead
5826*c689edbbSJens Wiklander            indent_add(TYPE_TO_STR[sc.orig_type])
5827*c689edbbSJens Wiklander
5828*c689edbbSJens Wiklander        if self.prompt:
5829*c689edbbSJens Wiklander            if sc.orig_type:
5830*c689edbbSJens Wiklander                prefix = TYPE_TO_STR[sc.orig_type]
5831*c689edbbSJens Wiklander            else:
5832*c689edbbSJens Wiklander                # Symbol defined without a type (which generates a warning)
5833*c689edbbSJens Wiklander                prefix = "prompt"
5834*c689edbbSJens Wiklander
5835*c689edbbSJens Wiklander            indent_add_cond(prefix + ' "{}"'.format(escape(self.prompt[0])),
5836*c689edbbSJens Wiklander                            self.orig_prompt[1])
5837*c689edbbSJens Wiklander
5838*c689edbbSJens Wiklander        if sc.__class__ is Symbol:
5839*c689edbbSJens Wiklander            if sc.is_allnoconfig_y:
5840*c689edbbSJens Wiklander                indent_add("option allnoconfig_y")
5841*c689edbbSJens Wiklander
5842*c689edbbSJens Wiklander            if sc is sc.kconfig.defconfig_list:
5843*c689edbbSJens Wiklander                indent_add("option defconfig_list")
5844*c689edbbSJens Wiklander
5845*c689edbbSJens Wiklander            if sc.env_var is not None:
5846*c689edbbSJens Wiklander                indent_add('option env="{}"'.format(sc.env_var))
5847*c689edbbSJens Wiklander
5848*c689edbbSJens Wiklander            if sc is sc.kconfig.modules:
5849*c689edbbSJens Wiklander                indent_add("option modules")
5850*c689edbbSJens Wiklander
5851*c689edbbSJens Wiklander            for low, high, cond in self.orig_ranges:
5852*c689edbbSJens Wiklander                indent_add_cond(
5853*c689edbbSJens Wiklander                    "range {} {}".format(sc_expr_str_fn(low),
5854*c689edbbSJens Wiklander                                         sc_expr_str_fn(high)),
5855*c689edbbSJens Wiklander                    cond)
5856*c689edbbSJens Wiklander
5857*c689edbbSJens Wiklander        for default, cond in self.orig_defaults:
5858*c689edbbSJens Wiklander            indent_add_cond("default " + expr_str(default, sc_expr_str_fn),
5859*c689edbbSJens Wiklander                            cond)
5860*c689edbbSJens Wiklander
5861*c689edbbSJens Wiklander        if sc.__class__ is Choice and sc.is_optional:
5862*c689edbbSJens Wiklander            indent_add("optional")
5863*c689edbbSJens Wiklander
5864*c689edbbSJens Wiklander        if sc.__class__ is Symbol:
5865*c689edbbSJens Wiklander            for select, cond in self.orig_selects:
5866*c689edbbSJens Wiklander                indent_add_cond("select " + sc_expr_str_fn(select), cond)
5867*c689edbbSJens Wiklander
5868*c689edbbSJens Wiklander            for imply, cond in self.orig_implies:
5869*c689edbbSJens Wiklander                indent_add_cond("imply " + sc_expr_str_fn(imply), cond)
5870*c689edbbSJens Wiklander
5871*c689edbbSJens Wiklander        if self.dep is not sc.kconfig.y:
5872*c689edbbSJens Wiklander            indent_add("depends on " + expr_str(self.dep, sc_expr_str_fn))
5873*c689edbbSJens Wiklander
5874*c689edbbSJens Wiklander        if self.help is not None:
5875*c689edbbSJens Wiklander            indent_add("help")
5876*c689edbbSJens Wiklander            for line in self.help.splitlines():
5877*c689edbbSJens Wiklander                indent_add("  " + line)
5878*c689edbbSJens Wiklander
5879*c689edbbSJens Wiklander        return "\n".join(lines)
5880*c689edbbSJens Wiklander
5881*c689edbbSJens Wiklander    def _strip_dep(self, expr):
5882*c689edbbSJens Wiklander        # Helper function for removing MenuNode.dep from 'expr'. Uses two
5883*c689edbbSJens Wiklander        # pieces of internal knowledge: (1) Expressions are reused rather than
5884*c689edbbSJens Wiklander        # copied, and (2) the direct dependencies always appear at the end.
5885*c689edbbSJens Wiklander
5886*c689edbbSJens Wiklander        # ... if dep -> ... if y
5887*c689edbbSJens Wiklander        if self.dep is expr:
5888*c689edbbSJens Wiklander            return self.kconfig.y
5889*c689edbbSJens Wiklander
5890*c689edbbSJens Wiklander        # (AND, X, dep) -> X
5891*c689edbbSJens Wiklander        if expr.__class__ is tuple and expr[0] is AND and expr[2] is self.dep:
5892*c689edbbSJens Wiklander            return expr[1]
5893*c689edbbSJens Wiklander
5894*c689edbbSJens Wiklander        return expr
5895*c689edbbSJens Wiklander
5896*c689edbbSJens Wiklander
5897*c689edbbSJens Wiklanderclass Variable(object):
5898*c689edbbSJens Wiklander    """
5899*c689edbbSJens Wiklander    Represents a preprocessor variable/function.
5900*c689edbbSJens Wiklander
5901*c689edbbSJens Wiklander    The following attributes are available:
5902*c689edbbSJens Wiklander
5903*c689edbbSJens Wiklander    name:
5904*c689edbbSJens Wiklander      The name of the variable.
5905*c689edbbSJens Wiklander
5906*c689edbbSJens Wiklander    value:
5907*c689edbbSJens Wiklander      The unexpanded value of the variable.
5908*c689edbbSJens Wiklander
5909*c689edbbSJens Wiklander    expanded_value:
5910*c689edbbSJens Wiklander      The expanded value of the variable. For simple variables (those defined
5911*c689edbbSJens Wiklander      with :=), this will equal 'value'. Accessing this property will raise a
5912*c689edbbSJens Wiklander      KconfigError if the expansion seems to be stuck in a loop.
5913*c689edbbSJens Wiklander
5914*c689edbbSJens Wiklander      Accessing this field is the same as calling expanded_value_w_args() with
5915*c689edbbSJens Wiklander      no arguments. I hadn't considered function arguments when adding it. It
5916*c689edbbSJens Wiklander      is retained for backwards compatibility though.
5917*c689edbbSJens Wiklander
5918*c689edbbSJens Wiklander    is_recursive:
5919*c689edbbSJens Wiklander      True if the variable is recursive (defined with =).
5920*c689edbbSJens Wiklander    """
5921*c689edbbSJens Wiklander    __slots__ = (
5922*c689edbbSJens Wiklander        "_n_expansions",
5923*c689edbbSJens Wiklander        "is_recursive",
5924*c689edbbSJens Wiklander        "kconfig",
5925*c689edbbSJens Wiklander        "name",
5926*c689edbbSJens Wiklander        "value",
5927*c689edbbSJens Wiklander    )
5928*c689edbbSJens Wiklander
5929*c689edbbSJens Wiklander    @property
5930*c689edbbSJens Wiklander    def expanded_value(self):
5931*c689edbbSJens Wiklander        """
5932*c689edbbSJens Wiklander        See the class documentation.
5933*c689edbbSJens Wiklander        """
5934*c689edbbSJens Wiklander        return self.expanded_value_w_args()
5935*c689edbbSJens Wiklander
5936*c689edbbSJens Wiklander    def expanded_value_w_args(self, *args):
5937*c689edbbSJens Wiklander        """
5938*c689edbbSJens Wiklander        Returns the expanded value of the variable/function. Any arguments
5939*c689edbbSJens Wiklander        passed will be substituted for $(1), $(2), etc.
5940*c689edbbSJens Wiklander
5941*c689edbbSJens Wiklander        Raises a KconfigError if the expansion seems to be stuck in a loop.
5942*c689edbbSJens Wiklander        """
5943*c689edbbSJens Wiklander        return self.kconfig._fn_val((self.name,) + args)
5944*c689edbbSJens Wiklander
5945*c689edbbSJens Wiklander    def __repr__(self):
5946*c689edbbSJens Wiklander        return "<variable {}, {}, value '{}'>" \
5947*c689edbbSJens Wiklander               .format(self.name,
5948*c689edbbSJens Wiklander                       "recursive" if self.is_recursive else "immediate",
5949*c689edbbSJens Wiklander                       self.value)
5950*c689edbbSJens Wiklander
5951*c689edbbSJens Wiklander
5952*c689edbbSJens Wiklanderclass KconfigError(Exception):
5953*c689edbbSJens Wiklander    """
5954*c689edbbSJens Wiklander    Exception raised for Kconfig-related errors.
5955*c689edbbSJens Wiklander
5956*c689edbbSJens Wiklander    KconfigError and KconfigSyntaxError are the same class. The
5957*c689edbbSJens Wiklander    KconfigSyntaxError alias is only maintained for backwards compatibility.
5958*c689edbbSJens Wiklander    """
5959*c689edbbSJens Wiklander
5960*c689edbbSJens WiklanderKconfigSyntaxError = KconfigError  # Backwards compatibility
5961*c689edbbSJens Wiklander
5962*c689edbbSJens Wiklander
5963*c689edbbSJens Wiklanderclass InternalError(Exception):
5964*c689edbbSJens Wiklander    "Never raised. Kept around for backwards compatibility."
5965*c689edbbSJens Wiklander
5966*c689edbbSJens Wiklander
5967*c689edbbSJens Wiklander# Workaround:
5968*c689edbbSJens Wiklander#
5969*c689edbbSJens Wiklander# If 'errno' and 'strerror' are set on IOError, then __str__() always returns
5970*c689edbbSJens Wiklander# "[Errno <errno>] <strerror>", ignoring any custom message passed to the
5971*c689edbbSJens Wiklander# constructor. By defining our own subclass, we can use a custom message while
5972*c689edbbSJens Wiklander# also providing 'errno', 'strerror', and 'filename' to scripts.
5973*c689edbbSJens Wiklanderclass _KconfigIOError(IOError):
5974*c689edbbSJens Wiklander    def __init__(self, ioerror, msg):
5975*c689edbbSJens Wiklander        self.msg = msg
5976*c689edbbSJens Wiklander        super(_KconfigIOError, self).__init__(
5977*c689edbbSJens Wiklander            ioerror.errno, ioerror.strerror, ioerror.filename)
5978*c689edbbSJens Wiklander
5979*c689edbbSJens Wiklander    def __str__(self):
5980*c689edbbSJens Wiklander        return self.msg
5981*c689edbbSJens Wiklander
5982*c689edbbSJens Wiklander
5983*c689edbbSJens Wiklander#
5984*c689edbbSJens Wiklander# Public functions
5985*c689edbbSJens Wiklander#
5986*c689edbbSJens Wiklander
5987*c689edbbSJens Wiklander
5988*c689edbbSJens Wiklanderdef expr_value(expr):
5989*c689edbbSJens Wiklander    """
5990*c689edbbSJens Wiklander    Evaluates the expression 'expr' to a tristate value. Returns 0 (n), 1 (m),
5991*c689edbbSJens Wiklander    or 2 (y).
5992*c689edbbSJens Wiklander
5993*c689edbbSJens Wiklander    'expr' must be an already-parsed expression from a Symbol, Choice, or
5994*c689edbbSJens Wiklander    MenuNode property. To evaluate an expression represented as a string, use
5995*c689edbbSJens Wiklander    Kconfig.eval_string().
5996*c689edbbSJens Wiklander
5997*c689edbbSJens Wiklander    Passing subexpressions of expressions to this function works as expected.
5998*c689edbbSJens Wiklander    """
5999*c689edbbSJens Wiklander    if expr.__class__ is not tuple:
6000*c689edbbSJens Wiklander        return expr.tri_value
6001*c689edbbSJens Wiklander
6002*c689edbbSJens Wiklander    if expr[0] is AND:
6003*c689edbbSJens Wiklander        v1 = expr_value(expr[1])
6004*c689edbbSJens Wiklander        # Short-circuit the n case as an optimization (~5% faster
6005*c689edbbSJens Wiklander        # allnoconfig.py and allyesconfig.py, as of writing)
6006*c689edbbSJens Wiklander        return 0 if not v1 else min(v1, expr_value(expr[2]))
6007*c689edbbSJens Wiklander
6008*c689edbbSJens Wiklander    if expr[0] is OR:
6009*c689edbbSJens Wiklander        v1 = expr_value(expr[1])
6010*c689edbbSJens Wiklander        # Short-circuit the y case as an optimization
6011*c689edbbSJens Wiklander        return 2 if v1 == 2 else max(v1, expr_value(expr[2]))
6012*c689edbbSJens Wiklander
6013*c689edbbSJens Wiklander    if expr[0] is NOT:
6014*c689edbbSJens Wiklander        return 2 - expr_value(expr[1])
6015*c689edbbSJens Wiklander
6016*c689edbbSJens Wiklander    # Relation
6017*c689edbbSJens Wiklander    #
6018*c689edbbSJens Wiklander    # Implements <, <=, >, >= comparisons as well. These were added to
6019*c689edbbSJens Wiklander    # kconfig in 31847b67 (kconfig: allow use of relations other than
6020*c689edbbSJens Wiklander    # (in)equality).
6021*c689edbbSJens Wiklander
6022*c689edbbSJens Wiklander    rel, v1, v2 = expr
6023*c689edbbSJens Wiklander
6024*c689edbbSJens Wiklander    # If both operands are strings...
6025*c689edbbSJens Wiklander    if v1.orig_type is STRING and v2.orig_type is STRING:
6026*c689edbbSJens Wiklander        # ...then compare them lexicographically
6027*c689edbbSJens Wiklander        comp = _strcmp(v1.str_value, v2.str_value)
6028*c689edbbSJens Wiklander    else:
6029*c689edbbSJens Wiklander        # Otherwise, try to compare them as numbers
6030*c689edbbSJens Wiklander        try:
6031*c689edbbSJens Wiklander            comp = _sym_to_num(v1) - _sym_to_num(v2)
6032*c689edbbSJens Wiklander        except ValueError:
6033*c689edbbSJens Wiklander            # Fall back on a lexicographic comparison if the operands don't
6034*c689edbbSJens Wiklander            # parse as numbers
6035*c689edbbSJens Wiklander            comp = _strcmp(v1.str_value, v2.str_value)
6036*c689edbbSJens Wiklander
6037*c689edbbSJens Wiklander    return 2*(comp == 0 if rel is EQUAL else
6038*c689edbbSJens Wiklander              comp != 0 if rel is UNEQUAL else
6039*c689edbbSJens Wiklander              comp <  0 if rel is LESS else
6040*c689edbbSJens Wiklander              comp <= 0 if rel is LESS_EQUAL else
6041*c689edbbSJens Wiklander              comp >  0 if rel is GREATER else
6042*c689edbbSJens Wiklander              comp >= 0)
6043*c689edbbSJens Wiklander
6044*c689edbbSJens Wiklander
6045*c689edbbSJens Wiklanderdef standard_sc_expr_str(sc):
6046*c689edbbSJens Wiklander    """
6047*c689edbbSJens Wiklander    Standard symbol/choice printing function. Uses plain Kconfig syntax, and
6048*c689edbbSJens Wiklander    displays choices as <choice> (or <choice NAME>, for named choices).
6049*c689edbbSJens Wiklander
6050*c689edbbSJens Wiklander    See expr_str().
6051*c689edbbSJens Wiklander    """
6052*c689edbbSJens Wiklander    if sc.__class__ is Symbol:
6053*c689edbbSJens Wiklander        if sc.is_constant and sc.name not in STR_TO_TRI:
6054*c689edbbSJens Wiklander            return '"{}"'.format(escape(sc.name))
6055*c689edbbSJens Wiklander        return sc.name
6056*c689edbbSJens Wiklander
6057*c689edbbSJens Wiklander    return "<choice {}>".format(sc.name) if sc.name else "<choice>"
6058*c689edbbSJens Wiklander
6059*c689edbbSJens Wiklander
6060*c689edbbSJens Wiklanderdef expr_str(expr, sc_expr_str_fn=standard_sc_expr_str):
6061*c689edbbSJens Wiklander    """
6062*c689edbbSJens Wiklander    Returns the string representation of the expression 'expr', as in a Kconfig
6063*c689edbbSJens Wiklander    file.
6064*c689edbbSJens Wiklander
6065*c689edbbSJens Wiklander    Passing subexpressions of expressions to this function works as expected.
6066*c689edbbSJens Wiklander
6067*c689edbbSJens Wiklander    sc_expr_str_fn (default: standard_sc_expr_str):
6068*c689edbbSJens Wiklander      This function is called for every symbol/choice (hence "sc") appearing in
6069*c689edbbSJens Wiklander      the expression, with the symbol/choice as the argument. It is expected to
6070*c689edbbSJens Wiklander      return a string to be used for the symbol/choice.
6071*c689edbbSJens Wiklander
6072*c689edbbSJens Wiklander      This can be used e.g. to turn symbols/choices into links when generating
6073*c689edbbSJens Wiklander      documentation, or for printing the value of each symbol/choice after it.
6074*c689edbbSJens Wiklander
6075*c689edbbSJens Wiklander      Note that quoted values are represented as constants symbols
6076*c689edbbSJens Wiklander      (Symbol.is_constant == True).
6077*c689edbbSJens Wiklander    """
6078*c689edbbSJens Wiklander    if expr.__class__ is not tuple:
6079*c689edbbSJens Wiklander        return sc_expr_str_fn(expr)
6080*c689edbbSJens Wiklander
6081*c689edbbSJens Wiklander    if expr[0] is AND:
6082*c689edbbSJens Wiklander        return "{} && {}".format(_parenthesize(expr[1], OR, sc_expr_str_fn),
6083*c689edbbSJens Wiklander                                 _parenthesize(expr[2], OR, sc_expr_str_fn))
6084*c689edbbSJens Wiklander
6085*c689edbbSJens Wiklander    if expr[0] is OR:
6086*c689edbbSJens Wiklander        # This turns A && B || C && D into "(A && B) || (C && D)", which is
6087*c689edbbSJens Wiklander        # redundant, but more readable
6088*c689edbbSJens Wiklander        return "{} || {}".format(_parenthesize(expr[1], AND, sc_expr_str_fn),
6089*c689edbbSJens Wiklander                                 _parenthesize(expr[2], AND, sc_expr_str_fn))
6090*c689edbbSJens Wiklander
6091*c689edbbSJens Wiklander    if expr[0] is NOT:
6092*c689edbbSJens Wiklander        if expr[1].__class__ is tuple:
6093*c689edbbSJens Wiklander            return "!({})".format(expr_str(expr[1], sc_expr_str_fn))
6094*c689edbbSJens Wiklander        return "!" + sc_expr_str_fn(expr[1])  # Symbol
6095*c689edbbSJens Wiklander
6096*c689edbbSJens Wiklander    # Relation
6097*c689edbbSJens Wiklander    #
6098*c689edbbSJens Wiklander    # Relation operands are always symbols (quoted strings are constant
6099*c689edbbSJens Wiklander    # symbols)
6100*c689edbbSJens Wiklander    return "{} {} {}".format(sc_expr_str_fn(expr[1]), REL_TO_STR[expr[0]],
6101*c689edbbSJens Wiklander                             sc_expr_str_fn(expr[2]))
6102*c689edbbSJens Wiklander
6103*c689edbbSJens Wiklander
6104*c689edbbSJens Wiklanderdef expr_items(expr):
6105*c689edbbSJens Wiklander    """
6106*c689edbbSJens Wiklander    Returns a set() of all items (symbols and choices) that appear in the
6107*c689edbbSJens Wiklander    expression 'expr'.
6108*c689edbbSJens Wiklander
6109*c689edbbSJens Wiklander    Passing subexpressions of expressions to this function works as expected.
6110*c689edbbSJens Wiklander    """
6111*c689edbbSJens Wiklander    res = set()
6112*c689edbbSJens Wiklander
6113*c689edbbSJens Wiklander    def rec(subexpr):
6114*c689edbbSJens Wiklander        if subexpr.__class__ is tuple:
6115*c689edbbSJens Wiklander            # AND, OR, NOT, or relation
6116*c689edbbSJens Wiklander
6117*c689edbbSJens Wiklander            rec(subexpr[1])
6118*c689edbbSJens Wiklander
6119*c689edbbSJens Wiklander            # NOTs only have a single operand
6120*c689edbbSJens Wiklander            if subexpr[0] is not NOT:
6121*c689edbbSJens Wiklander                rec(subexpr[2])
6122*c689edbbSJens Wiklander
6123*c689edbbSJens Wiklander        else:
6124*c689edbbSJens Wiklander            # Symbol or choice
6125*c689edbbSJens Wiklander            res.add(subexpr)
6126*c689edbbSJens Wiklander
6127*c689edbbSJens Wiklander    rec(expr)
6128*c689edbbSJens Wiklander    return res
6129*c689edbbSJens Wiklander
6130*c689edbbSJens Wiklander
6131*c689edbbSJens Wiklanderdef split_expr(expr, op):
6132*c689edbbSJens Wiklander    """
6133*c689edbbSJens Wiklander    Returns a list containing the top-level AND or OR operands in the
6134*c689edbbSJens Wiklander    expression 'expr', in the same (left-to-right) order as they appear in
6135*c689edbbSJens Wiklander    the expression.
6136*c689edbbSJens Wiklander
6137*c689edbbSJens Wiklander    This can be handy e.g. for splitting (weak) reverse dependencies
6138*c689edbbSJens Wiklander    from 'select' and 'imply' into individual selects/implies.
6139*c689edbbSJens Wiklander
6140*c689edbbSJens Wiklander    op:
6141*c689edbbSJens Wiklander      Either AND to get AND operands, or OR to get OR operands.
6142*c689edbbSJens Wiklander
6143*c689edbbSJens Wiklander      (Having this as an operand might be more future-safe than having two
6144*c689edbbSJens Wiklander      hardcoded functions.)
6145*c689edbbSJens Wiklander
6146*c689edbbSJens Wiklander
6147*c689edbbSJens Wiklander    Pseudo-code examples:
6148*c689edbbSJens Wiklander
6149*c689edbbSJens Wiklander      split_expr( A                    , OR  )  ->  [A]
6150*c689edbbSJens Wiklander      split_expr( A && B               , OR  )  ->  [A && B]
6151*c689edbbSJens Wiklander      split_expr( A || B               , OR  )  ->  [A, B]
6152*c689edbbSJens Wiklander      split_expr( A || B               , AND )  ->  [A || B]
6153*c689edbbSJens Wiklander      split_expr( A || B || (C && D)   , OR  )  ->  [A, B, C && D]
6154*c689edbbSJens Wiklander
6155*c689edbbSJens Wiklander      # Second || is not at the top level
6156*c689edbbSJens Wiklander      split_expr( A || (B && (C || D)) , OR )  ->  [A, B && (C || D)]
6157*c689edbbSJens Wiklander
6158*c689edbbSJens Wiklander      # Parentheses don't matter as long as we stay at the top level (don't
6159*c689edbbSJens Wiklander      # encounter any non-'op' nodes)
6160*c689edbbSJens Wiklander      split_expr( (A || B) || C        , OR )  ->  [A, B, C]
6161*c689edbbSJens Wiklander      split_expr( A || (B || C)        , OR )  ->  [A, B, C]
6162*c689edbbSJens Wiklander    """
6163*c689edbbSJens Wiklander    res = []
6164*c689edbbSJens Wiklander
6165*c689edbbSJens Wiklander    def rec(subexpr):
6166*c689edbbSJens Wiklander        if subexpr.__class__ is tuple and subexpr[0] is op:
6167*c689edbbSJens Wiklander            rec(subexpr[1])
6168*c689edbbSJens Wiklander            rec(subexpr[2])
6169*c689edbbSJens Wiklander        else:
6170*c689edbbSJens Wiklander            res.append(subexpr)
6171*c689edbbSJens Wiklander
6172*c689edbbSJens Wiklander    rec(expr)
6173*c689edbbSJens Wiklander    return res
6174*c689edbbSJens Wiklander
6175*c689edbbSJens Wiklander
6176*c689edbbSJens Wiklanderdef escape(s):
6177*c689edbbSJens Wiklander    r"""
6178*c689edbbSJens Wiklander    Escapes the string 's' in the same fashion as is done for display in
6179*c689edbbSJens Wiklander    Kconfig format and when writing strings to a .config file. " and \ are
6180*c689edbbSJens Wiklander    replaced by \" and \\, respectively.
6181*c689edbbSJens Wiklander    """
6182*c689edbbSJens Wiklander    # \ must be escaped before " to avoid double escaping
6183*c689edbbSJens Wiklander    return s.replace("\\", r"\\").replace('"', r'\"')
6184*c689edbbSJens Wiklander
6185*c689edbbSJens Wiklander
6186*c689edbbSJens Wiklanderdef unescape(s):
6187*c689edbbSJens Wiklander    r"""
6188*c689edbbSJens Wiklander    Unescapes the string 's'. \ followed by any character is replaced with just
6189*c689edbbSJens Wiklander    that character. Used internally when reading .config files.
6190*c689edbbSJens Wiklander    """
6191*c689edbbSJens Wiklander    return _unescape_sub(r"\1", s)
6192*c689edbbSJens Wiklander
6193*c689edbbSJens Wiklander# unescape() helper
6194*c689edbbSJens Wiklander_unescape_sub = re.compile(r"\\(.)").sub
6195*c689edbbSJens Wiklander
6196*c689edbbSJens Wiklander
6197*c689edbbSJens Wiklanderdef standard_kconfig(description=None):
6198*c689edbbSJens Wiklander    """
6199*c689edbbSJens Wiklander    Argument parsing helper for tools that take a single optional Kconfig file
6200*c689edbbSJens Wiklander    argument (default: Kconfig). Returns the Kconfig instance for the parsed
6201*c689edbbSJens Wiklander    configuration. Uses argparse internally.
6202*c689edbbSJens Wiklander
6203*c689edbbSJens Wiklander    Exits with sys.exit() (which raises SystemExit) on errors.
6204*c689edbbSJens Wiklander
6205*c689edbbSJens Wiklander    description (default: None):
6206*c689edbbSJens Wiklander      The 'description' passed to argparse.ArgumentParser().
6207*c689edbbSJens Wiklander      argparse.RawDescriptionHelpFormatter is used, so formatting is preserved.
6208*c689edbbSJens Wiklander    """
6209*c689edbbSJens Wiklander    import argparse
6210*c689edbbSJens Wiklander
6211*c689edbbSJens Wiklander    parser = argparse.ArgumentParser(
6212*c689edbbSJens Wiklander        formatter_class=argparse.RawDescriptionHelpFormatter,
6213*c689edbbSJens Wiklander        description=description)
6214*c689edbbSJens Wiklander
6215*c689edbbSJens Wiklander    parser.add_argument(
6216*c689edbbSJens Wiklander        "kconfig",
6217*c689edbbSJens Wiklander        metavar="KCONFIG",
6218*c689edbbSJens Wiklander        default="Kconfig",
6219*c689edbbSJens Wiklander        nargs="?",
6220*c689edbbSJens Wiklander        help="Top-level Kconfig file (default: Kconfig)")
6221*c689edbbSJens Wiklander
6222*c689edbbSJens Wiklander    return Kconfig(parser.parse_args().kconfig, suppress_traceback=True)
6223*c689edbbSJens Wiklander
6224*c689edbbSJens Wiklander
6225*c689edbbSJens Wiklanderdef standard_config_filename():
6226*c689edbbSJens Wiklander    """
6227*c689edbbSJens Wiklander    Helper for tools. Returns the value of KCONFIG_CONFIG (which specifies the
6228*c689edbbSJens Wiklander    .config file to load/save) if it is set, and ".config" otherwise.
6229*c689edbbSJens Wiklander
6230*c689edbbSJens Wiklander    Calling load_config() with filename=None might give the behavior you want,
6231*c689edbbSJens Wiklander    without having to use this function.
6232*c689edbbSJens Wiklander    """
6233*c689edbbSJens Wiklander    return os.getenv("KCONFIG_CONFIG", ".config")
6234*c689edbbSJens Wiklander
6235*c689edbbSJens Wiklander
6236*c689edbbSJens Wiklanderdef load_allconfig(kconf, filename):
6237*c689edbbSJens Wiklander    """
6238*c689edbbSJens Wiklander    Use Kconfig.load_allconfig() instead, which was added in Kconfiglib 13.4.0.
6239*c689edbbSJens Wiklander    Supported for backwards compatibility. Might be removed at some point after
6240*c689edbbSJens Wiklander    a long period of deprecation warnings.
6241*c689edbbSJens Wiklander    """
6242*c689edbbSJens Wiklander    allconfig = os.getenv("KCONFIG_ALLCONFIG")
6243*c689edbbSJens Wiklander    if allconfig is None:
6244*c689edbbSJens Wiklander        return
6245*c689edbbSJens Wiklander
6246*c689edbbSJens Wiklander    def std_msg(e):
6247*c689edbbSJens Wiklander        # "Upcasts" a _KconfigIOError to an IOError, removing the custom
6248*c689edbbSJens Wiklander        # __str__() message. The standard message is better here.
6249*c689edbbSJens Wiklander        #
6250*c689edbbSJens Wiklander        # This might also convert an OSError to an IOError in obscure cases,
6251*c689edbbSJens Wiklander        # but it's probably not a big deal. The distinction is shaky (see
6252*c689edbbSJens Wiklander        # PEP-3151).
6253*c689edbbSJens Wiklander        return IOError(e.errno, e.strerror, e.filename)
6254*c689edbbSJens Wiklander
6255*c689edbbSJens Wiklander    old_warn_assign_override = kconf.warn_assign_override
6256*c689edbbSJens Wiklander    old_warn_assign_redun = kconf.warn_assign_redun
6257*c689edbbSJens Wiklander    kconf.warn_assign_override = kconf.warn_assign_redun = False
6258*c689edbbSJens Wiklander
6259*c689edbbSJens Wiklander    if allconfig in ("", "1"):
6260*c689edbbSJens Wiklander        try:
6261*c689edbbSJens Wiklander            print(kconf.load_config(filename, False))
6262*c689edbbSJens Wiklander        except EnvironmentError as e1:
6263*c689edbbSJens Wiklander            try:
6264*c689edbbSJens Wiklander                print(kconf.load_config("all.config", False))
6265*c689edbbSJens Wiklander            except EnvironmentError as e2:
6266*c689edbbSJens Wiklander                sys.exit("error: KCONFIG_ALLCONFIG is set, but neither {} "
6267*c689edbbSJens Wiklander                         "nor all.config could be opened: {}, {}"
6268*c689edbbSJens Wiklander                         .format(filename, std_msg(e1), std_msg(e2)))
6269*c689edbbSJens Wiklander    else:
6270*c689edbbSJens Wiklander        try:
6271*c689edbbSJens Wiklander            print(kconf.load_config(allconfig, False))
6272*c689edbbSJens Wiklander        except EnvironmentError as e:
6273*c689edbbSJens Wiklander            sys.exit("error: KCONFIG_ALLCONFIG is set to '{}', which "
6274*c689edbbSJens Wiklander                     "could not be opened: {}"
6275*c689edbbSJens Wiklander                     .format(allconfig, std_msg(e)))
6276*c689edbbSJens Wiklander
6277*c689edbbSJens Wiklander    kconf.warn_assign_override = old_warn_assign_override
6278*c689edbbSJens Wiklander    kconf.warn_assign_redun = old_warn_assign_redun
6279*c689edbbSJens Wiklander
6280*c689edbbSJens Wiklander
6281*c689edbbSJens Wiklander#
6282*c689edbbSJens Wiklander# Internal functions
6283*c689edbbSJens Wiklander#
6284*c689edbbSJens Wiklander
6285*c689edbbSJens Wiklander
6286*c689edbbSJens Wiklanderdef _visibility(sc):
6287*c689edbbSJens Wiklander    # Symbols and Choices have a "visibility" that acts as an upper bound on
6288*c689edbbSJens Wiklander    # the values a user can set for them, corresponding to the visibility in
6289*c689edbbSJens Wiklander    # e.g. 'make menuconfig'. This function calculates the visibility for the
6290*c689edbbSJens Wiklander    # Symbol or Choice 'sc' -- the logic is nearly identical.
6291*c689edbbSJens Wiklander
6292*c689edbbSJens Wiklander    vis = 0
6293*c689edbbSJens Wiklander
6294*c689edbbSJens Wiklander    for node in sc.nodes:
6295*c689edbbSJens Wiklander        if node.prompt:
6296*c689edbbSJens Wiklander            vis = max(vis, expr_value(node.prompt[1]))
6297*c689edbbSJens Wiklander
6298*c689edbbSJens Wiklander    if sc.__class__ is Symbol and sc.choice:
6299*c689edbbSJens Wiklander        if sc.choice.orig_type is TRISTATE and \
6300*c689edbbSJens Wiklander           sc.orig_type is not TRISTATE and sc.choice.tri_value != 2:
6301*c689edbbSJens Wiklander            # Non-tristate choice symbols are only visible in y mode
6302*c689edbbSJens Wiklander            return 0
6303*c689edbbSJens Wiklander
6304*c689edbbSJens Wiklander        if sc.orig_type is TRISTATE and vis == 1 and sc.choice.tri_value == 2:
6305*c689edbbSJens Wiklander            # Choice symbols with m visibility are not visible in y mode
6306*c689edbbSJens Wiklander            return 0
6307*c689edbbSJens Wiklander
6308*c689edbbSJens Wiklander    # Promote m to y if we're dealing with a non-tristate (possibly due to
6309*c689edbbSJens Wiklander    # modules being disabled)
6310*c689edbbSJens Wiklander    if vis == 1 and sc.type is not TRISTATE:
6311*c689edbbSJens Wiklander        return 2
6312*c689edbbSJens Wiklander
6313*c689edbbSJens Wiklander    return vis
6314*c689edbbSJens Wiklander
6315*c689edbbSJens Wiklander
6316*c689edbbSJens Wiklanderdef _depend_on(sc, expr):
6317*c689edbbSJens Wiklander    # Adds 'sc' (symbol or choice) as a "dependee" to all symbols in 'expr'.
6318*c689edbbSJens Wiklander    # Constant symbols in 'expr' are skipped as they can never change value
6319*c689edbbSJens Wiklander    # anyway.
6320*c689edbbSJens Wiklander
6321*c689edbbSJens Wiklander    if expr.__class__ is tuple:
6322*c689edbbSJens Wiklander        # AND, OR, NOT, or relation
6323*c689edbbSJens Wiklander
6324*c689edbbSJens Wiklander        _depend_on(sc, expr[1])
6325*c689edbbSJens Wiklander
6326*c689edbbSJens Wiklander        # NOTs only have a single operand
6327*c689edbbSJens Wiklander        if expr[0] is not NOT:
6328*c689edbbSJens Wiklander            _depend_on(sc, expr[2])
6329*c689edbbSJens Wiklander
6330*c689edbbSJens Wiklander    elif not expr.is_constant:
6331*c689edbbSJens Wiklander        # Non-constant symbol, or choice
6332*c689edbbSJens Wiklander        expr._dependents.add(sc)
6333*c689edbbSJens Wiklander
6334*c689edbbSJens Wiklander
6335*c689edbbSJens Wiklanderdef _parenthesize(expr, type_, sc_expr_str_fn):
6336*c689edbbSJens Wiklander    # expr_str() helper. Adds parentheses around expressions of type 'type_'.
6337*c689edbbSJens Wiklander
6338*c689edbbSJens Wiklander    if expr.__class__ is tuple and expr[0] is type_:
6339*c689edbbSJens Wiklander        return "({})".format(expr_str(expr, sc_expr_str_fn))
6340*c689edbbSJens Wiklander    return expr_str(expr, sc_expr_str_fn)
6341*c689edbbSJens Wiklander
6342*c689edbbSJens Wiklander
6343*c689edbbSJens Wiklanderdef _ordered_unique(lst):
6344*c689edbbSJens Wiklander    # Returns 'lst' with any duplicates removed, preserving order. This hacky
6345*c689edbbSJens Wiklander    # version seems to be a common idiom. It relies on short-circuit evaluation
6346*c689edbbSJens Wiklander    # and set.add() returning None, which is falsy.
6347*c689edbbSJens Wiklander
6348*c689edbbSJens Wiklander    seen = set()
6349*c689edbbSJens Wiklander    seen_add = seen.add
6350*c689edbbSJens Wiklander    return [x for x in lst if x not in seen and not seen_add(x)]
6351*c689edbbSJens Wiklander
6352*c689edbbSJens Wiklander
6353*c689edbbSJens Wiklanderdef _is_base_n(s, n):
6354*c689edbbSJens Wiklander    try:
6355*c689edbbSJens Wiklander        int(s, n)
6356*c689edbbSJens Wiklander        return True
6357*c689edbbSJens Wiklander    except ValueError:
6358*c689edbbSJens Wiklander        return False
6359*c689edbbSJens Wiklander
6360*c689edbbSJens Wiklander
6361*c689edbbSJens Wiklanderdef _strcmp(s1, s2):
6362*c689edbbSJens Wiklander    # strcmp()-alike that returns -1, 0, or 1
6363*c689edbbSJens Wiklander
6364*c689edbbSJens Wiklander    return (s1 > s2) - (s1 < s2)
6365*c689edbbSJens Wiklander
6366*c689edbbSJens Wiklander
6367*c689edbbSJens Wiklanderdef _sym_to_num(sym):
6368*c689edbbSJens Wiklander    # expr_value() helper for converting a symbol to a number. Raises
6369*c689edbbSJens Wiklander    # ValueError for symbols that can't be converted.
6370*c689edbbSJens Wiklander
6371*c689edbbSJens Wiklander    # For BOOL and TRISTATE, n/m/y count as 0/1/2. This mirrors 9059a3493ef
6372*c689edbbSJens Wiklander    # ("kconfig: fix relational operators for bool and tristate symbols") in
6373*c689edbbSJens Wiklander    # the C implementation.
6374*c689edbbSJens Wiklander    return sym.tri_value if sym.orig_type in _BOOL_TRISTATE else \
6375*c689edbbSJens Wiklander           int(sym.str_value, _TYPE_TO_BASE[sym.orig_type])
6376*c689edbbSJens Wiklander
6377*c689edbbSJens Wiklander
6378*c689edbbSJens Wiklanderdef _touch_dep_file(path, sym_name):
6379*c689edbbSJens Wiklander    # If sym_name is MY_SYM_NAME, touches my/sym/name.h. See the sync_deps()
6380*c689edbbSJens Wiklander    # docstring.
6381*c689edbbSJens Wiklander
6382*c689edbbSJens Wiklander    sym_path = path + os.sep + sym_name.lower().replace("_", os.sep) + ".h"
6383*c689edbbSJens Wiklander    sym_path_dir = dirname(sym_path)
6384*c689edbbSJens Wiklander    if not exists(sym_path_dir):
6385*c689edbbSJens Wiklander        os.makedirs(sym_path_dir, 0o755)
6386*c689edbbSJens Wiklander
6387*c689edbbSJens Wiklander    # A kind of truncating touch, mirroring the C tools
6388*c689edbbSJens Wiklander    os.close(os.open(
6389*c689edbbSJens Wiklander        sym_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o644))
6390*c689edbbSJens Wiklander
6391*c689edbbSJens Wiklander
6392*c689edbbSJens Wiklanderdef _save_old(path):
6393*c689edbbSJens Wiklander    # See write_config()
6394*c689edbbSJens Wiklander
6395*c689edbbSJens Wiklander    def copy(src, dst):
6396*c689edbbSJens Wiklander        # Import as needed, to save some startup time
6397*c689edbbSJens Wiklander        import shutil
6398*c689edbbSJens Wiklander        shutil.copyfile(src, dst)
6399*c689edbbSJens Wiklander
6400*c689edbbSJens Wiklander    if islink(path):
6401*c689edbbSJens Wiklander        # Preserve symlinks
6402*c689edbbSJens Wiklander        copy_fn = copy
6403*c689edbbSJens Wiklander    elif hasattr(os, "replace"):
6404*c689edbbSJens Wiklander        # Python 3 (3.3+) only. Best choice when available, because it
6405*c689edbbSJens Wiklander        # removes <filename>.old on both *nix and Windows.
6406*c689edbbSJens Wiklander        copy_fn = os.replace
6407*c689edbbSJens Wiklander    elif os.name == "posix":
6408*c689edbbSJens Wiklander        # Removes <filename>.old on POSIX systems
6409*c689edbbSJens Wiklander        copy_fn = os.rename
6410*c689edbbSJens Wiklander    else:
6411*c689edbbSJens Wiklander        # Fall back on copying
6412*c689edbbSJens Wiklander        copy_fn = copy
6413*c689edbbSJens Wiklander
6414*c689edbbSJens Wiklander    try:
6415*c689edbbSJens Wiklander        copy_fn(path, path + ".old")
6416*c689edbbSJens Wiklander    except Exception:
6417*c689edbbSJens Wiklander        # Ignore errors from 'path' missing as well as other errors.
6418*c689edbbSJens Wiklander        # <filename>.old file is usually more of a nice-to-have, and not worth
6419*c689edbbSJens Wiklander        # erroring out over e.g. if <filename>.old happens to be a directory or
6420*c689edbbSJens Wiklander        # <filename> is something like /dev/null.
6421*c689edbbSJens Wiklander        pass
6422*c689edbbSJens Wiklander
6423*c689edbbSJens Wiklander
6424*c689edbbSJens Wiklanderdef _locs(sc):
6425*c689edbbSJens Wiklander    # Symbol/Choice.name_and_loc helper. Returns the "(defined at ...)" part of
6426*c689edbbSJens Wiklander    # the string. 'sc' is a Symbol or Choice.
6427*c689edbbSJens Wiklander
6428*c689edbbSJens Wiklander    if sc.nodes:
6429*c689edbbSJens Wiklander        return "(defined at {})".format(
6430*c689edbbSJens Wiklander            ", ".join("{0.filename}:{0.linenr}".format(node)
6431*c689edbbSJens Wiklander                      for node in sc.nodes))
6432*c689edbbSJens Wiklander
6433*c689edbbSJens Wiklander    return "(undefined)"
6434*c689edbbSJens Wiklander
6435*c689edbbSJens Wiklander
6436*c689edbbSJens Wiklander# Menu manipulation
6437*c689edbbSJens Wiklander
6438*c689edbbSJens Wiklander
6439*c689edbbSJens Wiklanderdef _expr_depends_on(expr, sym):
6440*c689edbbSJens Wiklander    # Reimplementation of expr_depends_symbol() from mconf.c. Used to determine
6441*c689edbbSJens Wiklander    # if a submenu should be implicitly created. This also influences which
6442*c689edbbSJens Wiklander    # items inside choice statements are considered choice items.
6443*c689edbbSJens Wiklander
6444*c689edbbSJens Wiklander    if expr.__class__ is not tuple:
6445*c689edbbSJens Wiklander        return expr is sym
6446*c689edbbSJens Wiklander
6447*c689edbbSJens Wiklander    if expr[0] in _EQUAL_UNEQUAL:
6448*c689edbbSJens Wiklander        # Check for one of the following:
6449*c689edbbSJens Wiklander        # sym = m/y, m/y = sym, sym != n, n != sym
6450*c689edbbSJens Wiklander
6451*c689edbbSJens Wiklander        left, right = expr[1:]
6452*c689edbbSJens Wiklander
6453*c689edbbSJens Wiklander        if right is sym:
6454*c689edbbSJens Wiklander            left, right = right, left
6455*c689edbbSJens Wiklander        elif left is not sym:
6456*c689edbbSJens Wiklander            return False
6457*c689edbbSJens Wiklander
6458*c689edbbSJens Wiklander        return (expr[0] is EQUAL and right is sym.kconfig.m or
6459*c689edbbSJens Wiklander                                     right is sym.kconfig.y) or \
6460*c689edbbSJens Wiklander               (expr[0] is UNEQUAL and right is sym.kconfig.n)
6461*c689edbbSJens Wiklander
6462*c689edbbSJens Wiklander    return expr[0] is AND and \
6463*c689edbbSJens Wiklander           (_expr_depends_on(expr[1], sym) or
6464*c689edbbSJens Wiklander            _expr_depends_on(expr[2], sym))
6465*c689edbbSJens Wiklander
6466*c689edbbSJens Wiklander
6467*c689edbbSJens Wiklanderdef _auto_menu_dep(node1, node2):
6468*c689edbbSJens Wiklander    # Returns True if node2 has an "automatic menu dependency" on node1. If
6469*c689edbbSJens Wiklander    # node2 has a prompt, we check its condition. Otherwise, we look directly
6470*c689edbbSJens Wiklander    # at node2.dep.
6471*c689edbbSJens Wiklander
6472*c689edbbSJens Wiklander    return _expr_depends_on(node2.prompt[1] if node2.prompt else node2.dep,
6473*c689edbbSJens Wiklander                            node1.item)
6474*c689edbbSJens Wiklander
6475*c689edbbSJens Wiklander
6476*c689edbbSJens Wiklanderdef _flatten(node):
6477*c689edbbSJens Wiklander    # "Flattens" menu nodes without prompts (e.g. 'if' nodes and non-visible
6478*c689edbbSJens Wiklander    # symbols with children from automatic menu creation) so that their
6479*c689edbbSJens Wiklander    # children appear after them instead. This gives a clean menu structure
6480*c689edbbSJens Wiklander    # with no unexpected "jumps" in the indentation.
6481*c689edbbSJens Wiklander    #
6482*c689edbbSJens Wiklander    # Do not flatten promptless choices (which can appear "legitimately" if a
6483*c689edbbSJens Wiklander    # named choice is defined in multiple locations to add on symbols). It
6484*c689edbbSJens Wiklander    # looks confusing, and the menuconfig already shows all choice symbols if
6485*c689edbbSJens Wiklander    # you enter the choice at some location with a prompt.
6486*c689edbbSJens Wiklander
6487*c689edbbSJens Wiklander    while node:
6488*c689edbbSJens Wiklander        if node.list and not node.prompt and \
6489*c689edbbSJens Wiklander           node.item.__class__ is not Choice:
6490*c689edbbSJens Wiklander
6491*c689edbbSJens Wiklander            last_node = node.list
6492*c689edbbSJens Wiklander            while 1:
6493*c689edbbSJens Wiklander                last_node.parent = node.parent
6494*c689edbbSJens Wiklander                if not last_node.next:
6495*c689edbbSJens Wiklander                    break
6496*c689edbbSJens Wiklander                last_node = last_node.next
6497*c689edbbSJens Wiklander
6498*c689edbbSJens Wiklander            last_node.next = node.next
6499*c689edbbSJens Wiklander            node.next = node.list
6500*c689edbbSJens Wiklander            node.list = None
6501*c689edbbSJens Wiklander
6502*c689edbbSJens Wiklander        node = node.next
6503*c689edbbSJens Wiklander
6504*c689edbbSJens Wiklander
6505*c689edbbSJens Wiklanderdef _remove_ifs(node):
6506*c689edbbSJens Wiklander    # Removes 'if' nodes (which can be recognized by MenuNode.item being None),
6507*c689edbbSJens Wiklander    # which are assumed to already have been flattened. The C implementation
6508*c689edbbSJens Wiklander    # doesn't bother to do this, but we expose the menu tree directly, and it
6509*c689edbbSJens Wiklander    # makes it nicer to work with.
6510*c689edbbSJens Wiklander
6511*c689edbbSJens Wiklander    cur = node.list
6512*c689edbbSJens Wiklander    while cur and not cur.item:
6513*c689edbbSJens Wiklander        cur = cur.next
6514*c689edbbSJens Wiklander
6515*c689edbbSJens Wiklander    node.list = cur
6516*c689edbbSJens Wiklander
6517*c689edbbSJens Wiklander    while cur:
6518*c689edbbSJens Wiklander        next = cur.next
6519*c689edbbSJens Wiklander        while next and not next.item:
6520*c689edbbSJens Wiklander            next = next.next
6521*c689edbbSJens Wiklander
6522*c689edbbSJens Wiklander        # Equivalent to
6523*c689edbbSJens Wiklander        #
6524*c689edbbSJens Wiklander        #   cur.next = next
6525*c689edbbSJens Wiklander        #   cur = next
6526*c689edbbSJens Wiklander        #
6527*c689edbbSJens Wiklander        # due to tricky Python semantics. The order matters.
6528*c689edbbSJens Wiklander        cur.next = cur = next
6529*c689edbbSJens Wiklander
6530*c689edbbSJens Wiklander
6531*c689edbbSJens Wiklanderdef _finalize_choice(node):
6532*c689edbbSJens Wiklander    # Finalizes a choice, marking each symbol whose menu node has the choice as
6533*c689edbbSJens Wiklander    # the parent as a choice symbol, and automatically determining types if not
6534*c689edbbSJens Wiklander    # specified.
6535*c689edbbSJens Wiklander
6536*c689edbbSJens Wiklander    choice = node.item
6537*c689edbbSJens Wiklander
6538*c689edbbSJens Wiklander    cur = node.list
6539*c689edbbSJens Wiklander    while cur:
6540*c689edbbSJens Wiklander        if cur.item.__class__ is Symbol:
6541*c689edbbSJens Wiklander            cur.item.choice = choice
6542*c689edbbSJens Wiklander            choice.syms.append(cur.item)
6543*c689edbbSJens Wiklander        cur = cur.next
6544*c689edbbSJens Wiklander
6545*c689edbbSJens Wiklander    # If no type is specified for the choice, its type is that of
6546*c689edbbSJens Wiklander    # the first choice item with a specified type
6547*c689edbbSJens Wiklander    if not choice.orig_type:
6548*c689edbbSJens Wiklander        for item in choice.syms:
6549*c689edbbSJens Wiklander            if item.orig_type:
6550*c689edbbSJens Wiklander                choice.orig_type = item.orig_type
6551*c689edbbSJens Wiklander                break
6552*c689edbbSJens Wiklander
6553*c689edbbSJens Wiklander    # Each choice item of UNKNOWN type gets the type of the choice
6554*c689edbbSJens Wiklander    for sym in choice.syms:
6555*c689edbbSJens Wiklander        if not sym.orig_type:
6556*c689edbbSJens Wiklander            sym.orig_type = choice.orig_type
6557*c689edbbSJens Wiklander
6558*c689edbbSJens Wiklander
6559*c689edbbSJens Wiklanderdef _check_dep_loop_sym(sym, ignore_choice):
6560*c689edbbSJens Wiklander    # Detects dependency loops using depth-first search on the dependency graph
6561*c689edbbSJens Wiklander    # (which is calculated earlier in Kconfig._build_dep()).
6562*c689edbbSJens Wiklander    #
6563*c689edbbSJens Wiklander    # Algorithm:
6564*c689edbbSJens Wiklander    #
6565*c689edbbSJens Wiklander    #  1. Symbols/choices start out with _visited = 0, meaning unvisited.
6566*c689edbbSJens Wiklander    #
6567*c689edbbSJens Wiklander    #  2. When a symbol/choice is first visited, _visited is set to 1, meaning
6568*c689edbbSJens Wiklander    #     "visited, potentially part of a dependency loop". The recursive
6569*c689edbbSJens Wiklander    #     search then continues from the symbol/choice.
6570*c689edbbSJens Wiklander    #
6571*c689edbbSJens Wiklander    #  3. If we run into a symbol/choice X with _visited already set to 1,
6572*c689edbbSJens Wiklander    #     there's a dependency loop. The loop is found on the call stack by
6573*c689edbbSJens Wiklander    #     recording symbols while returning ("on the way back") until X is seen
6574*c689edbbSJens Wiklander    #     again.
6575*c689edbbSJens Wiklander    #
6576*c689edbbSJens Wiklander    #  4. Once a symbol/choice and all its dependencies (or dependents in this
6577*c689edbbSJens Wiklander    #     case) have been checked recursively without detecting any loops, its
6578*c689edbbSJens Wiklander    #     _visited is set to 2, meaning "visited, not part of a dependency
6579*c689edbbSJens Wiklander    #     loop".
6580*c689edbbSJens Wiklander    #
6581*c689edbbSJens Wiklander    #     This saves work if we run into the symbol/choice again in later calls
6582*c689edbbSJens Wiklander    #     to _check_dep_loop_sym(). We just return immediately.
6583*c689edbbSJens Wiklander    #
6584*c689edbbSJens Wiklander    # Choices complicate things, as every choice symbol depends on every other
6585*c689edbbSJens Wiklander    # choice symbol in a sense. When a choice is "entered" via a choice symbol
6586*c689edbbSJens Wiklander    # X, we visit all choice symbols from the choice except X, and prevent
6587*c689edbbSJens Wiklander    # immediately revisiting the choice with a flag (ignore_choice).
6588*c689edbbSJens Wiklander    #
6589*c689edbbSJens Wiklander    # Maybe there's a better way to handle this (different flags or the
6590*c689edbbSJens Wiklander    # like...)
6591*c689edbbSJens Wiklander
6592*c689edbbSJens Wiklander    if not sym._visited:
6593*c689edbbSJens Wiklander        # sym._visited == 0, unvisited
6594*c689edbbSJens Wiklander
6595*c689edbbSJens Wiklander        sym._visited = 1
6596*c689edbbSJens Wiklander
6597*c689edbbSJens Wiklander        for dep in sym._dependents:
6598*c689edbbSJens Wiklander            # Choices show up in Symbol._dependents when the choice has the
6599*c689edbbSJens Wiklander            # symbol in a 'prompt' or 'default' condition (e.g.
6600*c689edbbSJens Wiklander            # 'default ... if SYM').
6601*c689edbbSJens Wiklander            #
6602*c689edbbSJens Wiklander            # Since we aren't entering the choice via a choice symbol, all
6603*c689edbbSJens Wiklander            # choice symbols need to be checked, hence the None.
6604*c689edbbSJens Wiklander            loop = _check_dep_loop_choice(dep, None) \
6605*c689edbbSJens Wiklander                   if dep.__class__ is Choice \
6606*c689edbbSJens Wiklander                   else _check_dep_loop_sym(dep, False)
6607*c689edbbSJens Wiklander
6608*c689edbbSJens Wiklander            if loop:
6609*c689edbbSJens Wiklander                # Dependency loop found
6610*c689edbbSJens Wiklander                return _found_dep_loop(loop, sym)
6611*c689edbbSJens Wiklander
6612*c689edbbSJens Wiklander        if sym.choice and not ignore_choice:
6613*c689edbbSJens Wiklander            loop = _check_dep_loop_choice(sym.choice, sym)
6614*c689edbbSJens Wiklander            if loop:
6615*c689edbbSJens Wiklander                # Dependency loop found
6616*c689edbbSJens Wiklander                return _found_dep_loop(loop, sym)
6617*c689edbbSJens Wiklander
6618*c689edbbSJens Wiklander        # The symbol is not part of a dependency loop
6619*c689edbbSJens Wiklander        sym._visited = 2
6620*c689edbbSJens Wiklander
6621*c689edbbSJens Wiklander        # No dependency loop found
6622*c689edbbSJens Wiklander        return None
6623*c689edbbSJens Wiklander
6624*c689edbbSJens Wiklander    if sym._visited == 2:
6625*c689edbbSJens Wiklander        # The symbol was checked earlier and is already known to not be part of
6626*c689edbbSJens Wiklander        # a dependency loop
6627*c689edbbSJens Wiklander        return None
6628*c689edbbSJens Wiklander
6629*c689edbbSJens Wiklander    # sym._visited == 1, found a dependency loop. Return the symbol as the
6630*c689edbbSJens Wiklander    # first element in it.
6631*c689edbbSJens Wiklander    return (sym,)
6632*c689edbbSJens Wiklander
6633*c689edbbSJens Wiklander
6634*c689edbbSJens Wiklanderdef _check_dep_loop_choice(choice, skip):
6635*c689edbbSJens Wiklander    if not choice._visited:
6636*c689edbbSJens Wiklander        # choice._visited == 0, unvisited
6637*c689edbbSJens Wiklander
6638*c689edbbSJens Wiklander        choice._visited = 1
6639*c689edbbSJens Wiklander
6640*c689edbbSJens Wiklander        # Check for loops involving choice symbols. If we came here via a
6641*c689edbbSJens Wiklander        # choice symbol, skip that one, as we'd get a false positive
6642*c689edbbSJens Wiklander        # '<sym FOO> -> <choice> -> <sym FOO>' loop otherwise.
6643*c689edbbSJens Wiklander        for sym in choice.syms:
6644*c689edbbSJens Wiklander            if sym is not skip:
6645*c689edbbSJens Wiklander                # Prevent the choice from being immediately re-entered via the
6646*c689edbbSJens Wiklander                # "is a choice symbol" path by passing True
6647*c689edbbSJens Wiklander                loop = _check_dep_loop_sym(sym, True)
6648*c689edbbSJens Wiklander                if loop:
6649*c689edbbSJens Wiklander                    # Dependency loop found
6650*c689edbbSJens Wiklander                    return _found_dep_loop(loop, choice)
6651*c689edbbSJens Wiklander
6652*c689edbbSJens Wiklander        # The choice is not part of a dependency loop
6653*c689edbbSJens Wiklander        choice._visited = 2
6654*c689edbbSJens Wiklander
6655*c689edbbSJens Wiklander        # No dependency loop found
6656*c689edbbSJens Wiklander        return None
6657*c689edbbSJens Wiklander
6658*c689edbbSJens Wiklander    if choice._visited == 2:
6659*c689edbbSJens Wiklander        # The choice was checked earlier and is already known to not be part of
6660*c689edbbSJens Wiklander        # a dependency loop
6661*c689edbbSJens Wiklander        return None
6662*c689edbbSJens Wiklander
6663*c689edbbSJens Wiklander    # choice._visited == 1, found a dependency loop. Return the choice as the
6664*c689edbbSJens Wiklander    # first element in it.
6665*c689edbbSJens Wiklander    return (choice,)
6666*c689edbbSJens Wiklander
6667*c689edbbSJens Wiklander
6668*c689edbbSJens Wiklanderdef _found_dep_loop(loop, cur):
6669*c689edbbSJens Wiklander    # Called "on the way back" when we know we have a loop
6670*c689edbbSJens Wiklander
6671*c689edbbSJens Wiklander    # Is the symbol/choice 'cur' where the loop started?
6672*c689edbbSJens Wiklander    if cur is not loop[0]:
6673*c689edbbSJens Wiklander        # Nope, it's just a part of the loop
6674*c689edbbSJens Wiklander        return loop + (cur,)
6675*c689edbbSJens Wiklander
6676*c689edbbSJens Wiklander    # Yep, we have the entire loop. Throw an exception that shows it.
6677*c689edbbSJens Wiklander
6678*c689edbbSJens Wiklander    msg = "\nDependency loop\n" \
6679*c689edbbSJens Wiklander            "===============\n\n"
6680*c689edbbSJens Wiklander
6681*c689edbbSJens Wiklander    for item in loop:
6682*c689edbbSJens Wiklander        if item is not loop[0]:
6683*c689edbbSJens Wiklander            msg += "...depends on "
6684*c689edbbSJens Wiklander            if item.__class__ is Symbol and item.choice:
6685*c689edbbSJens Wiklander                msg += "the choice symbol "
6686*c689edbbSJens Wiklander
6687*c689edbbSJens Wiklander        msg += "{}, with definition...\n\n{}\n\n" \
6688*c689edbbSJens Wiklander               .format(item.name_and_loc, item)
6689*c689edbbSJens Wiklander
6690*c689edbbSJens Wiklander        # Small wart: Since we reuse the already calculated
6691*c689edbbSJens Wiklander        # Symbol/Choice._dependents sets for recursive dependency detection, we
6692*c689edbbSJens Wiklander        # lose information on whether a dependency came from a 'select'/'imply'
6693*c689edbbSJens Wiklander        # condition or e.g. a 'depends on'.
6694*c689edbbSJens Wiklander        #
6695*c689edbbSJens Wiklander        # This might cause selecting symbols to "disappear". For example,
6696*c689edbbSJens Wiklander        # a symbol B having 'select A if C' gives a direct dependency from A to
6697*c689edbbSJens Wiklander        # C, since it corresponds to a reverse dependency of B && C.
6698*c689edbbSJens Wiklander        #
6699*c689edbbSJens Wiklander        # Always print reverse dependencies for symbols that have them to make
6700*c689edbbSJens Wiklander        # sure information isn't lost. I wonder if there's some neat way to
6701*c689edbbSJens Wiklander        # improve this.
6702*c689edbbSJens Wiklander
6703*c689edbbSJens Wiklander        if item.__class__ is Symbol:
6704*c689edbbSJens Wiklander            if item.rev_dep is not item.kconfig.n:
6705*c689edbbSJens Wiklander                msg += "(select-related dependencies: {})\n\n" \
6706*c689edbbSJens Wiklander                       .format(expr_str(item.rev_dep))
6707*c689edbbSJens Wiklander
6708*c689edbbSJens Wiklander            if item.weak_rev_dep is not item.kconfig.n:
6709*c689edbbSJens Wiklander                msg += "(imply-related dependencies: {})\n\n" \
6710*c689edbbSJens Wiklander                       .format(expr_str(item.rev_dep))
6711*c689edbbSJens Wiklander
6712*c689edbbSJens Wiklander    msg += "...depends again on " + loop[0].name_and_loc
6713*c689edbbSJens Wiklander
6714*c689edbbSJens Wiklander    raise KconfigError(msg)
6715*c689edbbSJens Wiklander
6716*c689edbbSJens Wiklander
6717*c689edbbSJens Wiklanderdef _decoding_error(e, filename, macro_linenr=None):
6718*c689edbbSJens Wiklander    # Gives the filename and context for UnicodeDecodeError's, which are a pain
6719*c689edbbSJens Wiklander    # to debug otherwise. 'e' is the UnicodeDecodeError object.
6720*c689edbbSJens Wiklander    #
6721*c689edbbSJens Wiklander    # If the decoding error is for the output of a $(shell,...) command,
6722*c689edbbSJens Wiklander    # macro_linenr holds the line number where it was run (the exact line
6723*c689edbbSJens Wiklander    # number isn't available for decoding errors in files).
6724*c689edbbSJens Wiklander
6725*c689edbbSJens Wiklander    raise KconfigError(
6726*c689edbbSJens Wiklander        "\n"
6727*c689edbbSJens Wiklander        "Malformed {} in {}\n"
6728*c689edbbSJens Wiklander        "Context: {}\n"
6729*c689edbbSJens Wiklander        "Problematic data: {}\n"
6730*c689edbbSJens Wiklander        "Reason: {}".format(
6731*c689edbbSJens Wiklander            e.encoding,
6732*c689edbbSJens Wiklander            "'{}'".format(filename) if macro_linenr is None else
6733*c689edbbSJens Wiklander                "output from macro at {}:{}".format(filename, macro_linenr),
6734*c689edbbSJens Wiklander            e.object[max(e.start - 40, 0):e.end + 40],
6735*c689edbbSJens Wiklander            e.object[e.start:e.end],
6736*c689edbbSJens Wiklander            e.reason))
6737*c689edbbSJens Wiklander
6738*c689edbbSJens Wiklander
6739*c689edbbSJens Wiklanderdef _warn_verbose_deprecated(fn_name):
6740*c689edbbSJens Wiklander    sys.stderr.write(
6741*c689edbbSJens Wiklander        "Deprecation warning: {0}()'s 'verbose' argument has no effect. Since "
6742*c689edbbSJens Wiklander        "Kconfiglib 12.0.0, the message is returned from {0}() instead, "
6743*c689edbbSJens Wiklander        "and is always generated. Do e.g. print(kconf.{0}()) if you want to "
6744*c689edbbSJens Wiklander        "want to show a message like \"Loaded configuration '.config'\" on "
6745*c689edbbSJens Wiklander        "stdout. The old API required ugly hacks to reuse messages in "
6746*c689edbbSJens Wiklander        "configuration interfaces.\n".format(fn_name))
6747*c689edbbSJens Wiklander
6748*c689edbbSJens Wiklander
6749*c689edbbSJens Wiklander# Predefined preprocessor functions
6750*c689edbbSJens Wiklander
6751*c689edbbSJens Wiklander
6752*c689edbbSJens Wiklanderdef _filename_fn(kconf, _):
6753*c689edbbSJens Wiklander    return kconf.filename
6754*c689edbbSJens Wiklander
6755*c689edbbSJens Wiklander
6756*c689edbbSJens Wiklanderdef _lineno_fn(kconf, _):
6757*c689edbbSJens Wiklander    return str(kconf.linenr)
6758*c689edbbSJens Wiklander
6759*c689edbbSJens Wiklander
6760*c689edbbSJens Wiklanderdef _info_fn(kconf, _, msg):
6761*c689edbbSJens Wiklander    print("{}:{}: {}".format(kconf.filename, kconf.linenr, msg))
6762*c689edbbSJens Wiklander
6763*c689edbbSJens Wiklander    return ""
6764*c689edbbSJens Wiklander
6765*c689edbbSJens Wiklander
6766*c689edbbSJens Wiklanderdef _warning_if_fn(kconf, _, cond, msg):
6767*c689edbbSJens Wiklander    if cond == "y":
6768*c689edbbSJens Wiklander        kconf._warn(msg, kconf.filename, kconf.linenr)
6769*c689edbbSJens Wiklander
6770*c689edbbSJens Wiklander    return ""
6771*c689edbbSJens Wiklander
6772*c689edbbSJens Wiklander
6773*c689edbbSJens Wiklanderdef _error_if_fn(kconf, _, cond, msg):
6774*c689edbbSJens Wiklander    if cond == "y":
6775*c689edbbSJens Wiklander        raise KconfigError("{}:{}: {}".format(
6776*c689edbbSJens Wiklander            kconf.filename, kconf.linenr, msg))
6777*c689edbbSJens Wiklander
6778*c689edbbSJens Wiklander    return ""
6779*c689edbbSJens Wiklander
6780*c689edbbSJens Wiklander
6781*c689edbbSJens Wiklanderdef _shell_fn(kconf, _, command):
6782*c689edbbSJens Wiklander    import subprocess  # Only import as needed, to save some startup time
6783*c689edbbSJens Wiklander
6784*c689edbbSJens Wiklander    stdout, stderr = subprocess.Popen(
6785*c689edbbSJens Wiklander        command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
6786*c689edbbSJens Wiklander    ).communicate()
6787*c689edbbSJens Wiklander
6788*c689edbbSJens Wiklander    if not _IS_PY2:
6789*c689edbbSJens Wiklander        try:
6790*c689edbbSJens Wiklander            stdout = stdout.decode(kconf._encoding)
6791*c689edbbSJens Wiklander            stderr = stderr.decode(kconf._encoding)
6792*c689edbbSJens Wiklander        except UnicodeDecodeError as e:
6793*c689edbbSJens Wiklander            _decoding_error(e, kconf.filename, kconf.linenr)
6794*c689edbbSJens Wiklander
6795*c689edbbSJens Wiklander    if stderr:
6796*c689edbbSJens Wiklander        kconf._warn("'{}' wrote to stderr: {}".format(
6797*c689edbbSJens Wiklander                        command, "\n".join(stderr.splitlines())),
6798*c689edbbSJens Wiklander                    kconf.filename, kconf.linenr)
6799*c689edbbSJens Wiklander
6800*c689edbbSJens Wiklander    # Universal newlines with splitlines() (to prevent e.g. stray \r's in
6801*c689edbbSJens Wiklander    # command output on Windows), trailing newline removal, and
6802*c689edbbSJens Wiklander    # newline-to-space conversion.
6803*c689edbbSJens Wiklander    #
6804*c689edbbSJens Wiklander    # On Python 3 versions before 3.6, it's not possible to specify the
6805*c689edbbSJens Wiklander    # encoding when passing universal_newlines=True to Popen() (the 'encoding'
6806*c689edbbSJens Wiklander    # parameter was added in 3.6), so we do this manual version instead.
6807*c689edbbSJens Wiklander    return "\n".join(stdout.splitlines()).rstrip("\n").replace("\n", " ")
6808*c689edbbSJens Wiklander
6809*c689edbbSJens Wiklander#
6810*c689edbbSJens Wiklander# Global constants
6811*c689edbbSJens Wiklander#
6812*c689edbbSJens Wiklander
6813*c689edbbSJens WiklanderTRI_TO_STR = {
6814*c689edbbSJens Wiklander    0: "n",
6815*c689edbbSJens Wiklander    1: "m",
6816*c689edbbSJens Wiklander    2: "y",
6817*c689edbbSJens Wiklander}
6818*c689edbbSJens Wiklander
6819*c689edbbSJens WiklanderSTR_TO_TRI = {
6820*c689edbbSJens Wiklander    "n": 0,
6821*c689edbbSJens Wiklander    "m": 1,
6822*c689edbbSJens Wiklander    "y": 2,
6823*c689edbbSJens Wiklander}
6824*c689edbbSJens Wiklander
6825*c689edbbSJens Wiklander# Constant representing that there's no cached choice selection. This is
6826*c689edbbSJens Wiklander# distinct from a cached None (no selection). Any object that's not None or a
6827*c689edbbSJens Wiklander# Symbol will do. We test this with 'is'.
6828*c689edbbSJens Wiklander_NO_CACHED_SELECTION = 0
6829*c689edbbSJens Wiklander
6830*c689edbbSJens Wiklander# Are we running on Python 2?
6831*c689edbbSJens Wiklander_IS_PY2 = sys.version_info[0] < 3
6832*c689edbbSJens Wiklander
6833*c689edbbSJens Wiklandertry:
6834*c689edbbSJens Wiklander    _UNAME_RELEASE = os.uname()[2]
6835*c689edbbSJens Wiklanderexcept AttributeError:
6836*c689edbbSJens Wiklander    # Only import as needed, to save some startup time
6837*c689edbbSJens Wiklander    import platform
6838*c689edbbSJens Wiklander    _UNAME_RELEASE = platform.uname()[2]
6839*c689edbbSJens Wiklander
6840*c689edbbSJens Wiklander# The token and type constants below are safe to test with 'is', which is a bit
6841*c689edbbSJens Wiklander# faster (~30% faster on my machine, and a few % faster for total parsing
6842*c689edbbSJens Wiklander# time), even without assuming Python's small integer optimization (which
6843*c689edbbSJens Wiklander# caches small integer objects). The constants end up pointing to unique
6844*c689edbbSJens Wiklander# integer objects, and since we consistently refer to them via the names below,
6845*c689edbbSJens Wiklander# we always get the same object.
6846*c689edbbSJens Wiklander#
6847*c689edbbSJens Wiklander# Client code should use == though.
6848*c689edbbSJens Wiklander
6849*c689edbbSJens Wiklander# Tokens, with values 1, 2, ... . Avoiding 0 simplifies some checks by making
6850*c689edbbSJens Wiklander# all tokens except empty strings truthy.
6851*c689edbbSJens Wiklander(
6852*c689edbbSJens Wiklander    _T_ALLNOCONFIG_Y,
6853*c689edbbSJens Wiklander    _T_AND,
6854*c689edbbSJens Wiklander    _T_BOOL,
6855*c689edbbSJens Wiklander    _T_CHOICE,
6856*c689edbbSJens Wiklander    _T_CLOSE_PAREN,
6857*c689edbbSJens Wiklander    _T_COMMENT,
6858*c689edbbSJens Wiklander    _T_CONFIG,
6859*c689edbbSJens Wiklander    _T_DEFAULT,
6860*c689edbbSJens Wiklander    _T_DEFCONFIG_LIST,
6861*c689edbbSJens Wiklander    _T_DEF_BOOL,
6862*c689edbbSJens Wiklander    _T_DEF_HEX,
6863*c689edbbSJens Wiklander    _T_DEF_INT,
6864*c689edbbSJens Wiklander    _T_DEF_STRING,
6865*c689edbbSJens Wiklander    _T_DEF_TRISTATE,
6866*c689edbbSJens Wiklander    _T_DEPENDS,
6867*c689edbbSJens Wiklander    _T_ENDCHOICE,
6868*c689edbbSJens Wiklander    _T_ENDIF,
6869*c689edbbSJens Wiklander    _T_ENDMENU,
6870*c689edbbSJens Wiklander    _T_ENV,
6871*c689edbbSJens Wiklander    _T_EQUAL,
6872*c689edbbSJens Wiklander    _T_GREATER,
6873*c689edbbSJens Wiklander    _T_GREATER_EQUAL,
6874*c689edbbSJens Wiklander    _T_HELP,
6875*c689edbbSJens Wiklander    _T_HEX,
6876*c689edbbSJens Wiklander    _T_IF,
6877*c689edbbSJens Wiklander    _T_IMPLY,
6878*c689edbbSJens Wiklander    _T_INT,
6879*c689edbbSJens Wiklander    _T_LESS,
6880*c689edbbSJens Wiklander    _T_LESS_EQUAL,
6881*c689edbbSJens Wiklander    _T_MAINMENU,
6882*c689edbbSJens Wiklander    _T_MENU,
6883*c689edbbSJens Wiklander    _T_MENUCONFIG,
6884*c689edbbSJens Wiklander    _T_MODULES,
6885*c689edbbSJens Wiklander    _T_NOT,
6886*c689edbbSJens Wiklander    _T_ON,
6887*c689edbbSJens Wiklander    _T_OPEN_PAREN,
6888*c689edbbSJens Wiklander    _T_OPTION,
6889*c689edbbSJens Wiklander    _T_OPTIONAL,
6890*c689edbbSJens Wiklander    _T_OR,
6891*c689edbbSJens Wiklander    _T_ORSOURCE,
6892*c689edbbSJens Wiklander    _T_OSOURCE,
6893*c689edbbSJens Wiklander    _T_PROMPT,
6894*c689edbbSJens Wiklander    _T_RANGE,
6895*c689edbbSJens Wiklander    _T_RSOURCE,
6896*c689edbbSJens Wiklander    _T_SELECT,
6897*c689edbbSJens Wiklander    _T_SOURCE,
6898*c689edbbSJens Wiklander    _T_STRING,
6899*c689edbbSJens Wiklander    _T_TRISTATE,
6900*c689edbbSJens Wiklander    _T_UNEQUAL,
6901*c689edbbSJens Wiklander    _T_VISIBLE,
6902*c689edbbSJens Wiklander) = range(1, 51)
6903*c689edbbSJens Wiklander
6904*c689edbbSJens Wiklander# Keyword to token map, with the get() method assigned directly as a small
6905*c689edbbSJens Wiklander# optimization
6906*c689edbbSJens Wiklander_get_keyword = {
6907*c689edbbSJens Wiklander    "---help---":     _T_HELP,
6908*c689edbbSJens Wiklander    "allnoconfig_y":  _T_ALLNOCONFIG_Y,
6909*c689edbbSJens Wiklander    "bool":           _T_BOOL,
6910*c689edbbSJens Wiklander    "boolean":        _T_BOOL,
6911*c689edbbSJens Wiklander    "choice":         _T_CHOICE,
6912*c689edbbSJens Wiklander    "comment":        _T_COMMENT,
6913*c689edbbSJens Wiklander    "config":         _T_CONFIG,
6914*c689edbbSJens Wiklander    "def_bool":       _T_DEF_BOOL,
6915*c689edbbSJens Wiklander    "def_hex":        _T_DEF_HEX,
6916*c689edbbSJens Wiklander    "def_int":        _T_DEF_INT,
6917*c689edbbSJens Wiklander    "def_string":     _T_DEF_STRING,
6918*c689edbbSJens Wiklander    "def_tristate":   _T_DEF_TRISTATE,
6919*c689edbbSJens Wiklander    "default":        _T_DEFAULT,
6920*c689edbbSJens Wiklander    "defconfig_list": _T_DEFCONFIG_LIST,
6921*c689edbbSJens Wiklander    "depends":        _T_DEPENDS,
6922*c689edbbSJens Wiklander    "endchoice":      _T_ENDCHOICE,
6923*c689edbbSJens Wiklander    "endif":          _T_ENDIF,
6924*c689edbbSJens Wiklander    "endmenu":        _T_ENDMENU,
6925*c689edbbSJens Wiklander    "env":            _T_ENV,
6926*c689edbbSJens Wiklander    "grsource":       _T_ORSOURCE,  # Backwards compatibility
6927*c689edbbSJens Wiklander    "gsource":        _T_OSOURCE,   # Backwards compatibility
6928*c689edbbSJens Wiklander    "help":           _T_HELP,
6929*c689edbbSJens Wiklander    "hex":            _T_HEX,
6930*c689edbbSJens Wiklander    "if":             _T_IF,
6931*c689edbbSJens Wiklander    "imply":          _T_IMPLY,
6932*c689edbbSJens Wiklander    "int":            _T_INT,
6933*c689edbbSJens Wiklander    "mainmenu":       _T_MAINMENU,
6934*c689edbbSJens Wiklander    "menu":           _T_MENU,
6935*c689edbbSJens Wiklander    "menuconfig":     _T_MENUCONFIG,
6936*c689edbbSJens Wiklander    "modules":        _T_MODULES,
6937*c689edbbSJens Wiklander    "on":             _T_ON,
6938*c689edbbSJens Wiklander    "option":         _T_OPTION,
6939*c689edbbSJens Wiklander    "optional":       _T_OPTIONAL,
6940*c689edbbSJens Wiklander    "orsource":       _T_ORSOURCE,
6941*c689edbbSJens Wiklander    "osource":        _T_OSOURCE,
6942*c689edbbSJens Wiklander    "prompt":         _T_PROMPT,
6943*c689edbbSJens Wiklander    "range":          _T_RANGE,
6944*c689edbbSJens Wiklander    "rsource":        _T_RSOURCE,
6945*c689edbbSJens Wiklander    "select":         _T_SELECT,
6946*c689edbbSJens Wiklander    "source":         _T_SOURCE,
6947*c689edbbSJens Wiklander    "string":         _T_STRING,
6948*c689edbbSJens Wiklander    "tristate":       _T_TRISTATE,
6949*c689edbbSJens Wiklander    "visible":        _T_VISIBLE,
6950*c689edbbSJens Wiklander}.get
6951*c689edbbSJens Wiklander
6952*c689edbbSJens Wiklander# The constants below match the value of the corresponding tokens to remove the
6953*c689edbbSJens Wiklander# need for conversion
6954*c689edbbSJens Wiklander
6955*c689edbbSJens Wiklander# Node types
6956*c689edbbSJens WiklanderMENU    = _T_MENU
6957*c689edbbSJens WiklanderCOMMENT = _T_COMMENT
6958*c689edbbSJens Wiklander
6959*c689edbbSJens Wiklander# Expression types
6960*c689edbbSJens WiklanderAND           = _T_AND
6961*c689edbbSJens WiklanderOR            = _T_OR
6962*c689edbbSJens WiklanderNOT           = _T_NOT
6963*c689edbbSJens WiklanderEQUAL         = _T_EQUAL
6964*c689edbbSJens WiklanderUNEQUAL       = _T_UNEQUAL
6965*c689edbbSJens WiklanderLESS          = _T_LESS
6966*c689edbbSJens WiklanderLESS_EQUAL    = _T_LESS_EQUAL
6967*c689edbbSJens WiklanderGREATER       = _T_GREATER
6968*c689edbbSJens WiklanderGREATER_EQUAL = _T_GREATER_EQUAL
6969*c689edbbSJens Wiklander
6970*c689edbbSJens WiklanderREL_TO_STR = {
6971*c689edbbSJens Wiklander    EQUAL:         "=",
6972*c689edbbSJens Wiklander    UNEQUAL:       "!=",
6973*c689edbbSJens Wiklander    LESS:          "<",
6974*c689edbbSJens Wiklander    LESS_EQUAL:    "<=",
6975*c689edbbSJens Wiklander    GREATER:       ">",
6976*c689edbbSJens Wiklander    GREATER_EQUAL: ">=",
6977*c689edbbSJens Wiklander}
6978*c689edbbSJens Wiklander
6979*c689edbbSJens Wiklander# Symbol/choice types. UNKNOWN is 0 (falsy) to simplify some checks.
6980*c689edbbSJens Wiklander# Client code shouldn't rely on it though, as it was non-zero in
6981*c689edbbSJens Wiklander# older versions.
6982*c689edbbSJens WiklanderUNKNOWN  = 0
6983*c689edbbSJens WiklanderBOOL     = _T_BOOL
6984*c689edbbSJens WiklanderTRISTATE = _T_TRISTATE
6985*c689edbbSJens WiklanderSTRING   = _T_STRING
6986*c689edbbSJens WiklanderINT      = _T_INT
6987*c689edbbSJens WiklanderHEX      = _T_HEX
6988*c689edbbSJens Wiklander
6989*c689edbbSJens WiklanderTYPE_TO_STR = {
6990*c689edbbSJens Wiklander    UNKNOWN:  "unknown",
6991*c689edbbSJens Wiklander    BOOL:     "bool",
6992*c689edbbSJens Wiklander    TRISTATE: "tristate",
6993*c689edbbSJens Wiklander    STRING:   "string",
6994*c689edbbSJens Wiklander    INT:      "int",
6995*c689edbbSJens Wiklander    HEX:      "hex",
6996*c689edbbSJens Wiklander}
6997*c689edbbSJens Wiklander
6998*c689edbbSJens Wiklander# Used in comparisons. 0 means the base is inferred from the format of the
6999*c689edbbSJens Wiklander# string.
7000*c689edbbSJens Wiklander_TYPE_TO_BASE = {
7001*c689edbbSJens Wiklander    HEX:      16,
7002*c689edbbSJens Wiklander    INT:      10,
7003*c689edbbSJens Wiklander    STRING:   0,
7004*c689edbbSJens Wiklander    UNKNOWN:  0,
7005*c689edbbSJens Wiklander}
7006*c689edbbSJens Wiklander
7007*c689edbbSJens Wiklander# def_bool -> BOOL, etc.
7008*c689edbbSJens Wiklander_DEF_TOKEN_TO_TYPE = {
7009*c689edbbSJens Wiklander    _T_DEF_BOOL:     BOOL,
7010*c689edbbSJens Wiklander    _T_DEF_HEX:      HEX,
7011*c689edbbSJens Wiklander    _T_DEF_INT:      INT,
7012*c689edbbSJens Wiklander    _T_DEF_STRING:   STRING,
7013*c689edbbSJens Wiklander    _T_DEF_TRISTATE: TRISTATE,
7014*c689edbbSJens Wiklander}
7015*c689edbbSJens Wiklander
7016*c689edbbSJens Wiklander# Tokens after which strings are expected. This is used to tell strings from
7017*c689edbbSJens Wiklander# constant symbol references during tokenization, both of which are enclosed in
7018*c689edbbSJens Wiklander# quotes.
7019*c689edbbSJens Wiklander#
7020*c689edbbSJens Wiklander# Identifier-like lexemes ("missing quotes") are also treated as strings after
7021*c689edbbSJens Wiklander# these tokens. _T_CHOICE is included to avoid symbols being registered for
7022*c689edbbSJens Wiklander# named choices.
7023*c689edbbSJens Wiklander_STRING_LEX = frozenset({
7024*c689edbbSJens Wiklander    _T_BOOL,
7025*c689edbbSJens Wiklander    _T_CHOICE,
7026*c689edbbSJens Wiklander    _T_COMMENT,
7027*c689edbbSJens Wiklander    _T_HEX,
7028*c689edbbSJens Wiklander    _T_INT,
7029*c689edbbSJens Wiklander    _T_MAINMENU,
7030*c689edbbSJens Wiklander    _T_MENU,
7031*c689edbbSJens Wiklander    _T_ORSOURCE,
7032*c689edbbSJens Wiklander    _T_OSOURCE,
7033*c689edbbSJens Wiklander    _T_PROMPT,
7034*c689edbbSJens Wiklander    _T_RSOURCE,
7035*c689edbbSJens Wiklander    _T_SOURCE,
7036*c689edbbSJens Wiklander    _T_STRING,
7037*c689edbbSJens Wiklander    _T_TRISTATE,
7038*c689edbbSJens Wiklander})
7039*c689edbbSJens Wiklander
7040*c689edbbSJens Wiklander# Various sets for quick membership tests. Gives a single global lookup and
7041*c689edbbSJens Wiklander# avoids creating temporary dicts/tuples.
7042*c689edbbSJens Wiklander
7043*c689edbbSJens Wiklander_TYPE_TOKENS = frozenset({
7044*c689edbbSJens Wiklander    _T_BOOL,
7045*c689edbbSJens Wiklander    _T_TRISTATE,
7046*c689edbbSJens Wiklander    _T_INT,
7047*c689edbbSJens Wiklander    _T_HEX,
7048*c689edbbSJens Wiklander    _T_STRING,
7049*c689edbbSJens Wiklander})
7050*c689edbbSJens Wiklander
7051*c689edbbSJens Wiklander_SOURCE_TOKENS = frozenset({
7052*c689edbbSJens Wiklander    _T_SOURCE,
7053*c689edbbSJens Wiklander    _T_RSOURCE,
7054*c689edbbSJens Wiklander    _T_OSOURCE,
7055*c689edbbSJens Wiklander    _T_ORSOURCE,
7056*c689edbbSJens Wiklander})
7057*c689edbbSJens Wiklander
7058*c689edbbSJens Wiklander_REL_SOURCE_TOKENS = frozenset({
7059*c689edbbSJens Wiklander    _T_RSOURCE,
7060*c689edbbSJens Wiklander    _T_ORSOURCE,
7061*c689edbbSJens Wiklander})
7062*c689edbbSJens Wiklander
7063*c689edbbSJens Wiklander# Obligatory (non-optional) sources
7064*c689edbbSJens Wiklander_OBL_SOURCE_TOKENS = frozenset({
7065*c689edbbSJens Wiklander    _T_SOURCE,
7066*c689edbbSJens Wiklander    _T_RSOURCE,
7067*c689edbbSJens Wiklander})
7068*c689edbbSJens Wiklander
7069*c689edbbSJens Wiklander_BOOL_TRISTATE = frozenset({
7070*c689edbbSJens Wiklander    BOOL,
7071*c689edbbSJens Wiklander    TRISTATE,
7072*c689edbbSJens Wiklander})
7073*c689edbbSJens Wiklander
7074*c689edbbSJens Wiklander_BOOL_TRISTATE_UNKNOWN = frozenset({
7075*c689edbbSJens Wiklander    BOOL,
7076*c689edbbSJens Wiklander    TRISTATE,
7077*c689edbbSJens Wiklander    UNKNOWN,
7078*c689edbbSJens Wiklander})
7079*c689edbbSJens Wiklander
7080*c689edbbSJens Wiklander_INT_HEX = frozenset({
7081*c689edbbSJens Wiklander    INT,
7082*c689edbbSJens Wiklander    HEX,
7083*c689edbbSJens Wiklander})
7084*c689edbbSJens Wiklander
7085*c689edbbSJens Wiklander_SYMBOL_CHOICE = frozenset({
7086*c689edbbSJens Wiklander    Symbol,
7087*c689edbbSJens Wiklander    Choice,
7088*c689edbbSJens Wiklander})
7089*c689edbbSJens Wiklander
7090*c689edbbSJens Wiklander_MENU_COMMENT = frozenset({
7091*c689edbbSJens Wiklander    MENU,
7092*c689edbbSJens Wiklander    COMMENT,
7093*c689edbbSJens Wiklander})
7094*c689edbbSJens Wiklander
7095*c689edbbSJens Wiklander_EQUAL_UNEQUAL = frozenset({
7096*c689edbbSJens Wiklander    EQUAL,
7097*c689edbbSJens Wiklander    UNEQUAL,
7098*c689edbbSJens Wiklander})
7099*c689edbbSJens Wiklander
7100*c689edbbSJens Wiklander_RELATIONS = frozenset({
7101*c689edbbSJens Wiklander    EQUAL,
7102*c689edbbSJens Wiklander    UNEQUAL,
7103*c689edbbSJens Wiklander    LESS,
7104*c689edbbSJens Wiklander    LESS_EQUAL,
7105*c689edbbSJens Wiklander    GREATER,
7106*c689edbbSJens Wiklander    GREATER_EQUAL,
7107*c689edbbSJens Wiklander})
7108*c689edbbSJens Wiklander
7109*c689edbbSJens Wiklander# Helper functions for getting compiled regular expressions, with the needed
7110*c689edbbSJens Wiklander# matching function returned directly as a small optimization.
7111*c689edbbSJens Wiklander#
7112*c689edbbSJens Wiklander# Use ASCII regex matching on Python 3. It's already the default on Python 2.
7113*c689edbbSJens Wiklander
7114*c689edbbSJens Wiklander
7115*c689edbbSJens Wiklanderdef _re_match(regex):
7116*c689edbbSJens Wiklander    return re.compile(regex, 0 if _IS_PY2 else re.ASCII).match
7117*c689edbbSJens Wiklander
7118*c689edbbSJens Wiklander
7119*c689edbbSJens Wiklanderdef _re_search(regex):
7120*c689edbbSJens Wiklander    return re.compile(regex, 0 if _IS_PY2 else re.ASCII).search
7121*c689edbbSJens Wiklander
7122*c689edbbSJens Wiklander
7123*c689edbbSJens Wiklander# Various regular expressions used during parsing
7124*c689edbbSJens Wiklander
7125*c689edbbSJens Wiklander# The initial token on a line. Also eats leading and trailing whitespace, so
7126*c689edbbSJens Wiklander# that we can jump straight to the next token (or to the end of the line if
7127*c689edbbSJens Wiklander# there is only one token).
7128*c689edbbSJens Wiklander#
7129*c689edbbSJens Wiklander# This regex will also fail to match for empty lines and comment lines.
7130*c689edbbSJens Wiklander#
7131*c689edbbSJens Wiklander# '$' is included to detect preprocessor variable assignments with macro
7132*c689edbbSJens Wiklander# expansions in the left-hand side.
7133*c689edbbSJens Wiklander_command_match = _re_match(r"\s*([A-Za-z0-9_$-]+)\s*")
7134*c689edbbSJens Wiklander
7135*c689edbbSJens Wiklander# An identifier/keyword after the first token. Also eats trailing whitespace.
7136*c689edbbSJens Wiklander# '$' is included to detect identifiers containing macro expansions.
7137*c689edbbSJens Wiklander_id_keyword_match = _re_match(r"([A-Za-z0-9_$/.-]+)\s*")
7138*c689edbbSJens Wiklander
7139*c689edbbSJens Wiklander# A fragment in the left-hand side of a preprocessor variable assignment. These
7140*c689edbbSJens Wiklander# are the portions between macro expansions ($(foo)). Macros are supported in
7141*c689edbbSJens Wiklander# the LHS (variable name).
7142*c689edbbSJens Wiklander_assignment_lhs_fragment_match = _re_match("[A-Za-z0-9_-]*")
7143*c689edbbSJens Wiklander
7144*c689edbbSJens Wiklander# The assignment operator and value (right-hand side) in a preprocessor
7145*c689edbbSJens Wiklander# variable assignment
7146*c689edbbSJens Wiklander_assignment_rhs_match = _re_match(r"\s*(=|:=|\+=)\s*(.*)")
7147*c689edbbSJens Wiklander
7148*c689edbbSJens Wiklander# Special characters/strings while expanding a macro ('(', ')', ',', and '$(')
7149*c689edbbSJens Wiklander_macro_special_search = _re_search(r"\(|\)|,|\$\(")
7150*c689edbbSJens Wiklander
7151*c689edbbSJens Wiklander# Special characters/strings while expanding a string (quotes, '\', and '$(')
7152*c689edbbSJens Wiklander_string_special_search = _re_search(r'"|\'|\\|\$\(')
7153*c689edbbSJens Wiklander
7154*c689edbbSJens Wiklander# Special characters/strings while expanding a symbol name. Also includes
7155*c689edbbSJens Wiklander# end-of-line, in case the macro is the last thing on the line.
7156*c689edbbSJens Wiklander_name_special_search = _re_search(r'[^A-Za-z0-9_$/.-]|\$\(|$')
7157*c689edbbSJens Wiklander
7158*c689edbbSJens Wiklander# A valid right-hand side for an assignment to a string symbol in a .config
7159*c689edbbSJens Wiklander# file, including escaped characters. Extracts the contents.
7160*c689edbbSJens Wiklander_conf_string_match = _re_match(r'"((?:[^\\"]|\\.)*)"')
7161