9595environment variable is referenced inside the Kconfig files.
9696
9797
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-
11398Intro to symbol values
11499======================
115100
@@ -745,7 +730,7 @@ def mainmenu_text(self):
745730 """
746731 See the class documentation.
747732 """
748- return os . path . expandvars (self .top_node .prompt [0 ])
733+ return _expand (self .top_node .prompt [0 ])
749734
750735 @property
751736 def defconfig_filename (self ):
@@ -758,7 +743,7 @@ def defconfig_filename(self):
758743 for filename , cond in self .defconfig_list .defaults :
759744 if expr_value (cond ):
760745 try :
761- with self ._open (os . path . expandvars (filename .str_value )) as f :
746+ with self ._open (_expand (filename .str_value )) as f :
762747 return f .name
763748 except IOError :
764749 continue
@@ -1943,20 +1928,20 @@ def _parse_block(self, end_token, parent, prev):
19431928 prev .next = prev = node
19441929
19451930 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 ()))
19471932 prev = self ._parse_block (None , parent , prev )
19481933 self ._leave_file ()
19491934
19501935 elif t0 == _T_RSOURCE :
19511936 self ._enter_file (os .path .join (
19521937 os .path .dirname (self ._filename ),
1953- os . path . expandvars (self ._expect_str_and_eol ())
1938+ _expand (self ._expect_str_and_eol ())
19541939 ))
19551940 prev = self ._parse_block (None , parent , prev )
19561941 self ._leave_file ()
19571942
19581943 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 ())
19601945 if t0 == _T_GRSOURCE :
19611946 # Relative gsource
19621947 pattern = os .path .join (os .path .dirname (self ._filename ),
@@ -2132,21 +2117,9 @@ def _parse_properties(self, node):
21322117 continue
21332118
21342119 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 ])
21442121 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 )
21502123
21512124 elif t0 == _T_DEPENDS :
21522125 if not self ._check_token (_T_ON ):
@@ -2155,59 +2128,7 @@ def _parse_properties(self, node):
21552128 node .dep = self ._make_and (node .dep , self ._parse_expr (True ))
21562129
21572130 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 )
22112132
22122133 elif t0 == _T_SELECT :
22132134 if not isinstance (node .item , Symbol ):
@@ -2228,27 +2149,12 @@ def _parse_properties(self, node):
22282149 self ._parse_cond ()))
22292150
22302151 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 ])
22402153 node .defaults .append ((self ._parse_expr (False ),
22412154 self ._parse_cond ()))
22422155
22432156 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 )
22522158
22532159 elif t0 == _T_RANGE :
22542160 node .ranges .append ((self ._expect_sym (),
@@ -2263,15 +2169,15 @@ def _parse_properties(self, node):
22632169 env_var = self ._expect_str_and_eol ()
22642170 node .item .env_var = env_var
22652171
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 :
22672177 self ._warn ("{1} has 'option env=\" {0}\" ', "
22682178 "but the environment variable {0} is not "
22692179 "set" .format (node .item .name , env_var ),
22702180 self ._filename , self ._linenr )
2271- else :
2272- node .defaults .append (
2273- (self ._lookup_const_sym (os .environ [env_var ]),
2274- self .y ))
22752181
22762182 elif self ._check_token (_T_DEFCONFIG_LIST ):
22772183 if not self .defconfig_list :
@@ -2329,6 +2235,92 @@ def _parse_properties(self, node):
23292235 self ._tokens_i = - 1
23302236 return
23312237
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+
23322324 def _parse_expr (self , transform_m ):
23332325 # Parses an expression from the tokens in Kconfig._tokens using a
23342326 # simple top-down approach. See the module docstring for the expression
@@ -4532,6 +4524,15 @@ def _make_depend_on(sym, expr):
45324524 _internal_error ("Internal error while fetching symbols from an "
45334525 "expression with token stream {}." .format (expr ))
45344526
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+
45354536def _parenthesize (expr , type_ ):
45364537 # expr_str() helper. Adds parentheses around expressions of type 'type_'.
45374538
@@ -4546,18 +4547,6 @@ def _indentation(line):
45464547 line = line .expandtabs ()
45474548 return len (line ) - len (line .lstrip ())
45484549
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-
45614550def _is_base_n (s , n ):
45624551 try :
45634552 int (s , n )
0 commit comments