def ParseLikeEcho(self, argv):
        # type: (List[str]) -> Tuple[args._Attributes, int]
        """
    echo is a special case.  These work:
      echo -n
      echo -en
   
    - But don't respect --
    - doesn't fail when an invalid flag is passed
    """
        arg_r = args.Reader(argv)
        out = args._Attributes(self.defaults)

        while not arg_r.AtEnd():
            arg = arg_r.Peek()
            chars = arg[1:]
            if arg.startswith('-') and chars:
                # Check if it looks like -en or not.
                # NOTE: Changed to list comprehension to avoid
                # LOAD_CLOSURE/MAKE_CLOSURE.
                if not all([c in self.arity0 for c in arg[1:]]):
                    break  # looks like args

                for ch in chars:
                    assert ch in self.arity0
                    out.SetTrue(ch)

            else:
                break  # Looks like an arg

            arg_r.Next()  # next arg

        return out, arg_r.i
示例#2
0
  def Run(self, cmd_val):
    # type: (cmd_value__Assign) -> int
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()
    attrs = flag_spec.Parse('readonly', arg_r)
    arg = arg_types.readonly(attrs.attrs)

    if arg.p or len(cmd_val.pairs) == 0:
      return _PrintVariables(self.mem, cmd_val, attrs, True, builtin=_READONLY)

    for pair in cmd_val.pairs:
      if pair.rval is None:
        if arg.a:
          rval = value.MaybeStrArray([])  # type: value_t
        elif arg.A:
          rval = value.AssocArray({})
        else:
          rval = None
      else:
        rval = pair.rval

      rval = _ReconcileTypes(rval, arg.a, arg.A, pair.spid)

      # NOTE:
      # - when rval is None, only flags are changed
      # - dynamic scope because flags on locals can be changed, etc.
      self.mem.SetVar(lvalue.Named(pair.var_name), rval, scope_e.Dynamic,
                      flags=state.SetReadOnly)

    return 0
示例#3
0
  def __call__(self, cmd_val):
    # TODO:
    # - How to integrate this with auto-completion?  Have to handle '+'.

    if len(cmd_val.argv) == 1:
      # 'set' without args shows visible variable names and values.  According
      # to POSIX:
      # - the names should be sorted, and 
      # - the code should be suitable for re-input to the shell.  We have a
      #   spec test for this.
      # Also:
      # - autoconf also wants them to fit on ONE LINE.
      # http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
      mapping = self.mem.GetAllVars()
      for name in sorted(mapping):
        str_val = mapping[name]
        code_str = '%s=%s' % (name, string_ops.ShellQuoteOneLine(str_val))
        print(code_str)
      return 0

    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()  # skip 'set'
    arg = SET_SPEC.Parse(arg_r)

    # 'set -o' shows options.  This is actually used by autoconf-generated
    # scripts!
    if arg.show_options:
      self.exec_opts.ShowOptions([])
      return 0

    SetExecOpts(self.exec_opts, arg.opt_changes, arg.shopt_changes)
    # Hm do we need saw_double_dash?
    if arg.saw_double_dash or not arg_r.AtEnd():
      self.mem.SetArgv(arg_r.Rest())
    return 0
  def Run(self, cmd_val):
    # type: (cmd_value__Argv) -> int

    # There are no flags, but we need it to respect --
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()  # skip 'eval'
    arg = EVAL_SPEC.Parse(arg_r)

    if self.exec_opts.strict_eval_builtin():
      code_str, eval_spid = arg_r.ReadRequired2('requires code string')
      if not arg_r.AtEnd():
        raise error.Usage('requires exactly 1 argument')
    else:
      code_str = ' '.join(cmd_val.argv[arg_r.i:])
      # code_str could be EMPTY, so just use the first one
      eval_spid = cmd_val.arg_spids[0]

    line_reader = reader.StringLineReader(code_str, self.arena)
    c_parser = self.parse_ctx.MakeOshParser(line_reader)

    src = source.EvalArg(eval_spid)
    self.arena.PushSource(src)
    try:
      return main_loop.Batch(self.cmd_ev, c_parser, self.arena)
    finally:
      self.arena.PopSource()
