コード例 #1
0
ファイル: builtin.py プロジェクト: gnprice/oil
def Export(argv, mem):
    arg, i = EXPORT_SPEC.Parse(argv)
    if arg.n:
        for name in argv[i:]:
            m = match.IsValidVarName(name)
            if not m:
                raise args.UsageError('export: Invalid variable name %r' %
                                      name)

            # NOTE: bash doesn't care if it wasn't found.
            mem.ClearFlag(name, var_flags_e.Exported, scope_e.Dynamic)
    else:
        for arg in argv[i:]:
            parts = arg.split('=', 1)
            if len(parts) == 1:
                name = parts[0]
                val = None  # Creates an empty variable
            else:
                name, s = parts
                val = runtime.Str(s)

            m = match.IsValidVarName(name)
            if not m:
                raise args.UsageError('export: Invalid variable name %r' %
                                      name)

            #log('%s %s', name, val)
            mem.SetVar(runtime.LhsName(name), val, (var_flags_e.Exported, ),
                       scope_e.Dynamic)

    return 0
コード例 #2
0
ファイル: cmd_parse.py プロジェクト: janiceshiu/oil
  def _ParseForEachLoop(self):
    node = ast.ForEach()
    node.do_arg_iter = False

    ok, iter_name, quoted = word.StaticEval(self.cur_word)
    if not ok or quoted:
      self.AddErrorContext(
          "Invalid for loop variable", word=self.cur_word)
      return None
    if not match.IsValidVarName(iter_name):
      self.AddErrorContext(
          "Invalid for loop variable name", word=self.cur_word)
      return None
    node.iter_name = iter_name
    self._Next()  # skip past name

    if not self._NewlineOk(): return None

    in_spid = const.NO_INTEGER
    semi_spid = const.NO_INTEGER

    if not self._Peek(): return None
    if self.c_id == Id.KW_In:
      self._Next()  # skip in

      in_spid = word.LeftMostSpanForWord(self.cur_word) + 1
      x = self.ParseForWords()
      if x is None:
        return None
      iter_words, semi_spid = x
      words2 = braces.BraceDetectAll(iter_words)
      words3 = word.TildeDetectAll(words2)

      if iter_words is None:  # empty list of words is OK
        return None
      node.iter_words = words3

    elif self.c_id == Id.Op_Semi:
      node.do_arg_iter = True  # implicit for loop
      self._Next()

    elif self.c_id == Id.KW_Do:
      node.do_arg_iter = True  # implicit for loop
      # do not advance

    else:
      self.AddErrorContext("Unexpected word in for loop: %s", self.cur_word,
          word=self.cur_word)
      return None

    node.spids.extend((in_spid, semi_spid))

    body_node = self.ParseDoGroup()
    if not body_node: return None

    node.body = body_node
    return node
コード例 #3
0
ファイル: builtin.py プロジェクト: gnprice/oil
def Repr(argv, mem):
    """Given a list of variable names, print their values.

  'repr a' is a lot easier to type than 'argv.py "${a[@]}"'.
  """
    status = 0
    for name in argv:
        if not match.IsValidVarName(name):
            util.error('%r is not a valid variable name', name)
            return 1

        # TODO: Should we print flags too?
        val = mem.GetVar(name)
        if val.tag == value_e.Undef:
            print('%r is not defined' % name)
            status = 1
        else:
            print('%s = %s' % (name, val))
    return status
コード例 #4
0
ファイル: word_eval.py プロジェクト: jedahan/oil
    def _ApplyPrefixOp(self, val, op_id):
        """
    Returns:
      value
    """
        assert val.tag != value_e.Undef

        if op_id == Id.VSub_Pound:  # LENGTH
            if val.tag == value_e.Str:
                # NOTE: Whether bash counts bytes or chars is affected by LANG
                # environment variables.
                # Should we respect that, or another way to select?  set -o
                # count-bytes?

                # https://stackoverflow.com/questions/17368067/length-of-string-in-bash
                try:
                    length = libstr.CountUtf8Chars(val.s)
                except util.InvalidUtf8 as e:
                    # TODO: Add location info from 'part'?  Only the caller has it.
                    if self.exec_opts.strict_word_eval:
                        raise
                    else:
                        # NOTE: Doesn't make the command exit with 1; it just returns a
                        # length of -1.
                        util.warn(e.UserErrorString())
                        return runtime.Str('-1')

            elif val.tag == value_e.StrArray:
                # There can be empty placeholder values in the array.
                length = sum(1 for s in val.strs if s is not None)

            return runtime.Str(str(length))

        elif op_id == Id.VSub_Bang:
            # NOTES:
            # - Could translate to eval('$' + name) or eval("\$$name")
            # - ${!array[@]} means something completely different.  TODO: implement
            #   that.
            # - It might make sense to suggest implementing this with associative
            #   arrays?

            # Treat the value of the variable as a variable name.
            if val.tag == value_e.Str:
                try:
                    # e.g. ${!OPTIND} gives $1 when OPTIND is 1
                    arg_num = int(val.s)
                    return self.mem.GetArgNum(arg_num)
                except ValueError:
                    if not match.IsValidVarName(val.s):
                        # TODO: location information.
                        # Also note that bash doesn't consider this fatal.  It makes the
                        # command exit with '1', but we don't have that ability yet?
                        e_die('Bad variable name %r in var ref', val.s)
                    return self.mem.GetVar(val.s)
            elif val.tag == value_e.StrArray:
                raise NotImplementedError(
                    '${!a[@]}')  # bash gets keys this way
            else:
                raise AssertionError

        else:
            raise AssertionError(op_id)
コード例 #5
0
ファイル: cmd_parse.py プロジェクト: janiceshiu/oil
  def _MakeAssignment(self, assign_kw, suffix_words):
    # First parse flags, e.g. -r -x -a -A.  None of the flags have arguments.
    flags = []
    n = len(suffix_words)
    i = 1
    while i < n:
      w = suffix_words[i]
      ok, static_val, quoted = word.StaticEval(w)
      if not ok or quoted:
        break  # can't statically evaluate

      if static_val.startswith('-'):
        flags.append(static_val)
      else:
        break  # not a flag, rest are args
      i += 1

    # Now parse bindings or variable names
    assignments = []
    while i < n:
      w = suffix_words[i]
      left_spid = word.LeftMostSpanForWord(w)
      kov = word.LooksLikeAssignment(w)
      if kov:
        k, op, v = kov
        t = word.TildeDetect(v)
        if t:
          # t is an unevaluated word with TildeSubPart
          a = (k, op, t, left_spid)
        else:
          a = (k, op, v, left_spid)  # v is unevaluated word
      else:
        # In aboriginal in variables/sources: export_if_blank does export "$1".
        # We should allow that.

        # Parse this differently then?
        # dynamic-export?
        # It sets global variables.
        ok, static_val, quoted = word.StaticEval(w)
        if not ok or quoted:
           self.AddErrorContext(
               'Variable names must be constant strings, got %s', w, word=w)
           return None

        # No value is equivalent to ''
        if not match.IsValidVarName(static_val):
          self.AddErrorContext('Invalid variable name %r', static_val, word=w)
          return None
        a = (static_val, assign_op_e.Equal, None, left_spid)

      assignments.append(a)
      i += 1

    # TODO: Also make with LhsIndexedName
    pairs = []
    for lhs, op, rhs, spid in assignments:
      p = ast.assign_pair(ast.LhsName(lhs), op, rhs)
      p.spids.append(spid)
      pairs.append(p)

    node = ast.Assignment(assign_kw, flags, pairs)

    return node