9
9
10
10
import kconfiglib
11
11
12
- # "Extend" the standard kconfiglib.expr_str() to turn references to defined
13
- # Kconfig symbols into RST links. Symbol.__str__() will then use the extended
14
- # version.
15
- #
16
- # This is a bit hacky, but better than reimplementing Symbol.__str__() and/or
17
- # kconfiglib.expr_str().
18
-
19
- def expr_str_rst ( expr ):
20
- # Skip constant and undefined symbols by checking if expr.nodes is empty
21
- if isinstance ( expr , kconfiglib . Symbol ) and expr .nodes :
22
- # The "\ " avoids RST issues for !CONFIG_FOO -- see
23
- # http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#character-level-inline-markup
24
- return r"\ :option:`{0} <CONFIG_{0}>`" .format (expr .name )
25
-
26
- # Choices appear as dependencies of choice symbols.
27
- #
28
- # Use a :ref: instead of an :option:. With an :option:, we'd have to have
29
- # an '.. option::' in the choice reference page as well. That would make
30
- # the internal choice ID show up in the documentation.
31
- #
32
- # Note that the first pair of <...> is non-syntactic here. We just display
33
- # choices links within <> in the documentation.
34
- if isinstance ( expr , kconfiglib . Choice ):
12
+
13
+ def rst_link ( sc ):
14
+ # Returns an RST link (string) for the symbol/choice 'sc', or the normal
15
+ # Kconfig expression format (e.g. just the name) for 'sc' if it can't be
16
+ # turned into a link.
17
+
18
+ if isinstance ( sc , kconfiglib . Symbol ):
19
+ # Skip constant and undefined symbols by checking if expr.nodes is
20
+ # empty
21
+ if sc .nodes :
22
+ # The "\ " avoids RST issues for !CONFIG_FOO -- see
23
+ # http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#character-level-inline-markup
24
+ return r"\ :option:`{0} <CONFIG_{0}>`" .format (sc .name )
25
+
26
+ elif isinstance ( sc , kconfiglib . Choice ):
27
+ # Choices appear as dependencies of choice symbols.
28
+ #
29
+ # Use a :ref: instead of an :option:. With an :option:, we'd have to have
30
+ # an '.. option::' in the choice reference page as well. That would make
31
+ # the internal choice ID show up in the documentation.
32
+ #
33
+ # Note that the first pair of <...> is non-syntactic here. We just display
34
+ # choices links within <> in the documentation.
35
35
return r"\ :ref:`<{}> <{}>`" \
36
- .format (choice_desc (expr ), choice_id (expr ))
36
+ .format (choice_desc (sc ), choice_id (sc ))
37
+
38
+ # Can't turn 'sc' into a link. Use the standard Kconfig format.
39
+ return kconfiglib .standard_sc_expr_str (sc )
37
40
38
- # We'll end up back in expr_str_rst() when expr_str_orig() does recursive
39
- # calls for subexpressions
40
- return expr_str_orig (expr )
41
41
42
- expr_str_orig = kconfiglib .expr_str
43
- kconfiglib .expr_str = expr_str_rst
42
+ def expr_str (expr ):
43
+ # Returns the Kconfig representation of 'expr', with symbols/choices turned
44
+ # into RST links
45
+
46
+ return kconfiglib .expr_str (expr , rst_link )
44
47
45
48
46
49
INDEX_RST_HEADER = """.. _configuration:
@@ -87,12 +90,8 @@ def write_kconfig_rst():
87
90
# String with the RST for the index page
88
91
index_rst = INDEX_RST_HEADER
89
92
90
- # - Sort the symbols by name so that they end up in sorted order in
91
- # index.rst
92
- #
93
- # - Use set() to get rid of duplicates for symbols defined in multiple
94
- # locations.
95
- for sym in sorted (set (kconf .defined_syms ), key = lambda sym : sym .name ):
93
+ # Sort the symbols by name so that they end up in sorted order in index.rst
94
+ for sym in sorted (kconf .unique_defined_syms , key = lambda sym : sym .name ):
96
95
# Write an RST file for the symbol
97
96
write_sym_rst (sym , out_dir )
98
97
@@ -104,7 +103,7 @@ def write_kconfig_rst():
104
103
" / " .join (node .prompt [0 ]
105
104
for node in sym .nodes if node .prompt ))
106
105
107
- for choice in kconf .choices :
106
+ for choice in kconf .unique_choices :
108
107
# Write an RST file for the choice
109
108
write_choice_rst (choice , out_dir )
110
109
@@ -120,6 +119,7 @@ def write_sym_rst(sym, out_dir):
120
119
direct_deps_rst (sym ) +
121
120
defaults_rst (sym ) +
122
121
select_imply_rst (sym ) +
122
+ selecting_implying_rst (sym ) +
123
123
kconfig_definition_rst (sym ))
124
124
125
125
@@ -202,24 +202,39 @@ def direct_deps_rst(sc):
202
202
"===================\n \n " \
203
203
"{}\n \n " \
204
204
"*(Includes any dependencies from if's and menus.)*\n \n " \
205
- .format (kconfiglib . expr_str (sc .direct_dep ))
205
+ .format (expr_str (sc .direct_dep ))
206
206
207
207
208
208
def defaults_rst (sc ):
209
209
# Returns RST that lists the 'default' properties of 'sc' (symbol or
210
210
# choice)
211
211
212
- if not sc .defaults :
212
+ if isinstance (sc , kconfiglib .Symbol ) and sc .choice :
213
+ # 'default's on choice symbols have no effect (and generate a warning).
214
+ # The implicit value hint below would be misleading as well.
213
215
return ""
214
216
215
217
rst = "Defaults\n " \
216
218
"========\n \n "
217
219
218
- for value , cond in sc .defaults :
219
- default_str = kconfiglib .expr_str (value )
220
- if cond is not sc .kconfig .y :
221
- default_str += " if " + kconfiglib .expr_str (cond )
222
- rst += "- {}\n " .format (default_str )
220
+ if sc .defaults :
221
+ for value , cond in sc .defaults :
222
+ rst += "- " + expr_str (value )
223
+ if cond is not sc .kconfig .y :
224
+ rst += " if " + expr_str (cond )
225
+ rst += "\n "
226
+
227
+ else :
228
+ rst += "No defaults. Implicitly defaults to "
229
+
230
+ if isinstance (sc , kconfiglib .Choice ):
231
+ rst += "the first (visible) choice option.\n "
232
+ elif sc .orig_type in (kconfiglib .BOOL , kconfiglib .TRISTATE ):
233
+ rst += "``n``.\n "
234
+ else :
235
+ # This is accurate even for int/hex symbols, though an active
236
+ # 'range' might clamp the value (which is then treated as zero)
237
+ rst += "the empty string.\n "
223
238
224
239
return rst + "\n "
225
240
@@ -235,53 +250,95 @@ def choice_syms_rst(choice):
235
250
236
251
for sym in choice .syms :
237
252
# Generates a link
238
- rst += "- {}\n " .format (kconfiglib . expr_str (sym ))
253
+ rst += "- {}\n " .format (expr_str (sym ))
239
254
240
255
return rst + "\n "
241
256
242
257
243
258
def select_imply_rst (sym ):
259
+ # Returns RST that lists the symbols 'select'ed or 'imply'd by the symbol
260
+
261
+ rst = ""
262
+
263
+ def add_select_imply_rst (type_str , lst ):
264
+ # Adds RST that lists the selects/implies from 'lst', which holds
265
+ # (<symbol>, <condition>) tuples, if any. Also adds a heading derived
266
+ # from 'type_str' if there any selects/implies.
267
+
268
+ nonlocal rst
269
+
270
+ if lst :
271
+ heading = "Symbols {} by this symbol" .format (type_str )
272
+ rst += "{}\n {}\n \n " .format (heading , len (heading )* "=" )
273
+
274
+ for select , cond in lst :
275
+ rst += "- " + rst_link (select )
276
+ if cond is not sym .kconfig .y :
277
+ rst += " if " + expr_str (cond )
278
+ rst += "\n "
279
+
280
+ rst += "\n "
281
+
282
+ add_select_imply_rst ("selected" , sym .selects )
283
+ add_select_imply_rst ("implied" , sym .implies )
284
+
285
+ return rst
286
+
287
+
288
+ def selecting_implying_rst (sym ):
244
289
# Returns RST that lists the symbols that are 'select'ing or 'imply'ing the
245
290
# symbol
246
291
247
292
rst = ""
248
293
249
- def add_select_imply_rst (type_str , expr ):
250
- # Writes a link for each selecting symbol (if 'expr' is sym.rev_dep) or
251
- # each implying symbol (if 'expr' is sym.weak_rev_dep). Also adds a
252
- # heading at the top, derived from type_str ("select"/"imply").
294
+ def add_selecting_implying_rst (type_str , expr ):
295
+ # Writes a link for each symbol that selects the symbol (if 'expr' is
296
+ # sym.rev_dep) or each symbol that imply's the symbol (if 'expr' is
297
+ # sym.weak_rev_dep). Also adds a heading at the top derived from
298
+ # type_str ("select"/"imply"), if there are any selecting/implying
299
+ # symbols.
253
300
254
301
nonlocal rst
255
302
256
- heading = "Symbols that ``{}`` this symbol" .format (type_str )
257
- rst += "{}\n {}\n \n " .format (heading , len (heading )* "=" )
303
+ if expr is not sym .kconfig .n :
304
+ heading = "Symbols that {} this symbol" .format (type_str )
305
+ rst += "{}\n {}\n \n " .format (heading , len (heading )* "=" )
258
306
259
- # The reverse dependencies from each select/imply are ORed together
260
- for select in kconfiglib .split_expr (expr , kconfiglib .OR ):
261
- # - 'select/imply A if B' turns into A && B
262
- # - 'select/imply A' just turns into A
263
- #
264
- # In both cases, we can split on AND and pick the first
265
- # operand.
307
+ # The reverse dependencies from each select/imply are ORed together
308
+ for select in kconfiglib .split_expr (expr , kconfiglib .OR ):
309
+ # - 'select/imply A if B' turns into A && B
310
+ # - 'select/imply A' just turns into A
311
+ #
312
+ # In both cases, we can split on AND and pick the first
313
+ # operand.
266
314
267
- # kconfiglib.expr_str() generates a link
268
- rst += "- {}\n " .format (kconfiglib .expr_str (
269
- kconfiglib .split_expr (select , kconfiglib .AND )[0 ]))
315
+ rst += "- {}\n " .format (rst_link (
316
+ kconfiglib .split_expr (select , kconfiglib .AND )[0 ]))
270
317
271
- rst += "\n "
318
+ rst += "\n "
272
319
273
- if sym .rev_dep is not sym .kconfig .n :
274
- add_select_imply_rst ("select" , sym .rev_dep )
275
-
276
- if sym .weak_rev_dep is not sym .kconfig .n :
277
- add_select_imply_rst ("imply" , sym .weak_rev_dep )
320
+ add_selecting_implying_rst ("select" , sym .rev_dep )
321
+ add_selecting_implying_rst ("imply" , sym .weak_rev_dep )
278
322
279
323
return rst
280
324
281
325
282
326
def kconfig_definition_rst (sc ):
283
- # Returns RST that lists the Kconfig definition(s) of 'sc' (symbol or
284
- # choice)
327
+ # Returns RST that lists the Kconfig definition location, include path,
328
+ # menu path, and Kconfig definition for each node (definition location) of
329
+ # 'sc' (symbol or choice)
330
+
331
+ # Fancy Unicode arrow. Added in '93, so ought to be pretty safe.
332
+ arrow = " \N{RIGHTWARDS ARROW} "
333
+
334
+ def include_path (node ):
335
+ if not node .include_path :
336
+ # In the top-level Kconfig file
337
+ return ""
338
+
339
+ return "Included via {}\n \n " .format (
340
+ arrow .join ("``{}:{}``" .format (filename , linenr )
341
+ for filename , linenr in node .include_path ))
285
342
286
343
def menu_path (node ):
287
344
path = ""
@@ -299,23 +356,30 @@ def menu_path(node):
299
356
if node is node .kconfig .top_node :
300
357
break
301
358
302
- # Fancy Unicode arrow. Added in '93, so ought to be pretty safe.
303
- path = " → " + node .prompt [0 ] + path
359
+ path = arrow + node .prompt [0 ] + path
304
360
305
361
return "(top menu)" + path
306
362
307
363
heading = "Kconfig definition"
308
364
if len (sc .nodes ) > 1 : heading += "s"
309
365
rst = "{}\n {}\n \n " .format (heading , len (heading )* "=" )
310
366
311
- rst += ".. highlight:: kconfig\n \n "
367
+ rst += ".. highlight:: kconfig"
312
368
313
- rst += "\n \n " .join (
314
- "At ``{}:{}``, in menu ``{}``:\n \n "
315
- ".. parsed-literal::\n \n "
316
- "{}" .format (node .filename , node .linenr , menu_path (node ),
317
- textwrap .indent (str (node ), " " * 4 ))
318
- for node in sc .nodes )
369
+ for node in sc .nodes :
370
+ rst += "\n \n " \
371
+ "At ``{}:{}``\n \n " \
372
+ "{}" \
373
+ "Menu path: {}\n \n " \
374
+ ".. parsed-literal::\n \n {}" \
375
+ .format (node .filename , node .linenr ,
376
+ include_path (node ), menu_path (node ),
377
+ textwrap .indent (node .custom_str (rst_link ), 4 * " " ))
378
+
379
+ # Not the last node?
380
+ if node is not sc .nodes [- 1 ]:
381
+ # Add a horizontal line between multiple definitions
382
+ rst += "\n \n ----"
319
383
320
384
rst += "\n \n *(Definitions include propagated dependencies, " \
321
385
"including from if's and menus.)*"
0 commit comments