95
95
environment variable is referenced inside the Kconfig files.
96
96
97
97
98
- Gotcha
99
- ******
100
-
101
- It's important to set $SRCARCH even if you don't care about values and only
102
- want to extract information from Kconfig files, because the top-level Kconfig
103
- file does this (as of writing):
104
-
105
- source "arch/$SRCARCH/Kconfig"
106
-
107
- If $SRCARCH is not set, this expands to "arch//Kconfig", and arch/Kconfig
108
- happens to be an existing file, giving something that appears to work but is
109
- actually a truncated configuration. The available symbols will differ depending
110
- on the arch as well.
111
-
112
-
113
98
Intro to symbol values
114
99
======================
115
100
@@ -745,7 +730,7 @@ def mainmenu_text(self):
745
730
"""
746
731
See the class documentation.
747
732
"""
748
- return os . path . expandvars (self .top_node .prompt [0 ])
733
+ return _expand (self .top_node .prompt [0 ])
749
734
750
735
@property
751
736
def defconfig_filename (self ):
@@ -758,7 +743,7 @@ def defconfig_filename(self):
758
743
for filename , cond in self .defconfig_list .defaults :
759
744
if expr_value (cond ):
760
745
try :
761
- with self ._open (os . path . expandvars (filename .str_value )) as f :
746
+ with self ._open (_expand (filename .str_value )) as f :
762
747
return f .name
763
748
except IOError :
764
749
continue
@@ -1943,20 +1928,20 @@ def _parse_block(self, end_token, parent, prev):
1943
1928
prev .next = prev = node
1944
1929
1945
1930
elif t0 == _T_SOURCE :
1946
- self ._enter_file (os . path . expandvars (self ._expect_str_and_eol ()))
1931
+ self ._enter_file (_expand (self ._expect_str_and_eol ()))
1947
1932
prev = self ._parse_block (None , parent , prev )
1948
1933
self ._leave_file ()
1949
1934
1950
1935
elif t0 == _T_RSOURCE :
1951
1936
self ._enter_file (os .path .join (
1952
1937
os .path .dirname (self ._filename ),
1953
- os . path . expandvars (self ._expect_str_and_eol ())
1938
+ _expand (self ._expect_str_and_eol ())
1954
1939
))
1955
1940
prev = self ._parse_block (None , parent , prev )
1956
1941
self ._leave_file ()
1957
1942
1958
1943
elif t0 in (_T_GSOURCE , _T_GRSOURCE ):
1959
- pattern = os . path . expandvars (self ._expect_str_and_eol ())
1944
+ pattern = _expand (self ._expect_str_and_eol ())
1960
1945
if t0 == _T_GRSOURCE :
1961
1946
# Relative gsource
1962
1947
pattern = os .path .join (os .path .dirname (self ._filename ),
@@ -2132,21 +2117,9 @@ def _parse_properties(self, node):
2132
2117
continue
2133
2118
2134
2119
if t0 in _TYPE_TOKENS :
2135
- new_type = _TOKEN_TO_TYPE [t0 ]
2136
-
2137
- if node .item .orig_type not in (UNKNOWN , new_type ):
2138
- self ._warn ("{} defined with multiple types, {} will be used"
2139
- .format (_name_and_loc (node .item ),
2140
- TYPE_TO_STR [new_type ]))
2141
-
2142
- node .item .orig_type = new_type
2143
-
2120
+ self ._set_type (node , _TOKEN_TO_TYPE [t0 ])
2144
2121
if self ._peek_token () is not None :
2145
- if node .prompt :
2146
- self ._warn ("{} defined with multiple prompts in single location"
2147
- .format (_name_and_loc (node .item )))
2148
-
2149
- node .prompt = (self ._expect_str (), self ._parse_cond ())
2122
+ self ._parse_prompt (node )
2150
2123
2151
2124
elif t0 == _T_DEPENDS :
2152
2125
if not self ._check_token (_T_ON ):
@@ -2155,59 +2128,7 @@ def _parse_properties(self, node):
2155
2128
node .dep = self ._make_and (node .dep , self ._parse_expr (True ))
2156
2129
2157
2130
elif t0 == _T_HELP :
2158
- # Find first non-blank (not all-space) line and get its
2159
- # indentation
2160
-
2161
- if node .help is not None :
2162
- self ._warn ("{} defined with more than one help text -- "
2163
- "only the last one will be used"
2164
- .format (_name_and_loc (node .item )))
2165
-
2166
- # Small optimization. This code is pretty hot.
2167
- readline = self ._file .readline
2168
-
2169
- while 1 :
2170
- line = readline ()
2171
- self ._linenr += 1
2172
- if not line or not line .isspace ():
2173
- break
2174
-
2175
- if not line :
2176
- self ._warn ("{} has 'help' but empty help text"
2177
- .format (_name_and_loc (node .item )))
2178
-
2179
- node .help = ""
2180
- break
2181
-
2182
- indent = _indentation (line )
2183
- if indent == 0 :
2184
- # If the first non-empty lines has zero indent, there is no
2185
- # help text
2186
- self ._warn ("{} has 'help' but empty help text"
2187
- .format (_name_and_loc (node .item )))
2188
-
2189
- node .help = ""
2190
- self ._saved_line = line # "Unget" the line
2191
- break
2192
-
2193
- help_lines = [_dedent_rstrip (line , indent )]
2194
- # Small optimization
2195
- add_help_line = help_lines .append
2196
-
2197
- # The help text goes on till the first non-empty line with less
2198
- # indent
2199
-
2200
- while 1 :
2201
- line = readline ()
2202
- self ._linenr += 1
2203
- if not (line and (line .isspace () or \
2204
- _indentation (line ) >= indent )):
2205
- break
2206
-
2207
- add_help_line (_dedent_rstrip (line , indent ))
2208
-
2209
- node .help = "\n " .join (help_lines ).rstrip () + "\n "
2210
- self ._saved_line = line # "Unget" the line
2131
+ self ._parse_help (node )
2211
2132
2212
2133
elif t0 == _T_SELECT :
2213
2134
if not isinstance (node .item , Symbol ):
@@ -2228,27 +2149,12 @@ def _parse_properties(self, node):
2228
2149
self ._parse_cond ()))
2229
2150
2230
2151
elif t0 in (_T_DEF_BOOL , _T_DEF_TRISTATE ):
2231
- new_type = _TOKEN_TO_TYPE [t0 ]
2232
-
2233
- if node .item .orig_type not in (UNKNOWN , new_type ):
2234
- self ._warn ("{} defined with multiple types, {} will be used"
2235
- .format (_name_and_loc (node .item ),
2236
- TYPE_TO_STR [new_type ]))
2237
-
2238
- node .item .orig_type = new_type
2239
-
2152
+ self ._set_type (node , _TOKEN_TO_TYPE [t0 ])
2240
2153
node .defaults .append ((self ._parse_expr (False ),
2241
2154
self ._parse_cond ()))
2242
2155
2243
2156
elif t0 == _T_PROMPT :
2244
- # 'prompt' properties override each other within a single
2245
- # definition of a symbol, but additional prompts can be added
2246
- # by defining the symbol multiple times
2247
- if node .prompt :
2248
- self ._warn ("{} defined with multiple prompts in single location"
2249
- .format (_name_and_loc (node .item )))
2250
-
2251
- node .prompt = (self ._expect_str (), self ._parse_cond ())
2157
+ self ._parse_prompt (node )
2252
2158
2253
2159
elif t0 == _T_RANGE :
2254
2160
node .ranges .append ((self ._expect_sym (),
@@ -2263,15 +2169,15 @@ def _parse_properties(self, node):
2263
2169
env_var = self ._expect_str_and_eol ()
2264
2170
node .item .env_var = env_var
2265
2171
2266
- if env_var not in os .environ :
2172
+ if env_var in os .environ :
2173
+ node .defaults .append (
2174
+ (self ._lookup_const_sym (os .environ [env_var ]),
2175
+ self .y ))
2176
+ else :
2267
2177
self ._warn ("{1} has 'option env=\" {0}\" ', "
2268
2178
"but the environment variable {0} is not "
2269
2179
"set" .format (node .item .name , env_var ),
2270
2180
self ._filename , self ._linenr )
2271
- else :
2272
- node .defaults .append (
2273
- (self ._lookup_const_sym (os .environ [env_var ]),
2274
- self .y ))
2275
2181
2276
2182
elif self ._check_token (_T_DEFCONFIG_LIST ):
2277
2183
if not self .defconfig_list :
@@ -2329,6 +2235,92 @@ def _parse_properties(self, node):
2329
2235
self ._tokens_i = - 1
2330
2236
return
2331
2237
2238
+ def _set_type (self , node , new_type ):
2239
+ if node .item .orig_type not in (UNKNOWN , new_type ):
2240
+ self ._warn ("{} defined with multiple types, {} will be used"
2241
+ .format (_name_and_loc (node .item ),
2242
+ TYPE_TO_STR [new_type ]))
2243
+
2244
+ node .item .orig_type = new_type
2245
+
2246
+ def _parse_prompt (self , node ):
2247
+ # 'prompt' properties override each other within a single definition of
2248
+ # a symbol, but additional prompts can be added by defining the symbol
2249
+ # multiple times
2250
+ if node .prompt :
2251
+ self ._warn ("{} defined with multiple prompts in single location"
2252
+ .format (_name_and_loc (node .item )))
2253
+
2254
+ prompt = self ._expect_str ()
2255
+ if prompt != prompt .strip ():
2256
+ self ._warn ("{} has leading or trailing whitespace in its prompt"
2257
+ .format (_name_and_loc (node .item )))
2258
+
2259
+ # This avoid issues for e.g. reStructuredText documentation, where
2260
+ # '*prompt *' is invalid
2261
+ prompt = prompt .strip ()
2262
+
2263
+ node .prompt = (prompt , self ._parse_cond ())
2264
+
2265
+ def _parse_help (self , node ):
2266
+ # Find first non-blank (not all-space) line and get its indentation
2267
+
2268
+ if node .help is not None :
2269
+ self ._warn ("{} defined with more than one help text -- only the "
2270
+ "last one will be used"
2271
+ .format (_name_and_loc (node .item )))
2272
+
2273
+ # Small optimization. This code is pretty hot.
2274
+ readline = self ._file .readline
2275
+
2276
+ while 1 :
2277
+ line = readline ()
2278
+ self ._linenr += 1
2279
+ if not line or not line .isspace ():
2280
+ break
2281
+
2282
+ if not line :
2283
+ self ._warn ("{} has 'help' but empty help text"
2284
+ .format (_name_and_loc (node .item )))
2285
+
2286
+ node .help = ""
2287
+ return
2288
+
2289
+ indent = _indentation (line )
2290
+ if indent == 0 :
2291
+ # If the first non-empty lines has zero indent, there is no help
2292
+ # text
2293
+ self ._warn ("{} has 'help' but empty help text"
2294
+ .format (_name_and_loc (node .item )))
2295
+
2296
+ node .help = ""
2297
+ self ._saved_line = line # "Unget" the line
2298
+ return
2299
+
2300
+ # The help text goes on till the first non-empty line with less indent
2301
+ # than the first line
2302
+
2303
+ help_lines = []
2304
+ # Small optimization
2305
+ add_help_line = help_lines .append
2306
+
2307
+ while line and (line .isspace () or _indentation (line ) >= indent ):
2308
+ # De-indent 'line' by 'indent' spaces and rstrip() it to remove any
2309
+ # newlines (which gets rid of other trailing whitespace too, but
2310
+ # that's fine).
2311
+ #
2312
+ # This prepares help text lines in a speedy way: The [indent:]
2313
+ # might already remove trailing newlines for lines shorter than
2314
+ # indent (e.g. empty lines). The rstrip() makes it consistent,
2315
+ # meaning we can join the lines with "\n" later.
2316
+ add_help_line (line .expandtabs ()[indent :].rstrip ())
2317
+
2318
+ line = readline ()
2319
+ self ._linenr += 1
2320
+
2321
+ node .help = "\n " .join (help_lines ).rstrip () + "\n "
2322
+ self ._saved_line = line # "Unget" the line
2323
+
2332
2324
def _parse_expr (self , transform_m ):
2333
2325
# Parses an expression from the tokens in Kconfig._tokens using a
2334
2326
# simple top-down approach. See the module docstring for the expression
@@ -4532,6 +4524,15 @@ def _make_depend_on(sym, expr):
4532
4524
_internal_error ("Internal error while fetching symbols from an "
4533
4525
"expression with token stream {}." .format (expr ))
4534
4526
4527
+ def _expand (s ):
4528
+ # The predefined UNAME_RELEASE symbol is expanded in one of the 'default's
4529
+ # of the DEFCONFIG_LIST symbol in the Linux kernel. This function maintains
4530
+ # compatibility with it even though environment variables in strings are
4531
+ # now expanded directly.
4532
+
4533
+ # platform.uname() has an internal cache, so this is speedy enough
4534
+ return os .path .expandvars (s .replace ("$UNAME_RELEASE" , platform .uname ()[2 ]))
4535
+
4535
4536
def _parenthesize (expr , type_ ):
4536
4537
# expr_str() helper. Adds parentheses around expressions of type 'type_'.
4537
4538
@@ -4546,18 +4547,6 @@ def _indentation(line):
4546
4547
line = line .expandtabs ()
4547
4548
return len (line ) - len (line .lstrip ())
4548
4549
4549
- def _dedent_rstrip (line , indent ):
4550
- # De-indents 'line' by 'indent' spaces and rstrip()s it to remove any
4551
- # newlines (which gets rid of other trailing whitespace too, but that's
4552
- # fine).
4553
- #
4554
- # Used to prepare help text lines in a speedy way: The [indent:] might
4555
- # already remove trailing newlines for lines shorter than indent (e.g.
4556
- # empty lines). The rstrip() makes it consistent, meaning we can join the
4557
- # lines with "\n" later.
4558
-
4559
- return line .expandtabs ()[indent :].rstrip ()
4560
-
4561
4550
def _is_base_n (s , n ):
4562
4551
try :
4563
4552
int (s , n )
0 commit comments