def Eval(self, node): # type: (command_t) -> None UP_node = node with tagswitch(node) as case: if case(command_e.Simple): node = cast(command__Simple, UP_node) # Need splitter for this. if 0: cmd_val = self.word_ev.EvalWordSequence2(node.words, allow_assign=True) for arg in cmd_val.argv: log('arg %s', arg) for w in node.words: val = self.word_ev.EvalWordToString(w) # TODO: how to print repr() in C++? log('arg %d', val.tag_()) elif case(command_e.DParen): node = cast(command__DParen, UP_node) a = self.arith_ev.Eval(node.child) # TODO: how to print repr() in C++? log('arith val %d', a.tag_()) else: log('Unhandled node %s', NewStr(command_str(node.tag_())))
def RunCommandSub(self, node): # type: (command_t) -> str # Hack for weird $(<file) construct if node.tag_() == command_e.Simple: simple = cast(command__Simple, node) # Detect '< file' if (len(simple.words) == 0 and len(simple.redirects) == 1 and simple.redirects[0].op.id == Id.Redir_Less): # change it to __cat < file # note: cmd_eval.py _Dispatch works around lack of spid tok = Token(Id.Lit_Chars, runtime.NO_SPID, '__cat') cat_word = compound_word([tok]) # MUTATE the command.Simple node. This will only be done the first # time in the parent process. simple.words.append(cat_word) p = self._MakeProcess(node, inherit_errexit=self.exec_opts.inherit_errexit()) r, w = posix.pipe() p.AddStateChange(process.StdoutToPipe(r, w)) _ = p.Start() #log('Command sub started %d', pid) chunks = [] # type: List[str] posix.close(w) # not going to write while True: byte_str = posix.read(r, 4096) if len(byte_str) == 0: break chunks.append(byte_str) posix.close(r) status = p.Wait(self.waiter) # OSH has the concept of aborting in the middle of a WORD. We're not # waiting until the command is over! if self.exec_opts.more_errexit(): if self.exec_opts.errexit() and status != 0: raise error.ErrExit('Command sub exited with status %d (%r)', status, NewStr(command_str(node.tag_()))) else: # Set a flag so we check errexit at the same time as bash. Example: # # a=$(false) # echo foo # no matter what comes here, the flag is reset # # Set ONLY until this command node has finished executing. # HACK: move this self.cmd_ev.check_command_sub_status = True self.mem.SetLastStatus(status) # 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 ''.join(chunks).rstrip('\n')
def CommandType(cmd): # type: (command_t) -> str """For displaying commands in the UI.""" # Displays 'value.MaybeStrArray' for now, maybe change it. return NewStr(command_str(cmd.tag_()))