Permalink
Browse files

Split out builtin-io.test.sh for echo and read.

Preparing to implement backslash escapes.  Both echo and read know about
backslashes.

Also:

- Begin tests that show off xtrace and PS4
- Add shell options and environment variables to the quick ref.  Allow
  topics that are upper case.
- Minor tweaks to comments.
  • Loading branch information...
Andy Chu
Andy Chu committed Dec 26, 2017
1 parent 6a45bd9 commit 7fd097bc95b453074f85db45619c7d7a1d8e5c56
Showing with 205 additions and 83 deletions.
  1. +2 −2 build/quick_ref.py
  2. +2 −2 core/cmd_exec.py
  3. +13 −2 doc/osh-quick-ref-toc.txt
  4. +23 −0 gold/lineno.sh
  5. +78 −0 gold/xtrace1.sh
  6. +81 −0 spec/builtin-io.test.sh
  7. +0 −76 spec/builtins.test.sh
  8. +6 −1 test/spec.sh
View
@@ -14,10 +14,10 @@
CAPS_RE = re.compile(r'^[A-Z ]+$')
# 1. Optional X, then a SINGLE space
# 2. lower-case topic
# 2. lower-case or upper-case topic
# 3. Optional: A SINGLE space, then punctuation
TOPIC_RE = re.compile(r'\b(X[ ])?([a-z\-]+)([ ]\S+)?', re.VERBOSE)
TOPIC_RE = re.compile(r'\b(X[ ])?([a-zA-Z\-]+)([ ]\S+)?', re.VERBOSE)
# Sections have alphabetical characters, spaces, and '/' for I/O. They are
# turned into anchors.
View
@@ -125,7 +125,7 @@ def __init__(self, mem, status_lines, funcs, completion, comp_lookup,
self.arith_ev = expr_eval.ArithEvaluator(mem, exec_opts, self.ev)
self.bool_ev = expr_eval.BoolEvaluator(mem, exec_opts, self.ev)
self.traps = {}
self.traps = {} # signal/hook -> LST node
self.fd_state = process.FdState()
self.dir_stack = state.DirStack()
@@ -618,7 +618,7 @@ def _Dispatch(self, node, fork_external):
if node.tag == command_e.SimpleCommand:
check_errexit = True
# PROBLEM: We want to log argv in 'xtrace' mode, but we may have already
# redirected here, which screws up loggnig. For example, 'echo hi
# redirected here, which screws up logging. For example, 'echo hi
# >/dev/null 2>&1'. We want to evaluate argv and log it BEFORE applying
# redirects.
View
@@ -77,8 +77,19 @@ X [Unsupported] enable
SHELL OPTIONS
[Errors] nounset errexit pipefail
[Globbing] noglob failglob nullglob
[Debugging] xtrace X verbose
[Debugging] xtrace X verbose X extdebug
[Other] X noclobber
[Parsing] TODO
[OSH Strict] TODO
[OSH Strict] STRICT strict-control-flow
[OSH Sane] TODO
ENVIRONMENT VARIABLES
[Shell Options] X SHELLOPTS X BASHOPTS
[Process State] UID EUID
[cd] PWD OLDPWD
[getopts] OPTIND OPTARG
[read] REPLY
[Other] IFS
[Libaries] X RANDOM TODO:TIMESTAMP
View
@@ -0,0 +1,23 @@
#!/bin/bash
#
# Usage:
# ./lineno.sh <function name>
set -o nounset
set -o pipefail
set -o errexit
# https://unix.stackexchange.com/questions/355965/how-to-check-which-line-of-a-bash-script-is-being-executed
# This is different than LINENO, see gold/xtrace1.sh.
f(){ echo "${BASH_LINENO[-2]}"; }
echo next1
f
echo next2
f
echo next 3
f
View
@@ -0,0 +1,78 @@
#!/bin/bash
#
# Usage:
# ./xtrace1.sh <function name>
set -o nounset
set -o pipefail
set -o errexit
# Problem:
# - There is no indentation for function calls
# - There is no indication of the function call. It only traces simple
# commands. 'local' is also traced with the concrete value.
func() {
local arg=$1
echo "{ func $arg"
echo "func $arg }"
}
main() {
set -o xtrace
echo '{ main'
func main
echo 'main }'
# No indentation or increase in +
( func subshell)
# Now we change to ++
foo=$(func commandsub)
echo $foo
# Still +
func pipeline | wc -l
# Increase to three
foo=$(echo $(func commandsub))
echo $foo
# Call it recursively
$0 func dollar-zero
# Call it recursively with
export SHELLOPTS
$0 func dollar-zero-shellopts
echo
echo
echo
# OK this is useful.
# https://unix.stackexchange.com/questions/355965/how-to-check-which-line-of-a-bash-script-is-being-executed
PS4='+${LINENO}: '
func ps4
foo=$(func ps4-commandsub)
echo foo
}
my-ps4() {
for i in {1..3}; do
echo -n $i
done
}
# The problem with this is you don't want to fork the shell for every line!
call-func-in-ps4() {
set -x
PS4='[$(my-ps4)] '
echo one
echo two
}
"$@"
View
@@ -0,0 +1,81 @@
#!/bin/bash
#
# echo, read
# later: perhaps mapfile, etc.
### echo dashes
echo -
echo --
echo ---
# stdout-json: "-\n--\n---\n"
### echo -en
echo -en 'abc\ndef\n'
# stdout-json: "abc\ndef\n"
# N-I dash stdout-json: "-en abc\ndef\n\n"
### echo -ez (invalid flag)
# bash differs from the other two shells, but its behavior is possibly more
# sensible, if you're going to ignore the error. It doesn't make sense for the
# 'e' to mean 2 different things simultaneously: flag and literal to be
# printed.
echo -ez 'abc\n'
# stdout-json: "-ez abc\\n\n"
# BUG dash/mksh stdout-json: "-ez abc\n\n"
### Read builtin
# NOTE: there are TABS below
read x <<EOF
A B C D E
FG
EOF
echo "[$x]"
# stdout: [A B C D E]
# status: 0
### Read builtin with no newline.
# This is odd because the variable is populated successfully. OSH/Oil might
# need a separate put reading feature that doesn't use IFS.
echo -n ZZZ | { read x; echo $?; echo $x; }
# stdout-json: "1\nZZZ\n"
# status: 0
### Read builtin with multiple variables
# NOTE: there are TABS below
read x y z <<EOF
A B C D E
FG
EOF
echo "$x/$y/$z"
# stdout: A/B/C D E
# status: 0
### Read builtin with not enough variables
set -o errexit
set -o nounset # hm this doesn't change it
read x y z <<EOF
A B
EOF
echo /$x/$y/$z/
# stdout: /A/B//
# status: 0
### get umask
umask | grep '[0-9]\+' # check for digits
# status: 0
### Read -n (with $REPLY)
echo 12345 > $TMP/readn.txt
read -n 4 x < $TMP/readn.txt
read -n 2 < $TMP/readn.txt # Do it again with no variable
argv.py $x $REPLY
# stdout: ['1234', '12']
# N-I dash stdout: []
### read -r ignores backslashes
echo 'one\ two' > $TMP/readr.txt
read escaped < $TMP/readr.txt
read -r raw < $TMP/readr.txt
argv "$escaped" "$raw"
# stdout: ['one two', 'one\\ two']
View
@@ -1,25 +1,5 @@
#!/usr/bin/env bash
### echo dashes
echo -
echo --
echo ---
# stdout-json: "-\n--\n---\n"
### echo -en
echo -en 'abc\ndef\n'
# stdout-json: "abc\ndef\n"
# N-I dash stdout-json: "-en abc\ndef\n\n"
### echo -ez (invalid flag)
# bash differs from the other two shells, but its behavior is possibly more
# sensible, if you're going to ignore the error. It doesn't make sense for the
# 'e' to mean 2 different things simultaneously: flag and literal to be
# printed.
echo -ez 'abc\n'
# stdout-json: "-ez abc\\n\n"
# BUG dash/mksh stdout-json: "-ez abc\n\n"
### exec builtin
exec echo hi
# stdout: hi
@@ -161,62 +141,6 @@ shift ZZZ
# OK dash status: 2
# BUG mksh status: 0
### Read builtin
# NOTE: there are TABS below
read x <<EOF
A B C D E
FG
EOF
echo "[$x]"
# stdout: [A B C D E]
# status: 0
### Read builtin with no newline.
# This is odd because the variable is populated successfully. OSH/Oil might
# need a separate put reading feature that doesn't use IFS.
echo -n ZZZ | { read x; echo $?; echo $x; }
# stdout-json: "1\nZZZ\n"
# status: 0
### Read builtin with multiple variables
# NOTE: there are TABS below
read x y z <<EOF
A B C D E
FG
EOF
echo "$x/$y/$z"
# stdout: A/B/C D E
# status: 0
### Read builtin with not enough variables
set -o errexit
set -o nounset # hm this doesn't change it
read x y z <<EOF
A B
EOF
echo /$x/$y/$z/
# stdout: /A/B//
# status: 0
### get umask
umask | grep '[0-9]\+' # check for digits
# status: 0
### Read -n (with $REPLY)
echo 12345 > $TMP/readn.txt
read -n 4 x < $TMP/readn.txt
read -n 2 < $TMP/readn.txt # Do it again with no variable
argv.py $x $REPLY
# stdout: ['1234', '12']
# N-I dash stdout: []
### read -r ignores backslashes
echo 'one\ two' > $TMP/readr.txt
read escaped < $TMP/readr.txt
read -r raw < $TMP/readr.txt
argv "$escaped" "$raw"
# stdout: ['one two', 'one\\ two']
### get umask
umask | grep '[0-9]\+' # check for digits
# status: 0
View
@@ -252,7 +252,12 @@ if_() {
}
builtins() {
sh-spec spec/builtins.test.sh --osh-failures-allowed 3 \
sh-spec spec/builtins.test.sh --osh-failures-allowed 1 \
${REF_SHELLS[@]} $OSH "$@"
}
builtin-io() {
sh-spec spec/builtin-io.test.sh --osh-failures-allowed 2 \
${REF_SHELLS[@]} $OSH "$@"
}

0 comments on commit 7fd097b

Please sign in to comment.