Permalink
Browse files

Implement the 'type' builtin (just the '-t' case), with tests.

Used by setup.sh in Nix.

Addresses issue #26.
  • Loading branch information...
Andy Chu
Andy Chu committed Sep 5, 2017
1 parent bbe5808 commit 5aaffbc2aa7fd9d539f068c6b51be88a557d527d
Showing with 115 additions and 2 deletions.
  1. +59 −1 core/builtin.py
  2. +4 −0 core/cmd_exec.py
  3. +19 −1 osh/lex.py
  4. +27 −0 spec/builtin-type.test.sh
  5. +6 −0 test/spec.sh
View
@@ -58,7 +58,7 @@
TRUE FALSE
COLON
TEST BRACKET
HELP
TYPE HELP
""".split())
@@ -197,6 +197,9 @@ def Resolve(argv0):
elif argv0 == "[":
return EBuiltin.BRACKET
elif argv0 == "type":
return EBuiltin.TYPE
elif argv0 == "help":
return EBuiltin.HELP
@@ -646,6 +649,61 @@ def Unset(argv, mem, funcs):
return 0
TYPE_SPEC = _Register('type')
TYPE_SPEC.ShortFlag('-t')
def Type(argv, funcs, path_val):
arg, i = TYPE_SPEC.Parse(argv)
if path_val.tag == value_e.Str:
path_list = path_val.s.split(':')
else:
path_list = [] # treat as empty path
status = 0
if not arg.t:
util.warn("*** 'type' builtin called without -t ***")
status = 1
# Keep going anyway
for name in argv[i:]:
if name in funcs:
print('function')
continue
if Resolve(name) != EBuiltin.NONE:
print('builtin')
continue
if ResolveSpecial(name) != EBuiltin.NONE:
print('builtin')
continue
if lex.IsOtherBuiltin(name):
print('builtin')
continue
if lex.IsKeyword(name):
print('keyword')
continue
# Now look for files.
found = False
for path_dir in path_list:
full_path = os.path.join(path_dir, name)
if os.path.exists(full_path):
print('file')
found = True
break
if found:
continue
# Name not found. Nothing printed, but status is 1.
#log('%r not found', name)
status = 1
return status
def Trap(argv, traps):
# TODO: register trap
View
@@ -297,6 +297,10 @@ def _RunBuiltin(self, builtin_id, argv):
elif builtin_id == EBuiltin.BRACKET:
status = test_builtin.Test(argv, True) # need_right_bracket
elif builtin_id == EBuiltin.TYPE:
path = self.mem.GetVar('PATH')
status = builtin.Type(argv, self.funcs, path)
elif builtin_id == EBuiltin.HELP:
loader = util.GetResourceLoader()
status = builtin.Help(argv, loader)
View
@@ -181,7 +181,11 @@
C('elif', Id.KW_Elif),
C('function', Id.KW_Function),
C('time', Id.KW_Time),
]
# These are treated like builtins in bash, but keywords in OSH. However, we
# main compatibility with bash for the 'type' builtin.
_MORE_KEYWORDS = [
C('declare', Id.Assign_Declare),
C('local', Id.Assign_Local),
C('readonly', Id.Assign_Readonly),
@@ -191,13 +195,27 @@
C('return', Id.ControlFlow_Return),
]
_TYPE_KEYWORDS = set(name for _, name, _ in _KEYWORDS)
_TYPE_KEYWORDS.add('{') # not in our lexer list
_TYPE_BUILTINS = set(name for _, name, _ in _MORE_KEYWORDS)
def IsOtherBuiltin(name):
return name in _TYPE_BUILTINS
def IsKeyword(name):
return name in _TYPE_KEYWORDS
# These two can must be recognized in the OUTER state, but can't nested within
# [[.
# Keywords have to be checked before _UNQUOTED so we get <KW_If "if"> instead
# of <Lit_Chars "if">.
LEXER_DEF[LexMode.OUTER] = [
C('((', Id.Op_DLeftParen), # not allowed within [[
] + _KEYWORDS + _UNQUOTED
] + _KEYWORDS + _MORE_KEYWORDS + _UNQUOTED
# DBRACKET: can be like OUTER, except:
# - Don't really need redirects either... Redir_Less could be Op_Less
View
@@ -0,0 +1,27 @@
#!/bin/bash
#
# Bash implements type -t.
#
# NOTE: Aliases don't work in batch mode! Interactive only.
### type -t builtin -> function
f() { echo hi; }
type -t f
# stdout-json: "function\n"
### type -t builtin -> builtin
type -t echo read : [ declare local break continue
# stdout-json: "builtin\nbuiltin\nbuiltin\nbuiltin\nbuiltin\nbuiltin\nbuiltin\nbuiltin\n"
### type -t builtin -> keyword
type -t for time ! fi do {
# stdout-json: "keyword\nkeyword\nkeyword\nkeyword\nkeyword\nkeyword\n"
### type -t builtin -> file
type -t find xargs
# stdout-json: "file\nfile\n"
### type -t builtin -> not found
type -t echo ZZZ find =
echo status=$?
# stdout-json: "builtin\nfile\nstatus=1\n"
View
@@ -262,6 +262,12 @@ builtin-vars() {
${REF_SHELLS[@]} $OSH "$@"
}
# Bash impleement type -t, but no other shell does. For Nix.
builtin-type() {
sh-spec spec/builtin-type.test.sh \
$BASH $OSH "$@"
}
builtins-special() {
sh-spec spec/builtins-special.test.sh --osh-failures-allowed 3 \
${REF_SHELLS[@]} $OSH "$@"

0 comments on commit 5aaffbc

Please sign in to comment.