示例#5
0
    def __call__(self, argv):
        arg_r = args.Reader(argv)
        arg = COMPLETE_SPEC.Parse(arg_r)
        # TODO: process arg.opt_changes
        #log('arg %s', arg)

        commands = arg_r.Rest()

        if arg.D:
            commands.append(
                '__fallback')  # if the command doesn't match anything
        if arg.E:
            commands.append('__first')  # empty line

        if not commands:
            self.comp_lookup.PrintSpecs()
            return 0

        base_opts = dict(arg.opt_changes)
        try:
            user_spec = self.spec_builder.Build(argv, arg, base_opts)
        except util.ParseError as e:
            # error printed above
            return 2
        for command in commands:
            self.comp_lookup.RegisterName(command, base_opts, user_spec)

        patterns = []
        for pat in patterns:
            self.comp_lookup.RegisterGlob(pat, base_opts, user_spec)

        return 0
示例#6
0
  def Run(self, cmd_val):
    # type: (cmd_value__Argv) -> int

    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()  # skip 'exec'
    _ = EXEC_SPEC.Parse(arg_r)  # no flags now, but accepts --

    # Apply redirects in this shell.  # NOTE: Redirects were processed earlier.
    if arg_r.AtEnd():
      self.fd_state.MakePermanent()
      return 0

    environ = self.mem.GetExported()
    i = arg_r.i
    cmd = cmd_val.argv[i]
    argv0_path = self.search_path.CachedLookup(cmd)
    if argv0_path is None:
      self.errfmt.Print('exec: %r not found', cmd,
                        span_id=cmd_val.arg_spids[1])
      raise SystemExit(127)  # exec builtin never returns

    # shift off 'exec'
    c2 = cmd_value.Argv(cmd_val.argv[i:], cmd_val.arg_spids[i:], cmd_val.block)
    self.ext_prog.Exec(argv0_path, c2, environ)  # NEVER RETURNS
    assert False, "This line should never be reached" # makes mypy happy
示例#7
0
    def __call__(self, argv):
        arg_r = args.Reader(argv)
        arg = INIT_COMPLETION_SPEC.Parse(arg_r)
        var_names = arg_r.Rest()  # Output variables to set
        for name in var_names:
            # Ironically we could complete these
            if name not in ['cur', 'prev', 'words', 'cword']:
                raise args.UsageError('Invalid output variable name %r' % name)
        #print(arg)

        # TODO: How does the user test a completion function programmatically?  Set
        # COMP_ARGV?
        val = self.mem.GetVar('COMP_ARGV')
        if val.tag != value_e.StrArray:
            raise args.UsageError("COMP_ARGV should be an array")
        comp_argv = val.strs

        # These are the ones from COMP_WORDBREAKS that we care about.  The rest occur
        # "outside" of words.
        break_chars = [':', '=']
        if arg.s:  # implied
            break_chars.remove('=')
        # NOTE: The syntax is -n := and not -n : -n =.
        omit_chars = arg.n or ''
        for c in omit_chars:
            if c in break_chars:
                break_chars.remove(c)

        # argv adjusted according to 'break_chars'.
        adjusted_argv = []
        for a in comp_argv:
            completion.AdjustArg(a, break_chars, adjusted_argv)

        if 'words' in var_names:
            state.SetArrayDynamic(self.mem, 'words', adjusted_argv)

        n = len(adjusted_argv)
        cur = adjusted_argv[-1]
        prev = '' if n < 2 else adjusted_argv[-2]

        if arg.s:
            if cur.startswith(
                    '--') and '=' in cur:  # Split into flag name and value
                prev, cur = cur.split('=', 1)
                split = 'true'
            else:
                split = 'false'
            # Do NOT set 'split' without -s.  Caller might not have declared it.
            # Also does not respect var_names, because we don't need it.
            state.SetStringDynamic(self.mem, 'split', split)

        if 'cur' in var_names:
            state.SetStringDynamic(self.mem, 'cur', cur)
        if 'prev' in var_names:
            state.SetStringDynamic(self.mem, 'prev', prev)
        if 'cword' in var_names:
            # Same weird invariant after adjustment
            state.SetStringDynamic(self.mem, 'cword', str(n - 1))

        return 0
