def formatIfNotEmpty(fmt, value): """Return fmt % value (prefix: e.g. "%s"), unless value is empty string (in which case it returns empty string). Can handle following forms of 'value': - empty string - anything beginning with literal - anything with a literal in it - $(cv) where cv is conditional variable """ if fmt == '': return '' value = value.strip() if value == '' or value.isspace(): return '' if __certainlyNotEmpty(value): return fmt % value if value.startswith('$(') and value[-1] == ')': # FIXME: this is too limited, it should be done inside __doEvalExpr # callbacks instead. condname = value[2:-1] if condname in mk.options: if mk.options[condname].isNeverEmpty(): return fmt % value else: raise errors.Error("formatIfNotEmpty failed: option '%s' may be empty" % condname) if condname in mk.cond_vars: cond = mk.cond_vars[condname] var = mk.CondVar(makeUniqueCondVarName('%s_p' % cond.name)) mk.addCondVar(var) for v in cond.values: var.add(v.cond, formatIfNotEmpty(fmt, v.value)) return '$(%s)' % var.name if condname in mk.make_vars: form = formatIfNotEmpty(fmt, mk.make_vars[condname]) if form == '': return '' return fmt % value if condname in mk.vars: form = formatIfNotEmpty(fmt, mk.vars[condname]) if form == '': return '' return fmt % value raise errors.Error("formatIfNotEmpty failed: '%s' too complicated" % value)
def callbackVar(cnd, expr, use_options, target, add_dict): if expr in mk.cond_vars: cond = mk.cond_vars[expr] var = mk.CondVar(makeUniqueCondVarName('%s_%s' % (cond.name, desc))) mk.addCondVar(var, hints) for v in cond.values: cond2 = mk.mergeConditions(cnd, v.cond) if '$' in v.value: var.add(v.cond, substitute2(v.value, callback, desc, cond2, hints)) else: if len(v.value) == 0 or v.value.isspace(): var.add(v.cond, v.value) else: var.add(v.cond, callback(cond2, v.value)) return '$(%s)' % var.name if expr in mk.options and mk.options[expr].values != None: opt = mk.options[expr] var = mk.CondVar(makeUniqueCondVarName('%s_%s' % (opt.name, desc))) mk.addCondVar(var, hints) for v in opt.values: cond = mk.makeCondition("%s=='%s'" % (opt.name, v)) cond2 = mk.mergeConditions(cnd, cond) if '$' in v: var.add(cond, substitute2(v, callback, desc, cond2, hints)) else: if len(v) == 0 or v.isspace(): var.add(cond, v) else: var.add(cond, callback(cond2, v)) return '$(%s)' % var.name if expr in __substituteCallbacks: for func in __substituteCallbacks[expr]: rval = func(expr, callback, caller) if rval != None: return rval raise errors.Error("'%s' can't be used in this context, "%expr + "not a conditional variable or option with listed values")
def handleSet(e, target=None, add_dict=None): try: errors.pushCtx("in <set> at %s" % e.location()) name = basename = evalConstExpr(e, e.props['var'], target) if (name in mk.override_vars) and target == None: return # can't change value of variable overriden with -D=xxx doEval = not ('eval' in e.props and e.props['eval'] == '0') overwrite = not ('overwrite' in e.props and e.props['overwrite'] == '0') isCond = (len(e.children) > 0) isMakeVar = 'make_var' in e.props and e.props['make_var'] == '1' value = e.value if 'hints' in e.props: hints = e.props['hints'] else: hints = '' # Handle conditions: if isCond: if e.value: raise ReaderError(e, "cannot set unconditional value when <if> is used") noValueSet = 1 for e_if in e.children: try: errors.pushCtx(e_if) if e_if.name != 'if': raise ReaderError(e_if, "malformed <set> command") # Preprocess always true or always false conditions: condstr = evalConstExpr(e_if, e_if.props['cond'], target=target, add_dict=add_dict) condstr = translateSpecialCondition(e_if, condstr, target) typ = mk.evalCondition(condstr) # Condition never met when generating this target: if typ == '0': if config.debug: print "[dbg] removing never-met condition '%s' for variable '%s'" % (condstr, name) continue # Condition always met: elif typ == '1': if config.debug: print "[dbg] condition '%s' for variable '%s' is always met" % (condstr, name) noValueSet = 0 isCond = 0 value = e_if.value break elif typ != None: raise ReaderError(e, "malformed condition '%s': doesn't evaluate to boolean value" % condstr) cond = mk.makeCondition(condstr) noValueSet = 0 # Real conditions: checkConditionsSupport(e) if 'scope' in e.props: raise ReaderError(e, "conditional variable can't have nondefault scope ('%s')" % e.props['scope']) if target != None: if (not overwrite) and (name in target.vars): return name = '__%s_%s' % (target.id.replace('-','_').replace('.','_').replace('/','_'), basename) mk.setVar(e.props['var'], '$(%s)' % name, eval=0, target=target, add_dict=add_dict, hints=hints) if cond == None: raise ReaderError(e, "malformed condition: '%s': must be constant expression, equality test or conjunction of them" % condstr) if name in mk.cond_vars: if not overwrite: return var = mk.cond_vars[name] else: var = mk.CondVar(name, target) mk.addCondVar(var, hints) if doEval: value = mk.evalExpr(e_if.value,target=target,add_dict=add_dict) else: value = e_if.value var.add(cond, value) finally: errors.popCtx() if noValueSet: isCond = 0 value = '' if isCond: return # Non-conditional variables: if value == None: value = '' if 'append' in e.props and e.props['append'] == '1': doAppend = 1 else: doAppend = 0 if 'prepend' in e.props and e.props['prepend'] == '1': doPrepend = 1 else: doPrepend = 0 store_in = None if 'scope' in e.props: sc = evalConstExpr(e, e.props['scope'], target=target) if sc == 'local': pass elif sc == 'global': store_in = mk.vars else: if sc in mk.targets: store_in = mk.targets[sc].vars else: raise ReaderError(e, "invalid scope '%s': must be 'global', 'local' or target name" % sc) if isMakeVar: if doAppend or store_in != None or not doEval: raise ReaderError(e, "make variable (%s) can't be appended or stored in nondefault scope or not evaluated" % name) mk.setVar(name, value, eval=doEval, target=target, add_dict=add_dict, store_in=store_in, append=doAppend, prepend=doPrepend, overwrite=overwrite, makevar=isMakeVar, hints=hints) finally: errors.popCtx()
def eliminateDuplicateCondVars(): """Removes duplicate conditional variables, i.e. if there are two cond. variables with exactly same definition, remove them.""" duplicates = [] if config.verbose: sys.stdout.write('eliminating duplicate conditional variables') sys.stdout.flush() before = len(mk.cond_vars) keys = mk.cond_vars.keys() lng = len(keys) for c1 in range(0,lng): for c2 in range(c1+1,lng): cv1 = mk.cond_vars[keys[c1]] cv2 = mk.cond_vars[keys[c2]] if cv1.equals(cv2): duplicates.append((cv1, cv2)) break def commonPrefix(s1, s2): prefix = '' for i in range(0, min(len(s1), len(s2))): if s1[i] != s2[i]: break prefix += s1[i] return prefix.rstrip('_') def commonSuffix(s1, s2): suffix = '' for i in range(-1, -min(len(s1),len(s2))-1,-1): if s1[i] != s2[i]: break suffix = s1[i] + suffix return suffix.lstrip('_') for c1,c2 in duplicates: s1 = c1.name s2 = c2.name common = commonPrefix(s1, s2) if common == '' or common[0] in string.digits: common = commonSuffix(s1, s2) if common == '' or common[0] in string.digits: common = commonPrefix(s1.strip('_'), s2.strip('_')) if common == '' or common[0] in string.digits: common = commonSuffix(s1.strip('_'), s2.strip('_')) if common == '' or common[0] in string.digits: common = 'VAR' if common == s1 or common == s2: newname = common else: counter = 0 newname = common while newname in mk.vars or newname in mk.__vars_opt: newname = '%s_%i' % (common,counter) counter += 1 del mk.__vars_opt[c1.name] del mk.__vars_opt[c2.name] del mk.cond_vars[c1.name] del mk.cond_vars[c2.name] if c1.name != newname: mk.vars[c1.name] = '$(%s)' % newname if c2.name != newname: mk.vars[c2.name] = '$(%s)' % newname hints = mk.getHints(c1.name) c1.name = c2.name = newname mk.addCondVar(c1, hints=hints) if config.verbose: sys.stdout.write(': %i -> %i\n' % (before, len(mk.cond_vars))) return len(duplicates) > 0
def handleSet(e, target=None, add_dict=None): try: errors.pushCtx("in <set> at %s" % e.location()) name = basename = evalConstExpr(e, e.props['var'], target) if (name in mk.override_vars) and target == None: return # can't change value of variable overriden with -D=xxx doEval = not ('eval' in e.props and e.props['eval'] == '0') overwrite = not ('overwrite' in e.props and e.props['overwrite'] == '0') isCond = (len(e.children) > 0) isMakeVar = 'make_var' in e.props and e.props['make_var'] == '1' value = e.value if 'hints' in e.props: hints = e.props['hints'] else: hints = '' # Handle conditions: if isCond: if e.value: raise ReaderError( e, "cannot set unconditional value when <if> is used") noValueSet = 1 for e_if in e.children: try: errors.pushCtx(e_if) if e_if.name != 'if': raise ReaderError(e_if, "malformed <set> command") # Preprocess always true or always false conditions: condstr = evalConstExpr(e_if, e_if.props['cond'], target=target, add_dict=add_dict) condstr = translateSpecialCondition(e_if, condstr, target) typ = mk.evalCondition(condstr) # Condition never met when generating this target: if typ == '0': if config.debug: print "[dbg] removing never-met condition '%s' for variable '%s'" % ( condstr, name) continue # Condition always met: elif typ == '1': if config.debug: print "[dbg] condition '%s' for variable '%s' is always met" % ( condstr, name) noValueSet = 0 isCond = 0 value = e_if.value break elif typ != None: raise ReaderError( e, "malformed condition '%s': doesn't evaluate to boolean value" % condstr) cond = mk.makeCondition(condstr) noValueSet = 0 # Real conditions: checkConditionsSupport(e) if 'scope' in e.props: raise ReaderError( e, "conditional variable can't have nondefault scope ('%s')" % e.props['scope']) if target != None: if (not overwrite) and (name in target.vars): return name = '__%s_%s' % (target.id.replace( '-', '_').replace('.', '_').replace('/', '_'), basename) mk.setVar(e.props['var'], '$(%s)' % name, eval=0, target=target, add_dict=add_dict, hints=hints) if cond == None: raise ReaderError( e, "malformed condition: '%s': must be constant expression, equality test or conjunction of them" % condstr) if name in mk.cond_vars: if not overwrite: return var = mk.cond_vars[name] else: var = mk.CondVar(name, target) mk.addCondVar(var, hints) if doEval: value = mk.evalExpr(e_if.value, target=target, add_dict=add_dict) else: value = e_if.value var.add(cond, value) finally: errors.popCtx() if noValueSet: isCond = 0 value = '' if isCond: return # Non-conditional variables: if value == None: value = '' if 'append' in e.props and e.props['append'] == '1': doAppend = 1 else: doAppend = 0 if 'prepend' in e.props and e.props['prepend'] == '1': doPrepend = 1 else: doPrepend = 0 store_in = None if 'scope' in e.props: sc = evalConstExpr(e, e.props['scope'], target=target) if sc == 'local': pass elif sc == 'global': store_in = mk.vars else: if sc in mk.targets: store_in = mk.targets[sc].vars else: raise ReaderError( e, "invalid scope '%s': must be 'global', 'local' or target name" % sc) if isMakeVar: if doAppend or store_in != None or not doEval: raise ReaderError( e, "make variable (%s) can't be appended or stored in nondefault scope or not evaluated" % name) mk.setVar(name, value, eval=doEval, target=target, add_dict=add_dict, store_in=store_in, append=doAppend, prepend=doPrepend, overwrite=overwrite, makevar=isMakeVar, hints=hints) finally: errors.popCtx()