Changes in tools/config.py [aca97582:a35b458] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tools/config.py
raca97582 ra35b458 42 42 import random 43 43 44 ARGPOS_RULES = 1 45 ARGPOS_CHOICE = 2 46 ARGPOS_PRESET = 3 47 48 RULES_FILE = sys.argv[ARGPOS_RULES] 44 RULES_FILE = sys.argv[1] 49 45 MAKEFILE = 'Makefile.config' 50 46 MACROS = 'config.h' 51 47 PRESETS_DIR = 'defaults' 52 53 class BinaryOp:54 def __init__(self, operator, left, right):55 assert operator in ('&', '|', '=', '!=')56 57 self._operator = operator58 self._left = left59 self._right = right60 61 def evaluate(self, config):62 if self._operator == '&':63 return self._left.evaluate(config) and \64 self._right.evaluate(config)65 if self._operator == '|':66 return self._left.evaluate(config) or \67 self._right.evaluate(config)68 69 # '=' or '!='70 if not self._left in config:71 config_val = ''72 else:73 config_val = config[self._left]74 if config_val == '*':75 config_val = 'y'76 77 if self._operator == '=':78 return self._right == config_val79 return self._right != config_val80 81 # Expression parser82 class CondParser:83 TOKEN_EOE = 084 TOKEN_SPECIAL = 185 TOKEN_STRING = 286 87 def __init__(self, text):88 self._text = text89 90 def parse(self):91 self._position = -192 self._next_char()93 self._next_token()94 95 res = self._parse_expr()96 if self._token_type != self.TOKEN_EOE:97 self._error("Expected end of expression")98 return res99 100 def _next_char(self):101 self._position += 1102 if self._position >= len(self._text):103 self._char = None104 else:105 self._char = self._text[self._position]106 self._is_special_char = self._char in \107 ('&', '|', '=', '!', '(', ')')108 109 def _error(self, msg):110 raise RuntimeError("Error parsing expression: %s:\n%s\n%s^" %111 (msg, self._text, " " * self._token_position))112 113 def _next_token(self):114 self._token_position = self._position115 116 # End of expression117 if self._char == None:118 self._token = None119 self._token_type = self.TOKEN_EOE120 return121 122 # '&', '|', '=', '!=', '(', ')'123 if self._is_special_char:124 self._token = self._char125 self._next_char()126 if self._token == '!':127 if self._char != '=':128 self._error("Expected '='")129 self._token += self._char130 self._next_char()131 self._token_type = self.TOKEN_SPECIAL132 return133 134 # <var> or <val>135 self._token = ''136 self._token_type = self.TOKEN_STRING137 while True:138 self._token += self._char139 self._next_char()140 if self._is_special_char or self._char == None:141 break142 143 def _parse_expr(self):144 """ <expr> ::= <or_expr> ('&' <or_expr>)* """145 146 left = self._parse_or_expr()147 while self._token == '&':148 self._next_token()149 left = BinaryOp('&', left, self._parse_or_expr())150 return left151 152 def _parse_or_expr(self):153 """ <or_expr> ::= <factor> ('|' <factor>)* """154 155 left = self._parse_factor()156 while self._token == '|':157 self._next_token()158 left = BinaryOp('|', left, self._parse_factor())159 return left160 161 def _parse_factor(self):162 """ <factor> ::= <var> <cond> | '(' <expr> ')' """163 164 if self._token == '(':165 self._next_token()166 res = self._parse_expr()167 if self._token != ')':168 self._error("Expected ')'")169 self._next_token()170 return res171 172 if self._token_type == self.TOKEN_STRING:173 var = self._token174 self._next_token()175 return self._parse_cond(var)176 177 self._error("Expected '(' or <var>")178 179 def _parse_cond(self, var):180 """ <cond> ::= '=' <val> | '!=' <val> """181 182 if self._token not in ('=', '!='):183 self._error("Expected '=' or '!='")184 185 oper = self._token186 self._next_token()187 188 if self._token_type != self.TOKEN_STRING:189 self._error("Expected <val>")190 191 val = self._token192 self._next_token()193 194 return BinaryOp(oper, var, val)195 48 196 49 def read_config(fname, config): … … 206 59 inf.close() 207 60 61 def check_condition(text, config, rules): 62 "Check that the condition specified on input line is True (only CNF and DNF is supported)" 63 64 ctype = 'cnf' 65 66 if (')|' in text) or ('|(' in text): 67 ctype = 'dnf' 68 69 if ctype == 'cnf': 70 conds = text.split('&') 71 else: 72 conds = text.split('|') 73 74 for cond in conds: 75 if cond.startswith('(') and cond.endswith(')'): 76 cond = cond[1:-1] 77 78 inside = check_inside(cond, config, ctype) 79 80 if (ctype == 'cnf') and (not inside): 81 return False 82 83 if (ctype == 'dnf') and inside: 84 return True 85 86 if ctype == 'cnf': 87 return True 88 89 return False 90 91 def check_inside(text, config, ctype): 92 "Check for condition" 93 94 if ctype == 'cnf': 95 conds = text.split('|') 96 else: 97 conds = text.split('&') 98 99 for cond in conds: 100 res = re.match(r'^(.*?)(!?=)(.*)$', cond) 101 if not res: 102 raise RuntimeError("Invalid condition: %s" % cond) 103 104 condname = res.group(1) 105 oper = res.group(2) 106 condval = res.group(3) 107 108 if not condname in config: 109 varval = '' 110 else: 111 varval = config[condname] 112 if (varval == '*'): 113 varval = 'y' 114 115 if ctype == 'cnf': 116 if (oper == '=') and (condval == varval): 117 return True 118 119 if (oper == '!=') and (condval != varval): 120 return True 121 else: 122 if (oper == '=') and (condval != varval): 123 return False 124 125 if (oper == '!=') and (condval == varval): 126 return False 127 128 if ctype == 'cnf': 129 return False 130 131 return True 132 208 133 def parse_rules(fname, rules): 209 134 "Parse rules file" … … 224 149 225 150 cond = res.group(1) 226 if cond:227 cond = CondParser(cond).parse()228 151 varname = res.group(2) 229 152 vartype = res.group(3) … … 309 232 varname, vartype, name, choices, cond = rule 310 233 311 if cond and not cond.evaluate(config):234 if cond and (not check_condition(cond, config, rules)): 312 235 continue 313 236 … … 356 279 357 280 # First check that this rule would make sense 358 if cond and not cond.evaluate(config): 359 return random_choices(config, rules, start_index + 1) 281 if cond: 282 if not check_condition(cond, config, rules): 283 return random_choices(config, rules, start_index + 1) 360 284 361 285 # Remember previous choices for backtracking … … 563 487 564 488 for varname, vartype, name, choices, cond in rules: 565 if cond and not cond.evaluate(config):489 if cond and (not check_condition(cond, config, rules)): 566 490 continue 567 491 … … 590 514 outmk.write('TIMESTAMP_UNIX = %d\n' % timestamp_unix) 591 515 outmc.write('#define TIMESTAMP_UNIX %d\n' % timestamp_unix) 592 defs += ' "-DTIMESTAMP_UNIX=%d" ' % timestamp_unix516 defs += ' "-DTIMESTAMP_UNIX=%d"\n' % timestamp_unix 593 517 594 518 outmk.write('TIMESTAMP = %s\n' % timestamp) 595 519 outmc.write('#define TIMESTAMP %s\n' % timestamp) 596 defs += ' "-DTIMESTAMP=%s" ' % timestamp597 598 outmk.write( '%s\n' %defs)520 defs += ' "-DTIMESTAMP=%s"\n' % timestamp 521 522 outmk.write(defs) 599 523 600 524 outmk.close() … … 680 604 parse_rules(RULES_FILE, rules) 681 605 682 if len(sys.argv) > ARGPOS_CHOICE:683 choice = sys.argv[ARGPOS_CHOICE]684 else:685 choice = None686 687 if len(sys.argv) > ARGPOS_PRESET:688 preset = sys.argv[ARGPOS_PRESET]689 else:690 preset = None691 692 606 # Input configuration file can be specified on command line 693 607 # otherwise configuration from previous run is used. 694 if preset is not None:695 profile = parse_profile_name( preset)608 if len(sys.argv) >= 4: 609 profile = parse_profile_name(sys.argv[3]) 696 610 read_presets(profile, config) 697 611 elif os.path.exists(MAKEFILE): … … 699 613 700 614 # Default mode: check values and regenerate configuration files 701 if choice == 'default':615 if (len(sys.argv) >= 3) and (sys.argv[2] == 'default'): 702 616 if (infer_verify_choices(config, rules)): 703 617 preprocess_config(config, rules) … … 707 621 # Hands-off mode: check values and regenerate configuration files, 708 622 # but no interactive fallback 709 if choice == 'hands-off':710 # We deliberately test thisbecause we do not want623 if (len(sys.argv) >= 3) and (sys.argv[2] == 'hands-off'): 624 # We deliberately test sys.argv >= 4 because we do not want 711 625 # to read implicitly any possible previous run configuration 712 if preset is None:626 if len(sys.argv) < 4: 713 627 sys.stderr.write("Configuration error: No presets specified\n") 714 628 return 2 … … 723 637 724 638 # Check mode: only check configuration 725 if choice == 'check':639 if (len(sys.argv) >= 3) and (sys.argv[2] == 'check'): 726 640 if infer_verify_choices(config, rules): 727 641 return 0 … … 729 643 730 644 # Random mode 731 if choice == 'random':645 if (len(sys.argv) == 3) and (sys.argv[2] == 'random'): 732 646 ok = random_choices(config, rules, 0) 733 647 if not ok: … … 762 676 varname, vartype, name, choices, cond = rule 763 677 764 if cond and not cond.evaluate(config):678 if cond and (not check_condition(cond, config, rules)): 765 679 continue 766 680
Note:
See TracChangeset
for help on using the changeset viewer.