示例#8
0
    def __call__(self, argv):
        arg_r = args.Reader(argv)
        arg = COMPLETE_SPEC.Parse(arg_r)
        # TODO: process arg.opt_changes
        #log('arg %s', arg)

        commands = arg_r.Rest()

        if arg.D:
            commands.append(
                '__fallback')  # if the command doesn't match anything
        if arg.E:
            commands.append('__first')  # empty line

        if not commands:
            self.comp_state.PrintSpecs()
            return 0

        comp_opts = completion.Options(arg.opt_changes)
        user_spec = _BuildUserSpec(argv, arg, comp_opts, self.ex)
        for command in commands:
            self.comp_state.RegisterName(command, comp_opts, user_spec)

        patterns = []
        for pat in patterns:
            self.comp_state.RegisterGlob(pat, comp_opts, user_spec)

        return 0
示例#9
0
  def Run(self, cmd_val):
    # type: (cmd_value__Argv) -> int
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()  # skip 'hash'
    arg, i = HASH_SPEC.Parse(arg_r)

    rest = arg_r.Rest()
    if arg.r:
      if rest:
        raise args.UsageError('got extra arguments after -r')
      self.search_path.ClearCache()
      return 0

    status = 0
    if rest:
      for cmd in rest:  # enter in cache
        full_path = self.search_path.CachedLookup(cmd)
        if full_path is None:
          ui.Stderr('hash: %r not found', cmd)
          status = 1
    else:  # print cache
      commands = self.search_path.CachedCommands()
      commands.sort()
      for cmd in commands:
        print(cmd)

    return status
示例#10
0
  def Run(self, cmd_val):
    # type: (cmd_value__Assign) -> int
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()
    attrs = flag_spec.Parse('export_', arg_r)
    arg = arg_types.export_(attrs.attrs)
    #arg = attrs

    if arg.f:
      e_usage(
          "doesn't accept -f because it's dangerous.  "
          "(The code can usually be restructured with 'source')")

    if arg.p or len(cmd_val.pairs) == 0:
      return _PrintVariables(self.mem, cmd_val, attrs, True, builtin=_EXPORT)


    if arg.n:
      for pair in cmd_val.pairs:
        if pair.rval is not None:
          e_usage("doesn't accept RHS with -n", span_id=pair.spid)

        # NOTE: we don't care if it wasn't found, like bash.
        self.mem.ClearFlag(pair.var_name, state.ClearExport, scope_e.Dynamic)
    else:
      for pair in cmd_val.pairs:
        # NOTE: when rval is None, only flags are changed
        self.mem.SetVar(lvalue.Named(pair.var_name), pair.rval, scope_e.Dynamic,
                        flags=state.SetExport)

    return 0
示例#11
0
    def Run(self, cmd_val):
        # type: (cmd_value__Assign) -> int
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()
        arg, arg_index = EXPORT_SPEC.Parse(arg_r)

        if arg.f:
            raise args.UsageError(
                "doesn't accept -f because it's dangerous.  (The code can usually be restructured with 'source')"
            )

        positional = cmd_val.argv[arg_index:]
        if arg.n:
            for pair in cmd_val.pairs:
                if pair.rval is not None:
                    raise args.UsageError("doesn't accept RHS with -n",
                                          span_id=pair.spid)

                # NOTE: we don't care if it wasn't found, like bash.
                self.mem.ClearFlag(pair.lval.name, state.ClearExport,
                                   scope_e.Dynamic)
        else:
            for pair in cmd_val.pairs:
                # NOTE: when rval is None, only flags are changed
                self.mem.SetVar(pair.lval,
                                pair.rval,
                                scope_e.Dynamic,
                                flags=state.SetExport)

        return 0
