示例#1
0
  def _EvalDoubleQuotedPart(self, part, part_vals):
    """DoubleQuotedPart -> part_value

    Args:
      part_vals: output param to append to.
    """
    # Example of returning array:
    # $ a=(1 2); b=(3); $ c=(4 5)
    # $ argv "${a[@]}${b[@]}${c[@]}"
    # ['1', '234', '5']
    # Example of multiple parts
    # $ argv "${a[@]}${undef[@]:-${c[@]}}"
    # ['1', '24', '5']

    #log('DQ part %s', part)

    # Special case for "".  The parser outputs (DoubleQuotedPart []), instead
    # of (DoubleQuotedPart [LiteralPart '']).  This is better but it means we
    # have to check for it.
    if not part.parts:
      v = runtime.StringPartValue('', False)
      part_vals.append(v)
      return

    for p in part.parts:
      self._EvalWordPart(p, part_vals, quoted=True)
示例#2
0
    def _EvalCommandSub(self, node, quoted):
        stdout = self.ex.RunCommandSub(node)

        # Runtime errors test case: # $("echo foo > $@")

        # Why rstrip()?
        # https://unix.stackexchange.com/questions/17747/why-does-shell-command-substitution-gobble-up-a-trailing-newline-char
        return runtime.StringPartValue(stdout, not quoted, not quoted)
示例#3
0
    def _EvalDoubleQuotedPart(self, part):
        # Example of returning array:
        # $ a=(1 2); b=(3); $ c=(4 5)
        # $ argv "${a[@]}${b[@]}${c[@]}"
        # ['1', '234', '5']
        # Example of multiple parts
        # $ argv "${a[@]}${undef[@]:-${c[@]}}"
        # ['1', '24', '5']

        #log('DQ part %s', part)

        # Special case for "".  The parser outputs (DoubleQuotedPart []), instead
        # of (DoubleQuotedPart [LiteralPart '']).  This is better but it means we
        # have to check for it.
        if not part.parts:
            return runtime.StringPartValue('', False, False)

        frag_arrays = [[]]
        for p in part.parts:
            for part_val in self._EvalWordPart(p, quoted=True):
                assert isinstance(part_val, runtime.part_value), (p, part_val)
                if part_val.tag == part_value_e.StringPartValue:
                    frag_arrays[-1].append(part_val.s)
                else:
                    for i, s in enumerate(part_val.strs):
                        if i == 0:
                            frag_arrays[-1].append(s)
                        else:
                            frag_arrays.append([s])

        #log('frag_arrays %s', frag_arrays)

        strs = []
        for frag_array in frag_arrays:
            # "${empty[@]}" leads to [[]], should eval to [] and not ['']
            if frag_array:
                strs.append(''.join(frag_array))

        # This should be able to evaluate to EMPTY ARRAY!
        #log('strs %s', strs)
        if len(strs) == 1:
            val = runtime.StringPartValue(strs[0], False, False)
        else:
            val = runtime.ArrayPartValue(strs)
        return val
示例#4
0
def _ValueToPartValue(val, quoted):
    """Helper for VarSub evaluation."""
    assert isinstance(val, runtime.value), val
    if val.tag == value_e.Undef:
        return runtime.UndefPartValue()

    elif val.tag == value_e.Str:
        return runtime.StringPartValue(val.s, not quoted, not quoted)

    elif val.tag == value_e.StrArray:
        return runtime.ArrayPartValue(val.strs)

    else:
        raise AssertionError
示例#5
0
def _ValueToPartValue(val, quoted):
  """Helper for VarSub evaluation.

  Called by _EvalBracedVarSub and __EvalWordPart for SimpleVarSub.
  """
  assert isinstance(val, runtime.value), val

  if val.tag == value_e.Str:
    return runtime.StringPartValue(val.s, not quoted)

  elif val.tag == value_e.StrArray:
    return runtime.ArrayPartValue(val.strs)

  else:
    # Undef should be caught by _EmptyStrOrError().
    raise AssertionError
