Beispiel #1
0
        def substitute(self, args, lvars):
            """Substitute expansions in an argument or list of arguments.

            This serves as a wrapper for splitting up a string into
            separate tokens.
            """
            if is_String(args) and not isinstance(args, CmdStringHolder):
                args = str(args)        # In case it's a UserString.
                try:
                    def sub_match(match):
                        return self.conv(self.expand(match.group(1), lvars))
                    result = _dollar_exps.sub(sub_match, args)
                except TypeError:
                    # If the internal conversion routine doesn't return
                    # strings (it could be overridden to return Nodes, for
                    # example), then the 1.5.2 re module will throw this
                    # exception.  Back off to a slower, general-purpose
                    # algorithm that works for all data types.
                    args = _separate_args.findall(args)
                    result = []
                    for a in args:
                        result.append(self.conv(self.expand(a, lvars)))
                    if len(result) == 1:
                        result = result[0]
                    else:
                        result = ''.join(map(str, result))
                return result
            else:
                return self.expand(args, lvars)
Beispiel #2
0
        def expand(self, s, lvars):
            """Expand a single "token" as necessary, returning an
            appropriate string containing the expansion.

            This handles expanding different types of things (strings,
            lists, callables) appropriately.  It calls the wrapper
            substitute() method to re-expand things as necessary, so that
            the results of expansions of side-by-side strings still get
            re-evaluated separately, not smushed together.
            """
            if is_String(s):
                try:
                    s0, s1 = s[:2]
                except (IndexError, ValueError):
                    return s
                if s0 != '$':
                    return s
                if s1 == '$':
                    return '$'
                elif s1 in '()':
                    return s
                else:
                    key = s[1:]
                    if key[0] == '{' or key.find('.') >= 0:
                        if key[0] == '{':
                            key = key[1:-1]
                        try:
                            s = eval(key, self.gvars, lvars)
                        except KeyboardInterrupt:
                            raise
                        except Exception, e:
                            if e.__class__ in AllowableExceptions:
                                return ''
                            raise_exception(e, lvars['TARGETS'], s)
                    else:
                        if key in lvars:
                            s = lvars[key]
                        elif key in self.gvars:
                            s = self.gvars[key]
                        elif not NameError in AllowableExceptions:
                            raise_exception(NameError(key), lvars['TARGETS'], s)
                        else:
                            return ''
    
                    # Before re-expanding the result, handle
                    # recursive expansion by copying the local
                    # variable dictionary and overwriting a null
                    # string for the value of the variable name
                    # we just expanded.
                    #
                    # This could potentially be optimized by only
                    # copying lvars when s contains more expansions,
                    # but lvars is usually supposed to be pretty
                    # small, and deeply nested variable expansions
                    # are probably more the exception than the norm,
                    # so it should be tolerable for now.
                    lv = lvars.copy()
                    var = key.split('.')[0]
                    lv[var] = ''
                    return self.substitute(s, lv)
Beispiel #3
0
        def expand(self, s, lvars, within_list):
            """Expand a single "token" as necessary, appending the
            expansion to the current result.

            This handles expanding different types of things (strings,
            lists, callables) appropriately.  It calls the wrapper
            substitute() method to re-expand things as necessary, so that
            the results of expansions of side-by-side strings still get
            re-evaluated separately, not smushed together.
            """

            if is_String(s):
                try:
                    s0, s1 = s[:2]
                except (IndexError, ValueError):
                    self.append(s)
                    return
                if s0 != '$':
                    self.append(s)
                    return
                if s1 == '$':
                    self.append('$')
                elif s1 == '(':
                    self.open_strip('$(')
                elif s1 == ')':
                    self.close_strip('$)')
                else:
                    key = s[1:]
                    if key[0] == '{' or key.find('.') >= 0:
                        if key[0] == '{':
                            key = key[1:-1]
                        try:
                            s = eval(key, self.gvars, lvars)
                        except KeyboardInterrupt:
                            raise
                        except Exception, e:
                            if e.__class__ in AllowableExceptions:
                                return
                            raise_exception(e, lvars['TARGETS'], s)
                    else:
                        if key in lvars:
                            s = lvars[key]
                        elif key in self.gvars:
                            s = self.gvars[key]
                        elif not NameError in AllowableExceptions:
                            raise_exception(NameError(), lvars['TARGETS'], s)
                        else:
                            return

                    # Before re-expanding the result, handle
                    # recursive expansion by copying the local
                    # variable dictionary and overwriting a null
                    # string for the value of the variable name
                    # we just expanded.
                    lv = lvars.copy()
                    var = key.split('.')[0]
                    lv[var] = ''
                    self.substitute(s, lv, 0)
                    self.this_word()
Beispiel #4
0
 def add_new_word(self, x):
     if not self.in_strip or self.mode != SUBST_SIG:
         literal = self.literal(x)
         x = self.conv(x)
         if is_String(x):
             x = CmdStringHolder(x, literal)
         self[-1].append(x)
     self.append = self.add_to_current_word
