Example #1
0
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)
Example #2
0
    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")
Example #3
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()
Example #4
0
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
Example #5
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()
Example #6
0
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