Changes in tools/config.py [ba8de9c3:28f4adb] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tools/config.py
rba8de9c3 r28f4adb 3 3 # Copyright (c) 2006 Ondrej Palkovsky 4 4 # Copyright (c) 2009 Martin Decky 5 # Copyright (c) 2010 Jiri Svoboda6 5 # All rights reserved. 7 6 # … … 41 40 import xtui 42 41 43 RULES_FILE= sys.argv[1]42 INPUT = sys.argv[1] 44 43 MAKEFILE = 'Makefile.config' 45 44 MACROS = 'config.h' 46 PRE SETS_DIR= 'defaults'47 48 def read_ config(fname, config):45 PRECONF = 'defaults' 46 47 def read_defaults(fname, defaults): 49 48 "Read saved values from last configuration run" 50 49 … … 53 52 for line in inf: 54 53 res = re.match(r'^(?:#!# )?([^#]\w*)\s*=\s*(.*?)\s*$', line) 55 if res:56 config[res.group(1)] = res.group(2)54 if (res): 55 defaults[res.group(1)] = res.group(2) 57 56 58 57 inf.close() 59 58 60 def check_condition(text, config, rules):59 def check_condition(text, defaults, ask_names): 61 60 "Check that the condition specified on input line is True (only CNF and DNF is supported)" 62 61 63 62 ctype = 'cnf' 64 63 65 if ( ')|' in text) or ('|(' in text):64 if ((')|' in text) or ('|(' in text)): 66 65 ctype = 'dnf' 67 66 68 if ctype == 'cnf':67 if (ctype == 'cnf'): 69 68 conds = text.split('&') 70 69 else: … … 72 71 73 72 for cond in conds: 74 if cond.startswith('(') and cond.endswith(')'):73 if (cond.startswith('(')) and (cond.endswith(')')): 75 74 cond = cond[1:-1] 76 75 77 inside = check_inside(cond, config, ctype)76 inside = check_inside(cond, defaults, ctype) 78 77 79 78 if (ctype == 'cnf') and (not inside): 80 79 return False 81 80 82 if (ctype == 'dnf') and inside:81 if (ctype == 'dnf') and (inside): 83 82 return True 84 83 85 if ctype == 'cnf':84 if (ctype == 'cnf'): 86 85 return True 87 86 return False 88 87 89 def check_inside(text, config, ctype):88 def check_inside(text, defaults, ctype): 90 89 "Check for condition" 91 90 92 if ctype == 'cnf':91 if (ctype == 'cnf'): 93 92 conds = text.split('|') 94 93 else: … … 97 96 for cond in conds: 98 97 res = re.match(r'^(.*?)(!?=)(.*)$', cond) 99 if not res:98 if (not res): 100 99 raise RuntimeError("Invalid condition: %s" % cond) 101 100 … … 104 103 condval = res.group(3) 105 104 106 if not condname in config:105 if (not condname in defaults): 107 106 varval = '' 108 107 else: 109 varval = config[condname]108 varval = defaults[condname] 110 109 if (varval == '*'): 111 110 varval = 'y' 112 111 113 if ctype == 'cnf':112 if (ctype == 'cnf'): 114 113 if (oper == '=') and (condval == varval): 115 114 return True … … 124 123 return False 125 124 126 if ctype == 'cnf':125 if (ctype == 'cnf'): 127 126 return False 128 127 129 128 return True 130 129 131 def parse_ rules(fname, rules):132 "Parse rulesfile"130 def parse_config(fname, ask_names): 131 "Parse configuration file" 133 132 134 133 inf = open(fname, 'r') … … 139 138 for line in inf: 140 139 141 if line.startswith('!'):140 if (line.startswith('!')): 142 141 # Ask a question 143 142 res = re.search(r'!\s*(?:\[(.*?)\])?\s*([^\s]+)\s*\((.*)\)\s*$', line) 144 143 145 if not res:144 if (not res): 146 145 raise RuntimeError("Weird line: %s" % line) 147 146 … … 150 149 vartype = res.group(3) 151 150 152 rules.append((varname, vartype, name, choices, cond))151 ask_names.append((varname, vartype, name, choices, cond)) 153 152 name = '' 154 153 choices = [] 155 154 continue 156 155 157 if line.startswith('@'):156 if (line.startswith('@')): 158 157 # Add new line into the 'choices' array 159 158 res = re.match(r'@\s*(?:\[(.*?)\])?\s*"(.*?)"\s*(.*)$', line) … … 165 164 continue 166 165 167 if line.startswith('%'):166 if (line.startswith('%')): 168 167 # Name of the option 169 168 name = line[1:].strip() 170 169 continue 171 170 172 if line.startswith('#') or (line == '\n'):171 if ((line.startswith('#')) or (line == '\n')): 173 172 # Comment or empty line 174 173 continue … … 182 181 "Return '*' if yes, ' ' if no" 183 182 184 if default == 'y':183 if (default == 'y'): 185 184 return '*' 186 185 … … 200 199 cnt = 0 201 200 for key, val in choices: 202 if ( default) and (key == default):201 if ((default) and (key == default)): 203 202 position = cnt 204 203 … … 208 207 (button, value) = xtui.choice_window(screen, name, 'Choose value', options, position) 209 208 210 if button == 'cancel':209 if (button == 'cancel'): 211 210 return None 212 211 213 212 return choices[value][0] 214 213 215 ## Infer and verify configuration values. 216 # 217 # Augment @a config with values that can be inferred, purge invalid ones 218 # and verify that all variables have a value (previously specified or inferred). 219 # 220 # @param config Configuration to work on 221 # @param rules Rules 222 # 223 # @return True if configuration is complete and valid, False 224 # otherwise. 225 # 226 def infer_verify_choices(config, rules): 227 "Infer and verify configuration values." 228 229 for rule in rules: 230 varname, vartype, name, choices, cond = rule 231 232 if cond and (not check_condition(cond, config, rules)): 233 continue 234 235 if not varname in config: 236 value = None 237 else: 238 value = config[varname] 239 240 if not rule_value_is_valid(rule, value): 241 value = None 242 243 default = rule_get_default(rule) 244 if default != None: 245 config[varname] = default 246 247 if not varname in config: 214 def check_choices(defaults, ask_names): 215 "Check whether all accessible variables have a default" 216 217 for varname, vartype, name, choices, cond in ask_names: 218 if ((cond) and (not check_condition(cond, defaults, ask_names))): 219 continue 220 221 if (not varname in defaults): 248 222 return False 249 223 250 224 return True 251 225 252 ## Get default value from a rule. 253 def rule_get_default(rule): 254 varname, vartype, name, choices, cond = rule 255 256 default = None 257 258 if vartype == 'choice': 259 # If there is just one option, use it 260 if len(choices) == 1: 261 default = choices[0][0] 262 elif vartype == 'y': 263 default = '*' 264 elif vartype == 'n': 265 default = 'n' 266 elif vartype == 'y/n': 267 default = 'y' 268 elif vartype == 'n/y': 269 default = 'n' 270 else: 271 raise RuntimeError("Unknown variable type: %s" % vartype) 272 273 return default 274 275 ## Get option from a rule. 276 # 277 # @param rule Rule for a variable 278 # @param value Current value of the variable 279 # 280 # @return Option (string) to ask or None which means not to ask. 281 # 282 def rule_get_option(rule, value): 283 varname, vartype, name, choices, cond = rule 284 285 option = None 286 287 if vartype == 'choice': 288 # If there is just one option, don't ask 289 if len(choices) != 1: 290 if (value == None): 291 option = "? %s --> " % name 292 else: 293 option = " %s [%s] --> " % (name, value) 294 elif vartype == 'y': 295 pass 296 elif vartype == 'n': 297 pass 298 elif vartype == 'y/n': 299 option = " <%s> %s " % (yes_no(value), name) 300 elif vartype == 'n/y': 301 option =" <%s> %s " % (yes_no(value), name) 302 else: 303 raise RuntimeError("Unknown variable type: %s" % vartype) 304 305 return option 306 307 ## Check if variable value is valid. 308 # 309 # @param rule Rule for the variable 310 # @param value Value of the variable 311 # 312 # @return True if valid, False if not valid. 313 # 314 def rule_value_is_valid(rule, value): 315 varname, vartype, name, choices, cond = rule 316 317 if value == None: 318 return True 319 320 if vartype == 'choice': 321 if not value in [choice[0] for choice in choices]: 322 return False 323 elif vartype == 'y': 324 if value != 'y': 325 return False 326 elif vartype == 'n': 327 if value != 'n': 328 return False 329 elif vartype == 'y/n': 330 if not value in ['y', 'n']: 331 return False 332 elif vartype == 'n/y': 333 if not value in ['y', 'n']: 334 return False 335 else: 336 raise RuntimeError("Unknown variable type: %s" % vartype) 337 338 return True 339 340 def create_output(mkname, mcname, config, rules): 226 def create_output(mkname, mcname, defaults, ask_names): 341 227 "Create output configuration" 342 228 … … 352 238 sys.stderr.write("failed\n") 353 239 354 if len(version) == 3:240 if (len(version) == 3): 355 241 revision = version[1] 356 if version[0] != 1:242 if (version[0] != 1): 357 243 revision += 'M' 358 244 revision += ' (%s)' % version[2] … … 373 259 defs = 'CONFIG_DEFS =' 374 260 375 for varname, vartype, name, choices, cond in rules:376 if cond and (not check_condition(cond, config, rules)):377 continue 378 379 if not varname in config:380 value= ''261 for varname, vartype, name, choices, cond in ask_names: 262 if ((cond) and (not check_condition(cond, defaults, ask_names))): 263 continue 264 265 if (not varname in defaults): 266 default = '' 381 267 else: 382 value = config[varname]383 if ( value== '*'):384 value= 'y'385 386 outmk.write('# %s\n%s = %s\n\n' % (name, varname, value))387 388 if vartype in ["y", "n", "y/n", "n/y"]:389 if value == "y":268 default = defaults[varname] 269 if (default == '*'): 270 default = 'y' 271 272 outmk.write('# %s\n%s = %s\n\n' % (name, varname, default)) 273 274 if ((vartype == "y") or (vartype == "n") or (vartype == "y/n") or (vartype == "n/y")): 275 if (default == "y"): 390 276 outmc.write('/* %s */\n#define %s\n\n' % (name, varname)) 391 277 defs += ' -D%s' % varname 392 278 else: 393 outmc.write('/* %s */\n#define %s %s\n#define %s_%s\n\n' % (name, varname, value, varname, value))394 defs += ' -D%s=%s -D%s_%s' % (varname, value, varname, value)395 396 if revision is not None:279 outmc.write('/* %s */\n#define %s %s\n#define %s_%s\n\n' % (name, varname, default, varname, default)) 280 defs += ' -D%s=%s -D%s_%s' % (varname, default, varname, default) 281 282 if (revision is not None): 397 283 outmk.write('REVISION = %s\n' % revision) 398 284 outmc.write('#define REVISION %s\n' % revision) … … 413 299 return list 414 300 415 ## Choose a profile and load configuration presets. 416 # 417 def load_presets(root, fname, screen, config): 301 def read_preconfigured(root, fname, screen, defaults): 418 302 options = [] 419 303 opt2path = {} … … 425 309 canon = os.path.join(path, fname) 426 310 427 if os.path.isdir(path) and os.path.exists(canon) and os.path.isfile(canon):311 if ((os.path.isdir(path)) and (os.path.exists(canon)) and (os.path.isfile(canon))): 428 312 subprofile = False 429 313 … … 433 317 subcanon = os.path.join(subpath, fname) 434 318 435 if os.path.isdir(subpath) and os.path.exists(subcanon) and os.path.isfile(subcanon):319 if ((os.path.isdir(subpath)) and (os.path.exists(subcanon)) and (os.path.isfile(subcanon))): 436 320 subprofile = True 437 321 options.append("%s (%s)" % (name, subname)) … … 439 323 cnt += 1 440 324 441 if not subprofile:325 if (not subprofile): 442 326 options.append(name) 443 327 opt2path[cnt] = (canon, None) … … 446 330 (button, value) = xtui.choice_window(screen, 'Load preconfigured defaults', 'Choose configuration profile', options, None) 447 331 448 if button == 'cancel':332 if (button == 'cancel'): 449 333 return None 450 334 451 read_ config(opt2path[value][0], config)452 if opt2path[value][1] != None:453 read_ config(opt2path[value][1], config)335 read_defaults(opt2path[value][0], defaults) 336 if (opt2path[value][1] != None): 337 read_defaults(opt2path[value][1], defaults) 454 338 455 339 def main(): 456 config= {}457 rules = []458 459 # Parse rulesfile460 parse_ rules(RULES_FILE, rules)461 462 # Read configurationfrom previous run340 defaults = {} 341 ask_names = [] 342 343 # Parse configuration file 344 parse_config(INPUT, ask_names) 345 346 # Read defaults from previous run 463 347 if os.path.exists(MAKEFILE): 464 read_ config(MAKEFILE, config)465 466 # Default mode: only check values and regenerate configuration files467 if ( len(sys.argv) >= 3) and (sys.argv[2] == 'default'):468 if ( infer_verify_choices(config, rules)):469 create_output(MAKEFILE, MACROS, config, rules)348 read_defaults(MAKEFILE, defaults) 349 350 # Default mode: only check defaults and regenerate configuration 351 if ((len(sys.argv) >= 3) and (sys.argv[2] == 'default')): 352 if (check_choices(defaults, ask_names)): 353 create_output(MAKEFILE, MACROS, defaults, ask_names) 470 354 return 0 471 355 472 # Check mode: only check configuration473 if ( len(sys.argv) >= 3) and (sys.argv[2] == 'check'):474 if infer_verify_choices(config, rules):356 # Check mode: only check defaults 357 if ((len(sys.argv) >= 3) and (sys.argv[2] == 'check')): 358 if (check_choices(defaults, ask_names)): 475 359 return 0 476 360 return 1 … … 482 366 while True: 483 367 484 # Cancel out all values which have to be deduced485 for varname, vartype, name, choices, cond in rules:486 if ( vartype == 'y') and (varname in config) and (config[varname] == '*'):487 config[varname] = None368 # Cancel out all defaults which have to be deduced 369 for varname, vartype, name, choices, cond in ask_names: 370 if ((vartype == 'y') and (varname in defaults) and (defaults[varname] == '*')): 371 defaults[varname] = None 488 372 489 373 options = [] … … 493 377 options.append(" --- Load preconfigured defaults ... ") 494 378 495 for rule in rules: 496 varname, vartype, name, choices, cond = rule 497 498 if cond and (not check_condition(cond, config, rules)): 379 for varname, vartype, name, choices, cond in ask_names: 380 381 if ((cond) and (not check_condition(cond, defaults, ask_names))): 499 382 continue 500 383 501 if varname == selname:384 if (varname == selname): 502 385 position = cnt 503 386 504 if not varname in config:505 value= None387 if (not varname in defaults): 388 default = None 506 389 else: 507 value = config[varname] 508 509 if not rule_value_is_valid(rule, value): 510 value = None 511 512 default = rule_get_default(rule) 513 if default != None: 514 value = default 515 config[varname] = default 516 517 option = rule_get_option(rule, value) 518 if option != None: 519 options.append(option) 390 default = defaults[varname] 391 392 if (vartype == 'choice'): 393 # Check if the default is an acceptable value 394 if ((default) and (not default in [choice[0] for choice in choices])): 395 default = None 396 defaults.pop(varname) 397 398 # If there is just one option, use it 399 if (len(choices) == 1): 400 defaults[varname] = choices[0][0] 401 continue 402 403 if (default == None): 404 options.append("? %s --> " % name) 405 else: 406 options.append(" %s [%s] --> " % (name, default)) 407 elif (vartype == 'y'): 408 defaults[varname] = '*' 409 continue 410 elif (vartype == 'n'): 411 defaults[varname] = 'n' 412 continue 413 elif (vartype == 'y/n'): 414 if (default == None): 415 default = 'y' 416 defaults[varname] = default 417 options.append(" <%s> %s " % (yes_no(default), name)) 418 elif (vartype == 'n/y'): 419 if (default == None): 420 default = 'n' 421 defaults[varname] = default 422 options.append(" <%s> %s " % (yes_no(default), name)) 423 else: 424 raise RuntimeError("Unknown variable type: %s" % vartype) 520 425 521 426 opt2row[cnt] = (varname, vartype, name, choices) … … 528 433 (button, value) = xtui.choice_window(screen, 'HelenOS configuration', 'Choose configuration option', options, position) 529 434 530 if button == 'cancel':435 if (button == 'cancel'): 531 436 return 'Configuration canceled' 532 437 533 if button == 'done':534 if ( infer_verify_choices(config, rules)):438 if (button == 'done'): 439 if (check_choices(defaults, ask_names)): 535 440 break 536 441 else: … … 538 443 continue 539 444 540 if value == 0:541 load_presets(PRESETS_DIR, MAKEFILE, screen, config)445 if (value == 0): 446 read_preconfigured(PRECONF, MAKEFILE, screen, defaults) 542 447 position = 1 543 448 continue 544 449 545 450 position = None 546 if not value in opt2row:451 if (not value in opt2row): 547 452 raise RuntimeError("Error selecting value: %s" % value) 548 453 549 454 (selname, seltype, name, choices) = opt2row[value] 550 455 551 if not selname in config:552 value= None456 if (not selname in defaults): 457 default = None 553 458 else: 554 value = config[selname]555 556 if seltype == 'choice':557 config[selname] = subchoice(screen, name, choices, value)558 elif ( seltype == 'y/n') or (seltype == 'n/y'):559 if config[selname] == 'y':560 config[selname] = 'n'459 default = defaults[selname] 460 461 if (seltype == 'choice'): 462 defaults[selname] = subchoice(screen, name, choices, default) 463 elif ((seltype == 'y/n') or (seltype == 'n/y')): 464 if (defaults[selname] == 'y'): 465 defaults[selname] = 'n' 561 466 else: 562 config[selname] = 'y'467 defaults[selname] = 'y' 563 468 finally: 564 469 xtui.screen_done(screen) 565 470 566 create_output(MAKEFILE, MACROS, config, rules)471 create_output(MAKEFILE, MACROS, defaults, ask_names) 567 472 return 0 568 473
Note:
See TracChangeset
for help on using the changeset viewer.