Beispiel #5
0
def scons_subst_once(strSubst, env, key):
    """Perform single (non-recursive) substitution of a single
    construction variable keyword.

    This is used when setting a variable when copying or overriding values
    in an Environment.  We want to capture (expand) the old value before
    we override it, so people can do things like:

        env2 = env.Clone(CCFLAGS = '$CCFLAGS -g')

    We do this with some straightforward, brute-force code here...
    """
    if isinstance(strSubst, str) and strSubst.find('$') < 0:
        return strSubst

    matchlist = ['$' + key, '${' + key + '}']
    val = env.get(key, '')
    def sub_match(match, val=val, matchlist=matchlist):
        a = match.group(1)
        if a in matchlist:
            a = val
        if is_Sequence(a):
            return ' '.join(map(str, a))
        else:
            return str(a)

    if is_Sequence(strSubst):
        result = []
        for arg in strSubst:
            if is_String(arg):
                if arg in matchlist:
                    arg = val
                    if is_Sequence(arg):
                        result.extend(arg)
                    else:
                        result.append(arg)
                else:
                    result.append(_dollar_exps.sub(sub_match, arg))
            else:
                result.append(arg)
        return result
    elif is_String(strSubst):
        return _dollar_exps.sub(sub_match, strSubst)
    else:
        return strSubst
Beispiel #6
0
        def add_to_current_word(self, x):
            """Append the string x to the end of the current last word
            in the result.  If that is not possible, then just add
            it as a new word.  Make sure the entire concatenated string
            inherits the object attributes of x (in particular, the
            escape function) by wrapping it as CmdStringHolder."""

            if not self.in_strip or self.mode != SUBST_SIG:
                try:
                    current_word = self[-1][-1]
                except IndexError:
                    self.add_new_word(x)
                else:
                    # All right, this is a hack and it should probably
                    # be refactored out of existence in the future.
                    # The issue is that we want to smoosh words together
                    # and make one file name that gets escaped if
                    # we're expanding something like foo$EXTENSION,
                    # but we don't want to smoosh them together if
                    # it's something like >$TARGET, because then we'll
                    # treat the '>' like it's part of the file name.
                    # So for now, just hard-code looking for the special
                    # command-line redirection characters...
                    try:
                        last_char = str(current_word)[-1]
                    except IndexError:
                        last_char = '\0'
                    if last_char in '<>|':
                        self.add_new_word(x)
                    else:
                        y = current_word + x

                        # We used to treat a word appended to a literal
                        # as a literal itself, but this caused problems
                        # with interpreting quotes around space-separated
                        # targets on command lines.  Removing this makes
                        # none of the "substantive" end-to-end tests fail,
                        # so we'll take this out but leave it commented
                        # for now in case there's a problem not covered
                        # by the test cases and we need to resurrect this.
                        #literal1 = self.literal(self[-1][-1])
                        #literal2 = self.literal(x)
                        y = self.conv(y)
                        if is_String(y):
                            #y = CmdStringHolder(y, literal1 or literal2)
                            y = CmdStringHolder(y, None)
                        self[-1][-1] = y
Beispiel #7
0
        def substitute(self, args, lvars, within_list):
            """Substitute expansions in an argument or list of arguments.

            This serves as a wrapper for splitting up a string into
            separate tokens.
            """

            if is_String(args) and not isinstance(args, CmdStringHolder):
                args = str(args)        # In case it's a UserString.
                args = _separate_args.findall(args)
                for a in args:
                    if a[0] in ' \t\n\r\f\v':
                        if '\n' in a:
                            self.next_line()
                        elif within_list:
                            self.append(a)
                        else:
                            self.next_word()
                    else:
                        self.expand(a, lvars, within_list)
            else:
                self.expand(args, lvars, within_list)
Beispiel #8
0
    # find a __builtins__ value in the global dictionary used for eval(),
    # it copies the current global values for you.  Avoid this by
    # setting it explicitly and then deleting, so we don't pollute the
    # construction environment Dictionary(ies) that are typically used
    # for expansion.
    gvars['__builtins__'] = __builtins__

    ss = StringSubber(env, mode, conv, gvars)
    result = ss.substitute(strSubst, lvars)

    try:
        del gvars['__builtins__']
    except KeyError:
        pass

    if is_String(result):
        # Remove $(-$) pairs and any stuff in between,
        # if that's appropriate.
        remove = _regex_remove[mode]
        if remove:
            result = remove.sub('', result)
        if mode != SUBST_RAW:
            # Compress strings of white space characters into
            # a single space.
            result = _space_sep.sub(' ', result).strip()
    elif is_Sequence(result):
        remove = _list_remove[mode]
        if remove:
            result = remove(result)

    return result