Permalink
Browse files

Implement [ -t 1 ], which calls isatty() on a fd.

abuild uses this.

Also add the ability to return 2 for a usage error.
  • Loading branch information...
Andy Chu
Andy Chu committed Jan 8, 2018
1 parent 5ea4327 commit fa7ea7662288f32be1ed39b1cb50e0a07afd7ed7
Showing with 40 additions and 5 deletions.
  1. +12 −0 core/expr_eval.py
  2. +2 −2 core/id_kind.py
  3. +10 −2 core/test_builtin.py
  4. +4 −1 core/util.py
  5. +12 −0 spec/builtin-test.test.sh
View
@@ -477,6 +477,7 @@ def Eval(self, node):
# Now dispatch on arg type
arg_type = BOOL_OPS[op_id] # could be static in the LST?
if arg_type == OperandType.Path:
# Only use lstat if we're testing for a symlink.
if op_id in (Id.BoolUnary_h, Id.BoolUnary_L):
@@ -522,6 +523,17 @@ def Eval(self, node):
raise NotImplementedError(op_id)
if arg_type == OperandType.Other:
if op_id == Id.BoolUnary_t:
try:
fd = int(s)
except ValueError:
# TODO: Need location information of [
e_die('Invalid file descriptor %r', s)
return os.isatty(fd)
raise NotImplementedError(op_id)
raise NotImplementedError(arg_type)
if node.tag == bool_expr_e.BoolBinary:
View
@@ -412,8 +412,8 @@ def _AddKinds(spec):
# Shared between [[ and test/[.
_UNARY_STR_CHARS = 'zn' # -z -n
_UNARY_OTHER_CHARS = 'ovR' # -o is overloaded
_UNARY_PATH_CHARS = 'abcdefghLprsStuwxOGN' # -a is overloaded
_UNARY_OTHER_CHARS = 'otvR' # -o is overloaded
_UNARY_PATH_CHARS = 'abcdefghLprsSuwxOGN' # -a is overloaded
_BINARY_PATH = ['ef', 'nt', 'ot']
_BINARY_INT = ['eq', 'ne', 'gt', 'ge', 'lt', 'le']
View
@@ -1,4 +1,5 @@
#!/usr/bin/python
from __future__ import print_function
"""
test_builtin.py
"""
@@ -186,7 +187,14 @@ def Test(argv, need_right_bracket):
word_ev = _WordEvaluator()
bool_ev = expr_eval.BoolEvaluator(mem, exec_opts, word_ev)
b = bool_ev.Eval(bool_node)
try:
b = bool_ev.Eval(bool_node)
except util.FatalRuntimeError as e:
# e.g. [ -t xxx ]
# TODO: Printing the location would be nice.
print('test: %s' % e.UserErrorString(), file=sys.stderr)
return 2
status = 0 if b else 1
return status
@@ -196,6 +204,6 @@ def Test(argv, need_right_bracket):
e = _StringWordEmitter('-z X -o -z Y -a -z X'.split())
while True:
w = e.ReadWord(None)
print w
print(w)
if w.id == Id.Eof_Real:
break
View
@@ -74,7 +74,10 @@ class ParseError(_ErrorWithLocation):
class FatalRuntimeError(_ErrorWithLocation):
"""Used in the evaluators."""
"""Used in the evaluators.
Also used in test builtin for invalid argument.
"""
pass
View
@@ -220,3 +220,15 @@ dangling
dangling
dangling is not file
## END
### -t 1 for stdout
# There isn't way to get a terminal in the test environment?
[ -t 1 ]
echo status=$?
## stdout: status=1
### [ -t invalid ]
[ -t invalid ]
echo status=$?
## stdout: status=2
## BUG bash stdout: status=1

0 comments on commit fa7ea76

Please sign in to comment.