示例#6
0
文件: word_eval.py 项目: silky/oil
    def _EvalCommandSub(self, node, quoted):
        p = self.ex._GetProcessForNode(node)
        # NOTE: We could do an optimization for pipelines.  Pick the last
        # process element, and do pi.procs[-1].CaptureOutput()
        stdout = []
        p.CaptureOutput(stdout)
        status = p.Run()

        # Runtime errors:
        # what if the command sub was "echo foo > $@".  That is invalid.  Then
        # Return false here.  How do we get that value from the Process then?  Do
        # we use a special return value?

        # I think $() does a strip basically?
        # argv $(echo ' hi')$(echo bye) -> hibye
        s = ''.join(stdout).strip()
        return runtime.StringPartValue(s, not quoted, not quoted)
示例#7
0
    def _EvalCommandSub(self, node, quoted):
        p = self.ex._GetProcessForNode(node)
        # NOTE: We could do an optimization for pipelines.  Pick the last
        # process element, and do pi.procs[-1].CaptureOutput()
        stdout = []
        p.CaptureOutput(stdout)
        status = p.Run()

        # TODO: Add context
        if self.ex.exec_opts.errexit and status != 0:
            e_die('Command sub exited with status %d (%r)', status,
                  node.__class__.__name__)

        # Runtime errors:
        # what if the command sub was "echo foo > $@".  That is invalid.  Then
        # Return false here.  How do we get that value from the Process then?  Do
        # we use a special return value?

        # Why rstrip()?
        # https://unix.stackexchange.com/questions/17747/why-does-shell-command-substitution-gobble-up-a-trailing-newline-char
        s = ''.join(stdout).rstrip('\n')
        return runtime.StringPartValue(s, not quoted, not quoted)
示例#8
0
 def _EvalProcessSub(self, node, id_):
   return runtime.StringPartValue('__PROCESS_SUB_NOT_EXECUTED__', False)
示例#9
0
 def _EvalCommandSub(self, node, quoted):
   return runtime.StringPartValue('__COMMAND_SUB_NOT_EXECUTED__', not quoted)
示例#10
0
 def _EvalProcessSub(self, node, id_):
   dev_path = self.ex.RunProcessSub(node, id_)
   return runtime.StringPartValue(dev_path, False)  # no split or glob
示例#11
0
 def _EvalCommandSub(self, node, quoted):
   stdout = self.ex.RunCommandSub(node)
   return runtime.StringPartValue(stdout, not quoted)
示例#12
0
  def _EvalWordPart(self, part, part_vals, quoted=False):
    """Evaluate a word part.

    Args:
      part_vals: Output parameter.

    Returns:
      None
    """
    if part.tag == word_part_e.ArrayLiteralPart:
      raise AssertionError(
          'Array literal should have been handled at word level')

    elif part.tag == word_part_e.LiteralPart:
      v = runtime.StringPartValue(part.token.val, not quoted)
      part_vals.append(v)

    elif part.tag == word_part_e.EscapedLiteralPart:
      val = part.token.val
      assert len(val) == 2, val  # e.g. \*
      assert val[0] == '\\'
      s = val[1]
      v = runtime.StringPartValue(s, False)
      part_vals.append(v)

    elif part.tag == word_part_e.EmptyPart:
      part_vals.append(runtime.StringPartValue('', False))

    elif part.tag == word_part_e.SingleQuotedPart:
      if part.left.id == Id.Left_SingleQuote:
        s = ''.join(t.val for t in part.tokens)
      elif part.left.id == Id.Left_DollarSingleQuote:
        # NOTE: This could be done at compile time
        s = ''.join(word_compile.EvalCStringToken(t.id, t.val)
                    for t in part.tokens)
      else:
        raise AssertionError(part.left.id)

      v = runtime.StringPartValue(s, False)
      part_vals.append(v)

    elif part.tag == word_part_e.DoubleQuotedPart:
      self._EvalDoubleQuotedPart(part, part_vals)

    elif part.tag == word_part_e.CommandSubPart:
      id_ = part.left_token.id
      if id_ in (Id.Left_CommandSub, Id.Left_Backtick):
        v = self._EvalCommandSub(part.command_list, quoted)

      elif id_ in (Id.Left_ProcSubIn, Id.Left_ProcSubOut):
        v = self._EvalProcessSub(part.command_list, id_)

      else:
        raise AssertionError(id_)

      part_vals.append(v)

    elif part.tag == word_part_e.SimpleVarSub:
      decay_array = False
      # 1. Evaluate from (var_name, var_num, token) -> defined, value
      if part.token.id == Id.VSub_Name:
        var_name = part.token.val[1:]
        val = self.mem.GetVar(var_name)
      elif part.token.id == Id.VSub_Number:
        var_num = int(part.token.val[1:])
        val = self._EvalVarNum(var_num)
      else:
        val, decay_array = self._EvalSpecialVar(part.token.id, quoted)

      #log('SIMPLE %s', part)
      val = self._EmptyStrOrError(val, token=part.token)
      if decay_array:
        val = self._DecayArray(val)
      v = _ValueToPartValue(val, quoted)
      part_vals.append(v)

    elif part.tag == word_part_e.BracedVarSub:
      self._EvalBracedVarSub(part, part_vals, quoted)

    elif part.tag == word_part_e.TildeSubPart:
      # We never parse a quoted string into a TildeSubPart.
      assert not quoted
      s = self._EvalTildeSub(part.prefix)
      v = runtime.StringPartValue(s, False)
      part_vals.append(v)

    elif part.tag == word_part_e.ArithSubPart:
      num = self.arith_ev.Eval(part.anode)
      v = runtime.StringPartValue(str(num), False)
      part_vals.append(v)

    else:
      raise AssertionError(part.__class__.__name__)
