def EvalWordSequence2(self, words): """Turns a list of Words into a list of strings. Unlike the EvalWord*() methods, it does globbing. Args: words: list of Word instances Returns: argv: list of string arguments, or None if there was an eval error """ # Parse time: # 1. brace expansion. TODO: Do at parse time. # 2. Tilde detection. DONE at parse time. Only if Id.Lit_Tilde is the # first WordPart. # # Run time: # 3. tilde sub, var sub, command sub, arith sub. These are all # "concurrent" on WordParts. (optional process sub with <() ) # 4. word splitting. Can turn this off with a shell option? Definitely # off for oil. # 5. globbing -- several exec_opts affect this: nullglob, safeglob, etc. #log('W %s', words) arg_vec = arg_vector() strs = arg_vec.strs n = 0 for w in words: part_vals = [] self._EvalWordToParts(w, False, part_vals) # not double quoted if 0: log('') log('part_vals after _EvalWordToParts:') for entry in part_vals: log(' %s', entry) frames = _MakeWordFrames(part_vals) if 0: log('') log('frames after _MakeWordFrames:') for entry in frames: log(' %s', entry) # Now each frame will append zero or more args. for frame in frames: self._EvalWordFrame(frame, strs) # Fill in spids parallel to strs. n_next = len(strs) spid = word.LeftMostSpanForWord(w) for _ in xrange(n_next - n): arg_vec.spids.append(spid) n = n_next #log('ARGV %s', argv) return arg_vec
def testStringWordEmitter(self): # Test argv = '-z X -o -z Y -a -z X'.split() arg_vec = arg_vector(argv, [0] * len(argv)) e = builtin_bracket._StringWordEmitter(arg_vec) while True: w = e.ReadWord(None) print(w) if w.id == Id.Eof_Real: break
def _RunSimpleCommand(self, cmd_val, fork_external): """Private interface to run a simple command (including assignment).""" if cmd_val.tag == cmd_value_e.Argv: arg_vec = arg_vector(cmd_val.argv, cmd_val.arg_spids) return self.RunSimpleCommand(arg_vec, fork_external) elif cmd_val.tag == cmd_value_e.Assign: return self._RunAssignBuiltin(cmd_val) else: raise AssertionError
def _ExtProc(argv): arg_vec = arg_vector(argv, [0] * len(argv)) argv0_path = None for path_entry in ['/bin', '/usr/bin']: full_path = os.path.join(path_entry, argv[0]) if os.path.exists(full_path): argv0_path = full_path break if not argv0_path: argv0_path = argv[0] # fallback that tests failure case return Process(ExternalThunk(_EXT_PROG, argv0_path, arg_vec, {}), _JOB_STATE)
def _Exec(self, arg_vec): # Apply redirects in this shell. # NOTE: Redirects were processed earlier. if len(arg_vec.strs) == 1: return 0 environ = self.mem.GetExported() cmd = arg_vec.strs[1] argv0_path = self.search_path.CachedLookup(cmd) if argv0_path is None: self.errfmt.Print('exec: %r not found', cmd, span_id=arg_vec.spids[1]) sys.exit(127) # exec never returns # shift off 'exec' arg_vec2 = arg_vector(arg_vec.strs[1:], arg_vec.spids[1:]) self.ext_prog.Exec(argv0_path, arg_vec2, environ) # NEVER RETURNS
def __call__(self, arg_vec, fork_external): arg, arg_index = COMMAND_SPEC.ParseVec(arg_vec) if arg.v: status = 0 names = arg_vec.strs[arg_index:] for kind, arg in _ResolveNames(names, self.funcs, self.aliases, self.search_path): if kind is None: status = 1 # nothing printed, but we fail else: # This is for -v, -V is more detailed. print(arg) return status arg_vec2 = arg_vector(arg_vec.strs[1:], arg_vec.spids[1:]) # shift by one # 'command ls' suppresses function lookup. return self.ex.RunSimpleCommand(arg_vec2, fork_external, funcs=False)
def _ExtProc(argv): arg_vec = arg_vector(argv, [0] * len(argv)) return Process(ExternalThunk(_EXT_PROG, arg_vec, {}))
def _MakeArgVector(argv): argv = [''] + argv # add dummy since arg_vec includes argv[0] # no location info return arg_vector(argv, [runtime.NO_SPID] * len(argv))
def _MakeArgVector(argv): argv = [''] + argv # add dummy since arg_vec includes argv[0] # no location info return arg_vector(argv, [const.NO_INTEGER] * len(argv))
def _RunBuiltinAndRaise(self, builtin_id, arg_vec, fork_external): """ Raises: args.UsageError """ # Shift one arg. Builtins don't need to know their own name. argv = arg_vec.strs[1:] # Most builtins dispatch with a dictionary builtin_func = self.builtins.get(builtin_id) if builtin_func is not None: status = builtin_func(arg_vec) # Some builtins "belong" to the executor. elif builtin_id == builtin_e.EXEC: status = self._Exec(arg_vec) # may never return # But if it returns, then we want to permanently apply the redirects # associated with it. self.fd_state.MakePermanent() elif builtin_id == builtin_e.EVAL: status = self._Eval(arg_vec) elif builtin_id in (builtin_e.SOURCE, builtin_e.DOT): status = self._Source(arg_vec) elif builtin_id == builtin_e.COMMAND: # TODO: How do we handle fork_external? It doesn't fit the common # signature. We also don't handle 'command local', etc. b = builtin.Command(self, self.funcs, self.aliases, self.search_path) status = b(arg_vec, fork_external) elif builtin_id == builtin_e.BUILTIN: # NOTE: uses early return style if not argv: return 0 # this could be an error in strict mode? name = arg_vec.strs[1] # Run regular builtin or special builtin to_run = builtin.Resolve(name) if to_run == builtin_e.NONE: to_run = builtin.ResolveSpecial(name) if to_run == builtin_e.NONE: span_id = arg_vec.spids[1] if builtin.ResolveAssign(name) != builtin_e.NONE: # NOTE: There's a similar restriction for 'command' self.errfmt.Print("Can't run assignment builtin recursively", span_id=span_id) else: self.errfmt.Print("%r isn't a shell builtin", span_id=span_id) return 1 arg_vec2 = arg_vector(arg_vec.strs[1:], arg_vec.spids[1:]) status = self._RunBuiltinAndRaise(to_run, arg_vec2, fork_external) else: raise AssertionError('Unhandled builtin: %s' % builtin_id) assert isinstance(status, int) return status