示例#12
0
def _ParseCmdVal(spec, cmd_val):
    # type: (cmd_value__Argv) -> Tuple[args._Attributes, int]
    """For testing only
  """
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()  # move past the builtin name
    return spec.Parse(arg_r), arg_r.i
示例#13
0
    def __call__(self, cmd_val):
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()
        arg, arg_index = READONLY_SPEC.Parse(arg_r)

        for pair in cmd_val.pairs:
            if pair.rval is None:
                if arg.a:
                    rval = value.StrArray([])
                elif arg.A:
                    rval = value.AssocArray({})
                else:
                    rval = None
            else:
                rval = pair.rval

            if not _CheckType(rval, arg, self.errfmt, pair.spid):
                return 1

            # NOTE:
            # - when rval is None, only flags are changed
            # - dynamic scope because flags on locals can be changed, etc.
            self.mem.SetVar(pair.lval, rval, (var_flags_e.ReadOnly, ),
                            scope_e.Dynamic)

        return 0
示例#14
0
    def Run(self, cmd_val):
        # type: (cmd_value__Assign) -> int
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()
        arg, arg_index = READONLY_SPEC.Parse(arg_r)

        for pair in cmd_val.pairs:
            if pair.rval is None:
                if arg.a:
                    rval = value.MaybeStrArray([])  # type: value_t
                elif arg.A:
                    rval = value.AssocArray({})
                else:
                    rval = None
            else:
                rval = pair.rval

            if not _CheckType(rval, arg, self.errfmt, pair.spid):
                return 1

            # NOTE:
            # - when rval is None, only flags are changed
            # - dynamic scope because flags on locals can be changed, etc.
            self.mem.SetVar(pair.lval,
                            rval,
                            scope_e.Dynamic,
                            flags=state.SetReadOnly)

        return 0
示例#15
0
    def Run(self, cmd_val):
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()  # skip 'use'

        # TODO:
        # - Does shopt -s namespaces have to be on?
        #   - I don't think so?  It only affects 'procs', not funcs.

        arg = arg_r.Peek()

        # 'use bin' and 'use env' are for static analysis.  No-ops at runtime.
        if arg in ('bin', 'env'):
            return 0

        if arg == 'lib':  # OPTIONAL lib
            arg_r.Next()

        # Cosmetic: separator for 'use bin __ grep sed'.  Allowed for 'lib' to be
        # consistent.
        arg = arg_r.Peek()
        if arg == '__':  # OPTIONAL __
            arg_r.Next()

        # Now import everything.
        rest = arg_r.Rest()
        for path in rest:
            log('path %s', path)

        return 0
示例#16
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        argv = cmd_val.argv[1:]
        arg_r = args.Reader(argv)
        arg = COMPLETE_SPEC.Parse(arg_r)
        # TODO: process arg.opt_changes
        #log('arg %s', arg)

        commands = arg_r.Rest()

        if arg.D:
            commands.append(
                '__fallback')  # if the command doesn't match anything
        if arg.E:
            commands.append('__first')  # empty line

        if not commands:
            self.comp_lookup.PrintSpecs()
            return 0

        base_opts = dict(arg.opt_changes)
        try:
            user_spec = self.spec_builder.Build(argv, arg, base_opts)
        except error.Parse as e:
            # error printed above
            return 2
        for command in commands:
            self.comp_lookup.RegisterName(command, base_opts, user_spec)

        # TODO: Hook this up
        patterns = []  # type: List[str]
        for pat in patterns:
            self.comp_lookup.RegisterGlob(pat, base_opts, user_spec)

        return 0