示例#13
0
    def _EvalWordPart(self, part, quoted=False):
        """Evaluate a word part.

    Returns:
      A LIST of part_value, rather than just a single part_value, because of
      the quirk where ${a:-'x'y} is a single WordPart, but yields two
      part_values.
    """
        if part.tag == word_part_e.ArrayLiteralPart:
            raise AssertionError(
                'Array literal should have been handled at word level')

        elif part.tag == word_part_e.LiteralPart:
            s = part.token.val
            do_split_elide = not quoted
            do_glob = True
            return [runtime.StringPartValue(s, do_split_elide, do_glob)]

        elif part.tag == word_part_e.EscapedLiteralPart:
            val = part.token.val
            assert len(val) == 2, val  # e.g. \*
            assert val[0] == '\\'
            s = val[1]
            return [runtime.StringPartValue(s, False, False)]

        elif part.tag == word_part_e.SingleQuotedPart:
            s = ''.join(t.val for t in part.tokens)
            return [runtime.StringPartValue(s, False, False)]

        elif part.tag == word_part_e.DoubleQuotedPart:
            return [self._EvalDoubleQuotedPart(part)]

        elif part.tag == word_part_e.CommandSubPart:
            if part.left_token.id not in (Id.Left_CommandSub,
                                          Id.Left_Backtick):
                # TODO: If token is Id.Left_ProcSubIn or Id.Left_ProcSubOut, we have to
                # supply something like /dev/fd/63.
                raise NotImplementedError(part.left_token.id)

            return [self._EvalCommandSub(part.command_list, quoted)]

        elif part.tag == word_part_e.SimpleVarSub:
            decay_array = False
            # 1. Evaluate from (var_name, var_num, token) -> defined, value
            if part.token.id == Id.VSub_Name:
                var_name = part.token.val[1:]
                val = self.mem.GetVar(var_name)
            elif part.token.id == Id.VSub_Number:
                var_num = int(part.token.val[1:])
                val = self._EvalVarNum(var_num)
            else:
                val, decay_array = self._EvalSpecialVar(part.token.id, quoted)

            #log('SIMPLE %s', part)
            val = self._EmptyStrOrError(val, token=part.token)
            if decay_array:
                val = self._DecayArray(val)
            part_val = _ValueToPartValue(val, quoted)
            return [part_val]

        elif part.tag == word_part_e.BracedVarSub:
            return self._EvalBracedVarSub(part, quoted)

        elif part.tag == word_part_e.TildeSubPart:
            # We never parse a quoted string into a TildeSubPart.
            assert not quoted
            s = self._EvalTildeSub(part.prefix)
            return [runtime.StringPartValue(s, False, False)]

        elif part.tag == word_part_e.ArithSubPart:
            num = self.arith_ev.Eval(part.anode)
            return [runtime.StringPartValue(str(num), True, True)]

        else:
            raise AssertionError(part.tag)