#!/usr/bin/env bash
set -u

# Run troff discarding stdout, but capture stderr
((line=$LINENO+3))
result=$(
  (echo ".lf $line $0"; cat <<'EOF'
.
.nr debug 1
.de debugmsg
.  if \\n[debug] .tm \\$*
..
.de errormsg
.  tm ERROR (line \\n[.c]): \\$*
.  nr nerrors (\\n[nerrors]+1)
..
.nr nerrors 0
.
.\"  **TESTER FOR PROPOSED FIXED .substring (not how it works now) **
.\"
.\"  .substring str n1 [n2]
.\"     Replace the string named STR with the substring defined by the
.\"     indices N1 and N2.  The first character in the string has index 0.
.\"     If N1 or N2 is negative, it is counted from the end of the string, 
.\"     going backwards: The last character has index -1, the character before 
.\"     the last character has index -2, etc.  If N2 is omitted then -1 is used 
.\"     implicitly, indicating the last character, if any.
.\"
.\"     If N2 refers to a position before N1 then the substring is empty, and 
.\"     the string named STR is set to contain "".   It is allowed for N1 or N2 
.\"     to point to positions before the start or after the end of the existing 
.\"     string; the substring includes characters at valid positions within 
.\"     the indicated range, if any.
.\"     
.\"          .ds xxx abcdefgh
.\"          .substring xxx 1 -4
.\"          \*[xxx]
.\"              => bcde
.\"          .substring xxx 2
.\"          \*[xxx]
.\"              => de
.\"          .substring xxx -2
.\"          \*[xxx]
.\"              => de
.\"          .substring xxx 1
.\"          \*[xxx]
.\"              => e
.\"          .substring xxx 1
.\"          \*[xxx]
.\"              => (empty)
.\"          .substring xxx 1
.\"          \*[xxx]
.\"              => (empty)
.\"    
.de jtest \" input_string n1 n2 expected_result comment...
.  if \\n[.$]<4 .ab jtest: Not enough args
.  ds t*input "\\$1
.  ds t*n1 \\$2
.  ds t*n2 \\$3
.  ds t*expected "\\$4
.  shift 4
.  ds t*comment "\\$*
.
.  ds t*str "\\*[t*input]
.  ie '\\*[t*n2]'' .substring t*str \\*[t*n1]
.  el              .substring t*str \\*[t*n1] \\*[t*n2]
.  ie '\\*[t*str]'\\*[t*expected]' \{\
.    debugmsg .substring '\\*[t*input]' \\*[t*n1] \\*[t*n2] -> '\\*[t*str]' (OK) \\*[comment]
.  \}
.  el \{\
.    errormsg .substring '\\*[t*input]' \\*[t*n1] \\*[t*n2] yielded '\\*[t*str]', EXPECTED '\\*[t*expected]' \\*[comment]
.  \}
..
.
.debugmsg --- Pick a single character from non-empty ---
.jtest "abc"  0  0 "a"
.jtest "abc" -3 -3 "a"
.jtest "abc" -4 -1 "a" N1 points before start, harmlessly
.jtest "abc"  1  1 "b"
.jtest "abc" -2 -2 "b"
.jtest "abc"  2  2 "c"
.jtest "abc" -1 -1 "c"
.jtest "abc"  2  3 "c" N2 points after the end, harmlessly
.
.debugmsg --- Pick multiple characters from non-empty ---
.jtest "abcd"  0  1 "ab"
.jtest "abcd" -4 -3 "ab"
.jtest "abcd" -5 -3 "ab" N1 points before start, harmlessly
.jtest "abcd" -5  1 "ab" N1 points before start, harmlessly
.jtest "abcd"  0  3 "abcd"
.jtest "abcd" -4 -1 "abcd"
.jtest "abcd" -5 -1 "abcd" N1 points before start, harmlessly
.jtest "abcd"  1  3 "bcd"
.jtest "abcd"  1  4 "bcd" N2 points beyond end, harmlessly
.
.debugmsg --- Omit N2 with non-empty input and non-empty result ---
.jtest "abc"  0 "" "abc"
.jtest "abc" -3 "" "abc"
.jtest "abc"  1 "" "bc"
.jtest "abc" -2 "" "bc"
.jtest "abc"  2 "" "c"
.jtest "abc" -3 "" "c"
.jtest "a"    0 "" "a"
.jtest "a"   -1 "" "a"
.
.debugmsg --- Omit N2 with non-empty input but EMPTY result ---
.jtest "abc" 3 "" "" N1 points beyond end; the implicit N2 points before N1
.jtest "a"   1 "" "" N1 points beyond end; the implicit N2 points before N1
.
.debugmsg --- Omit N2 with empty input ---
.jtest ""  0 "" "" N1 points beyond end of the (empty) input
.jtest ""  1 "" "" N1 points beyond end of the (empty) input
.jtest "" -1 "" "" N1 points before start of the (empty) input
.jtest "" -2 "" "" N1 points before start of the (empty) input
.
.debugmsg --- Specify empty substring with N2==(N1-1) ---
.jtest "abcd"  3  2 ""
.jtest "abcd"  2  1 ""
.jtest "abcd"  1  0 ""
.jtest "abcd" -1 -2 "" Negative indicies specify a null range
.
.if \n[nerrors] .ab Aborting, got \n[nerrors] errors.
EOF
  ) | troff -wall 2>&1 >/dev/null
)
stat=$?
echo "Exit status was $stat"
echo "$result"
exit $stat
