Exemple #1
0
    def EvalWordToString(self, word, do_fnmatch=False, do_ere=False):
        """
    Args:
      word: CompoundWord

    Used for redirect arg, ControlFlow arg, ArithWord, BoolWord, etc.

    do_fnmatch is true for case $pat and RHS of [[ == ]].

    pat="*.py"
    case $x in
      $pat) echo 'matches glob pattern' ;;
      "$pat") echo 'equal to glob string' ;;  # must be glob escaped
    esac

    TODO: Raise AssertionError if it has ExtGlobPart.
    """
        if word.tag == word_e.EmptyWord:
            return value.Str('')

        part_vals = []
        for p in word.parts:
            self._EvalWordPart(p, part_vals, quoted=False)

        strs = []
        for part_val in part_vals:
            if part_val.tag == part_value_e.String:
                # [[ foo == */"*".py ]] or case *.py) ... esac
                if do_fnmatch and not part_val.do_split_glob:
                    s = glob_.GlobEscape(part_val.s)
                elif do_ere and not part_val.do_split_glob:
                    s = glob_.ExtendedRegexEscape(part_val.s)
                else:
                    s = part_val.s
            else:
                if self.exec_opts.strict_array:
                    # Examples: echo f > "$@"; local foo="$@"

                    # TODO: This attributes too coarsely, to the word rather than the
                    # parts.  Problem: the word is a TREE of parts, but we only have a
                    # flat list of part_vals.  The only case where we really get arrays
                    # is "$@", "${a[@]}", "${a[@]//pat/replace}", etc.
                    e_die(
                        "This word should evaluate to a string, but part of it was an "
                        "array",
                        word=word)

                    # TODO: Maybe add detail like this.
                    #e_die('RHS of assignment should only have strings.  '
                    #      'To assign arrays, use b=( "${a[@]}" )')
                else:
                    # It appears to not respect IFS
                    s = ' '.join(s for s in part_val.strs if s is not None)

            strs.append(s)

        return value.Str(''.join(strs))
Exemple #2
0
  def _EvalWordFrame(self, frame, argv):
    all_empty = True
    all_split_glob = True
    any_split_glob = False

    #log('--- frame %s', frame)

    for s, do_split_glob in frame:
      #log('-- %r %r', s, do_split_glob)
      if s:
        all_empty = False

      if do_split_glob:
        any_split_glob = True
      else:
        all_split_glob = False

    # Elision of ${empty}${empty} but not $empty"$empty" or $empty""
    if all_empty and all_split_glob:
      return

    # If every frag is quoted, e.g. "$a$b" or any part in "${a[@]}"x, then
    # don't do word splitting or globbing.
    if not any_split_glob:
      a = ''.join(s for s, _ in frame)
      argv.append(a)
      return

    will_glob = not self.exec_opts.noglob

    # Array of strings, some of which are BOTH IFS-escaped and GLOB escaped!
    frags = []
    for frag, do_split_glob in frame:
      #log('frag %r do_split_glob %s', frag, do_split_glob)

      # If it was quoted, then

      if do_split_glob:
        # We're going to both split and glob.  So we want to backslash
        # escape twice?

        # Suppose we get a literal \.
        # \ -> \\
        # \\ -> \\\\
        # Splitting takes \\\\ -> \\
        # Globbing takes \\ to \ if it doesn't match
        if will_glob:
          frag = _BackslashEscape(frag)
        frag = _BackslashEscape(frag)
      else:
        if will_glob:
          frag = glob_.GlobEscape(frag)
          #log('GLOB ESCAPED %r', p2)

        frag = self.splitter.Escape(frag)
        #log('IFS ESCAPED %r', p2)

      frags.append(frag)

    flat = ''.join(frags)
    #log('flat: %r', flat)

    args = self.splitter.SplitForWordEval(flat)

    # space=' '; argv $space"".  We have a quoted part, but we CANNOT elide.
    # Add it back and don't bother globbing.
    if not args and not all_split_glob:
      argv.append('')
      return

    #log('split args: %r', args)
    for a in args:
      # TODO: Expand() should take out parameter.
      results = self.globber.Expand(a)
      argv.extend(results)