示例#17
0
    def Run(self, cmd_val):
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()
        arg, _ = GETLINE_SPEC.Parse(arg_r)
        if arg.cstr:
            # TODO: implement it
            # returns error if it can't decode
            raise NotImplementedError()

        var_name, var_spid = arg_r.ReadRequired2('requires a variable name')

        if var_name.startswith(':'):  # optional : sigil
            var_name = var_name[1:]

        next_arg, next_spid = arg_r.Peek2()
        if next_arg is not None:
            raise error.Usage('got extra argument', span_id=next_spid)

        line = _ReadLine()
        if len(line) == 0:  # EOF
            return 1

        if not arg.end:
            if line.endswith('\r\n'):
                line = line[:-2]
            elif line.endswith('\n'):
                line = line[:-1]

        self.mem.SetVar(sh_lhs_expr.Name(var_name), value.Str(line),
                        scope_e.LocalOnly)
        return 0
示例#18
0
def ParseLikeEcho(spec_name, cmd_val):
    # type: (str, cmd_value__Argv) -> Tuple[args._Attributes, args.Reader]
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()  # move past the builtin name

    spec = FLAG_SPEC[spec_name]
    return args.ParseLikeEcho(spec, arg_r), arg_r
示例#19
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()

        # NOTE: If first char is a colon, error reporting is different.  Alpine
        # might not use that?
        spec_str = arg_r.ReadRequired('requires an argspec')

        var_name, var_spid = arg_r.ReadRequired2(
            'requires the name of a variable to set')

        spec = self.spec_cache.get(spec_str)
        if spec is None:
            spec = _ParseOptSpec(spec_str)
            self.spec_cache[spec_str] = spec

        user_argv = self.mem.GetArgv() if arg_r.AtEnd() else arg_r.Rest()
        #util.log('user_argv %s', user_argv)
        status, flag_char = _GetOpts(spec, user_argv, self.my_state,
                                     self.errfmt)

        if match.IsValidVarName(var_name):
            state.SetStringDynamic(self.mem, var_name, flag_char)
        else:
            # NOTE: The builtin has PARTIALLY set state.  This happens in all shells
            # except mksh.
            raise error.Usage('got invalid variable name %r' % var_name,
                              span_id=var_spid)
        return status
示例#20
0
def ParseOilCmdVal(spec_name, cmd_val):
    # type: (str, cmd_value__Argv) -> Tuple[args._Attributes, args.Reader]
    """Parse argv using a given FlagSpecAndMore."""
    arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
    arg_r.Next()  # move past the builtin name

    spec = OIL_SPEC[spec_name]
    return args.ParseOil(spec, arg_r), arg_r
示例#21
0
    def __call__(self, arg_vec):
        if self.exec_opts.simple_echo:
            arg_r = args.Reader(arg_vec.strs, spids=arg_vec.spids)
            arg_r.Next()  # skip 'echo'

            arg, _ = OIL_ECHO_SPEC.Parse(arg_r)
            #print(arg)

            i = 0
            while not arg_r.AtEnd():
                if i != 0:
                    sys.stdout.write(arg.sep)
                s = arg_r.Peek()
                sys.stdout.write(s)
                arg_r.Next()
                i += 1

            if arg.n:
                pass
            elif arg.end:
                sys.stdout.write(arg.end)

            return 0

        argv = arg_vec.strs[1:]
        arg, arg_index = ECHO_SPEC.ParseLikeEcho(argv)
        argv = argv[arg_index:]
        if arg.e:
            new_argv = []
            for a in argv:
                parts = []
                for id_, value in match.ECHO_LEXER.Tokens(a):
                    p = word_compile.EvalCStringToken(id_, value)

                    # Unusual behavior: '\c' prints what is there and aborts processing!
                    if p is None:
                        new_argv.append(''.join(parts))
                        for i, a in enumerate(new_argv):
                            if i != 0:
                                sys.stdout.write(' ')  # arg separator
                            sys.stdout.write(a)
                        return 0  # EARLY RETURN

                    parts.append(p)
                new_argv.append(''.join(parts))

            # Replace it
            argv = new_argv

        #log('echo argv %s', argv)
        for i, a in enumerate(argv):
            if i != 0:
                sys.stdout.write(' ')  # arg separator
            sys.stdout.write(a)
        if not arg.n:
            sys.stdout.write('\n')

        return 0
    def ParseCmdVal(self, cmd_val):
        # type: (cmd_value__Argv) -> Tuple[args._Attributes, int]
        """Used by builtins that don't need arg_r.

    Note: It might be more flexible to return arg_r instead if i.  Then they
    can call arg_r.Rest(), etc.

    TODO: Remove in favor of ParseCmdVal above
    """
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()  # move past the builtin name
        return self.Parse(arg_r), arg_r.i
