Permalink
Browse files

Fix some error handling in the interactive loop.

Still have more to do.
  • Loading branch information...
Andy Chu
Andy Chu committed Aug 20, 2018
1 parent 901e603 commit 315411784969d12721b67687fac5bf7f6022665b
Showing with 30 additions and 7 deletions.
  1. +15 −5 bin/oil.py
  2. +12 −2 core/process.py
  3. +3 −0 osh/cmd_parse.py
View
@@ -95,7 +95,7 @@ def _tlog(msg):
_tlog('after imports')
def InteractiveLoop(opts, ex, c_parser, w_parser, line_reader):
def InteractiveLoop(opts, ex, c_parser, w_parser, line_reader, arena):
if opts.show_ast:
ast_f = fmt.DetectConsoleOutput(sys.stdout)
else:
@@ -113,19 +113,25 @@ def InteractiveLoop(opts, ex, c_parser, w_parser, line_reader):
raise RuntimeError('Failed parse: %s' % c_parser.Error())
c_id = word.CommandId(w)
if c_id == Id.Op_Newline:
print('nothing to execute')
#print('nothing to execute')
pass
elif c_id == Id.Eof_Real:
print('EOF')
break
else:
node = c_parser.ParseCommandLine()
# Failed parse.
# TODO: Need an error for an empty command, which we ignore? GetLine
# could do that in the first position?
# ParseSimpleCommand fails with '\n' token?
if not node:
# TODO: PrintError here
raise RuntimeError('failed parse: %s' % c_parser.Error())
e = c_parser.Error()
# NOTE: This is a bit verbose.
ui.PrintErrorStack(e, arena, sys.stderr)
w_parser.Reset()
c_parser.Reset()
continue
if ast_f:
ast_lib.PrettyPrint(node)
@@ -305,14 +311,18 @@ def OshMain(argv0, argv, login_shell):
completion.Init(pool, builtin.BUILTIN_DEF, mem, funcs, comp_lookup,
status_out, ev)
return InteractiveLoop(opts, ex, c_parser, w_parser, line_reader)
return InteractiveLoop(opts, ex, c_parser, w_parser, line_reader, arena)
else:
# Parse the whole thing up front
#print('Parsing file')
_tlog('ParseWholeFile')
# TODO: Do I need ParseAndEvalLoop? How is it different than
# InteractiveLoop?
# TODO: InteractiveLoop above should use the same form of error handling.
# ParseWholeFile vs. ParseCommandLine
# I think ParseCommandLine should just be a loop
try:
node = c_parser.ParseWholeFile()
except util.ParseError as e:
View
@@ -312,15 +312,25 @@ def Run(self):
def ExecExternalProgram(argv, environ):
"""
"""Execute a program and exit this process.
Called by:
ls /
exec ls /
( ls / )
"""
# TODO: If there is an error, like the file isn't executable, then we should
# exit, and the parent will reap it. Should it capture stderr?
try:
os.execvpe(argv[0], argv, environ)
except OSError as e:
log('Unexpected error in execvpe(%r, %r, ...): %s', argv[0], argv, e)
# Command not found means 127. TODO: Are there other cases?
# TODO:
# - Make this error look better.
# - What about permission errors?
# Command not found means 127.
sys.exit(127)
# no return
View
@@ -1537,6 +1537,9 @@ def ParseWholeFile(self):
TODO: This should be turned into a Parse and Execute loop, freeing arenas
if they don't contain functions.
osh -n is a different loop -- it parses each line one at a time, but
doesn't execute!
"""
if not self._NewlineOk(): return None

0 comments on commit 3154117

Please sign in to comment.