Exemple #1
0
    def EvalWordToString(self, word, do_fnmatch=False, decay=False):
        """
    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
    """
        strs = []
        for part in word.parts:
            for part_val in self.part_ev._EvalWordPart(part, quoted=False):
                # TODO: if decay, then allow string part.  e.g. for here word or here
                # doc with "$@".

                if part_val.tag != part_value_e.StringPartValue:
                    # Example: echo f > "$@".  TODO: Add proper context.
                    e_die("Expected string, got %s", part)
                if do_fnmatch:
                    if part_val.do_glob:
                        strs.append(part_val.s)
                    else:
                        strs.append(glob_.GlobEscape(part_val.s))
                else:
                    strs.append(part_val.s)

        return runtime.Str(''.join(strs))
Exemple #2
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 runtime.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.StringPartValue:
                # [[ 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 runtime.Str(''.join(strs))
Exemple #3
0
  def EvalWordToString(self, word, do_fnmatch=False, decay=False):
    """
    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
    """
    part_vals = []
    for part in word.parts:
      self._EvalWordPart(part, part_vals, quoted=False)

    strs = []
    for part_val in part_vals:
      # TODO: if decay, then allow string part.  e.g. for here word or here
      # doc with "$@".

      if part_val.tag == part_value_e.StringPartValue:
        # [[ foo == */"*".py ]] or case *.py) ... esac
        if do_fnmatch and not part_val.do_split_glob:
          s = glob_.GlobEscape(part_val.s)
        else:
          s = part_val.s
      else:
        if self.exec_opts.strict_array:
          # Examples: echo f > "$@"; local foo="$@"
          e_die("Expected string, got %s", part_val, word=word)

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

      strs.append(s)

    return runtime.Str(''.join(strs))
Exemple #4
0
def _JoinElideEscape(frag_arrays, elide_empty, glob_escape):
    """Join parts without globbing or eliding.

  Returns:
    arg_value[]
  """
    args = []
    #log('_JoinElideEscape frag_arrays %s', frag_arrays)
    for frag_array in frag_arrays:
        if glob_escape:
            #log('frag_array: %s', frag_array)
            escaped_frags = []
            any_glob = False
            for frag in frag_array:
                if frag.do_glob:  # *.py should be literal
                    escaped_frags.append(frag.s)
                    any_glob = True
                else:
                    # "*.py" should be glob-escaped to \*.py
                    escaped_frags.append(glob_.GlobEscape(frag.s))

            arg_str = ''.join(escaped_frags)
            #log('ARG STR %s', arg_str)
            if any_glob:
                arg = runtime.GlobArg(arg_str)
            else:
                # e.g. 'foo'"${var}" shouldn't be globbed
                # TODO: combine with below:
                arg = runtime.ConstArg(''.join(frag.s for frag in frag_array))
        else:
            arg = runtime.ConstArg(''.join(frag.s for frag in frag_array))

        # Elide $a$b, but not $a"$b" or $a''
        if (elide_empty and not arg.s
                and all(frag.do_elide for frag in frag_array)):
            #log('eliding frag_array %s', frag_array)
            continue

        args.append(arg)

    return args
Exemple #5
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)