示例#23
0
  def __call__(self, arg_vec):
    argv = arg_vec.strs[1:]
    arg_r = args.Reader(argv)
    arg = COMPOPT_SPEC.Parse(arg_r)

    if not self.comp_state.currently_completing:  # bash also checks this.
      self.errfmt.Print('compopt: not currently executing a completion function')
      return 1

    self.comp_state.dynamic_opts.update(arg.opt_changes)
    #log('compopt: %s', arg)
    #log('compopt %s', base_opts)
    return 0
示例#24
0
def main(argv):
  arg_r = args.Reader(argv)
  arg_r.Next()  # skip argv[0]
  arg = args.Parse(SPEC, arg_r)

  if not arg.f:
    stderr_line("readlink: -f must be passed")
    return 1
  for path in arg_r.Rest():
    res = libc.realpath(path)
    if res is None:
      return 1
    print(res)
  return 0
示例#25
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        argv = cmd_val.argv[1:]
        arg_r = args.Reader(argv)
        arg = COMPOPT_SPEC.Parse(arg_r)

        if not self.comp_state.currently_completing:  # bash also checks this.
            self.errfmt.Print(
                'compopt: not currently executing a completion function')
            return 1

        self.comp_state.dynamic_opts.update(arg.opt_changes)
        #log('compopt: %s', arg)
        #log('compopt %s', base_opts)
        return 0
示例#26
0
    def __call__(self, cmd_val):
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        #arg_r.Next()  # skip 'use'

        # TODO: GetVar() and print them

        if cmd_val.block:
            # TODO: flatten value.{Str,Obj} into a flat dict?
            namespace = self.ex.EvalBlock(cmd_val.block)

            # TODO: Use JSON library
            from pprint import pprint
            pprint(namespace, indent=2)

        return 0
    def Run(self, cmd_val):
        argv = cmd_val.argv[1:]
        arg_r = args.Reader(argv)
        arg = COMPGEN_SPEC.Parse(arg_r)

        if arg_r.AtEnd():
            to_complete = ''
        else:
            to_complete = arg_r.Peek()
            arg_r.Next()
            # bash allows extra arguments here.
            #if not arg_r.AtEnd():
            #  raise error.Usage('Extra arguments')

        matched = False

        base_opts = dict(arg.opt_changes)
        try:
            user_spec = self.spec_builder.Build(argv, arg, base_opts)
        except error.Parse as e:
            # error printed above
            return 2

        # NOTE: Matching bash in passing dummy values for COMP_WORDS and COMP_CWORD,
        # and also showing ALL COMPREPLY reuslts, not just the ones that start with
        # the word to complete.
        matched = False
        comp = completion.Api()
        comp.Update(first='compgen',
                    to_complete=to_complete,
                    prev='',
                    index=-1)
        try:
            for m, _ in user_spec.Matches(comp):
                matched = True
                print(m)
        except error.FatalRuntime:
            # - DynamicWordsAction: We already printed an error, so return failure.
            return 1

        # - ShellFuncAction: We do NOT get FatalRuntimeError.  We printed an error
        # in the executor, but RunFuncForCompletion swallows failures.  See test
        # case in builtin-completion.test.sh.

        # TODO:
        # - need to dedupe results.

        return 0 if matched else 1
示例#28
0
    def __call__(self, argv):
        arg_r = args.Reader(argv)
        arg = COMPOPT_SPEC.Parse(arg_r)

        if not self.comp_state.currently_completing:
            # bash checks this.
            util.error(
                'compopt: not currently executing a completion function')
            return 1

        for name, b in arg.opt_changes:
            #log('setting %s = %s', name, b)
            self.comp_state.current_opts.Set(name, b)
        #log('compopt: %s', arg)
        #log('compopt %s', comp_opts)
        return 0
示例#29
0
    def Run(self, cmd_val):
        # type: (cmd_value__Argv) -> int
        arg_r = args.Reader(cmd_val.argv, spids=cmd_val.arg_spids)
        arg_r.Next()

        # NOTE: If first char is a colon, error reporting is different.  Alpine
        # might not use that?
        spec_str = arg_r.ReadRequired('requires an argspec')

        var_name, var_spid = arg_r.ReadRequired2(
            'requires the name of a variable to set')

        try:
            spec = self.spec_cache[spec_str]
        except KeyError:
            spec = _ParseOptSpec(spec_str)
            self.spec_cache[spec_str] = spec

        # These errors are fatal errors, not like the builtin exiting with code 1.
        # Because the invariants of the shell have been violated!
        v = self.mem.GetVar('OPTIND')
        if v.tag != value_e.Str:
            e_die('OPTIND should be a string, got %r', v)
        try:
            optind = int(v.s)
        except ValueError:
            e_die("OPTIND doesn't look like an integer, got %r", v.s)

        user_argv = arg_r.Rest() or self.mem.GetArgv()
        #util.log('user_argv %s', user_argv)
        status, opt_char, optarg, optind = _GetOpts(spec, user_argv, optind,
                                                    self.errfmt)

        # Bug fix: bash-completion uses a *local* OPTIND !  Not global.
        state.SetStringDynamic(self.mem, 'OPTARG', optarg)
        state.SetStringDynamic(self.mem, 'OPTIND', str(optind))
        if match.IsValidVarName(var_name):
            state.SetStringDynamic(self.mem, var_name, opt_char)
        else:
            # NOTE: The builtin has PARTIALLY filed.  This happens in all shells
            # except mksh.
            raise error.Usage('got invalid variable name %r' % var_name,
                              span_id=var_spid)
        return status
示例#30
0
文件: osh_eval.py 项目: o11c/oil
def main(argv):
    # type: (List[str]) -> int
    loader = pyutil.GetResourceLoader()
    login_shell = False

    environ = {}  # type: Dict[str, str]
    environ['PWD'] = posix.getcwd()

    arg_r = args.Reader(argv, spids=[runtime.NO_SPID] * len(argv))

    try:
        status = pure.Main('osh', arg_r, environ, login_shell, loader, None)
        return status
    except error.Usage as e:
        #builtin.Help(['oil-usage'], util.GetResourceLoader())
        log('oil: %s', e.msg)
        return 2
    except RuntimeError as e:
        if 0:
            import traceback
            traceback.print_exc()
        # NOTE: The Python interpreter can cause this, e.g. on stack overflow.
        # f() { f; }; f will cause this
        msg = e.message  # type: str
        stderr_line('osh fatal error: %s', msg)
        return 1

    # Note: This doesn't happen in C++.
    except KeyboardInterrupt:
        print('')
        return 130  # 128 + 2

    except OSError as e:
        if 0:
            import traceback
            traceback.print_exc()

        # test this with prlimit --nproc=1 --pid=$$
        stderr_line('osh I/O error: %s', pyutil.strerror_OS(e))
        return 2  # dash gives status 2

    except IOError as e:  # duplicate of above because CPython is inconsistent
        stderr_line('osh I/O error: %s', pyutil.strerror_IO(e))
        return 2