fix cosmetic error when printing if commands containing here-documents in the body; compiling -DSTRICT_POSIX now forces posix-mode shells to expand redirections before assignment statements preceding simple commands

This commit is contained in:
Chet Ramey
2026-03-03 11:14:10 -05:00
parent 044c1acc91
commit d0b41c2c5f
60 changed files with 526 additions and 7259 deletions
-16
View File
@@ -1,16 +0,0 @@
exec 9<>/dev/tcp/129.22.8.162/25
read banner <&9
echo "$banner"
echo quit >&9
read msg <&9
echo "$msg"
exec 9<&-
# nifty date command that queries the date/time server
cat < /dev/tcp/129.22.8.102/13
exit 0
-388
View File
@@ -1,388 +0,0 @@
export LC_COLLATE=C
#
# test the shell globbing
#
expect()
{
echo expect "$@"
}
# First, a test that bash-2.01.1 fails
${THIS_SH} ./glob1.sub
MYDIR=$PWD # save where we are
TESTDIR=/tmp/glob-test
mkdir $TESTDIR
builtin cd $TESTDIR || { echo $0: cannot cd to $TESTDIR >&2 ; exit 1; }
rm -rf *
touch a b c d abc abd abe bb bcd ca cb dd de Beware
mkdir bdir
# see if `regular' globbing works right
expect '<a> <abc> <abd> <abe> <X*>'
recho a* X*
expect '<a> <abc> <abd> <abe>'
recho \a*
# see if null glob expansion works
shopt -s nullglob
expect '<a> <abc> <abd> <abe>'
recho a* X*
shopt -u nullglob
# see if the failglob option works
mkdir tmp
touch tmp/l1 tmp/l2 tmp/l3
builtin echo tmp/l[12] tmp/*4 tmp/*3
shopt -s failglob
builtin echo tmp/l[12] tmp/*4 tmp/*3
rm -r tmp
shopt -u failglob
# see if the code that expands directories only works
expect '<bdir/>'
recho b*/
# Test quoted and unquoted globbing characters
expect '<*>'
recho \*
expect '<a*>'
recho 'a*'
expect '<a*>'
recho a\*
expect '<c> <ca> <cb> <a*> <*q*>'
recho c* a\* *q*
expect '<**>'
recho "*"*
expect '<**>'
recho \**
expect '<\.\./*/>'
recho "\.\./*/"
expect '<s/\..*//>'
recho 's/\..*//'
# Pattern from Larry Wall's Configure that caused bash to blow up
expect '</^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/>'
recho "/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*"'$'"/\1/"
# Make sure character classes work properly
expect '<abc> <abd> <abe> <bb> <cb>'
recho [a-c]b*
expect '<abd> <abe> <bb> <bcd> <bdir> <ca> <cb> <dd> <de>'
recho [a-y]*[^c]
expect '<abd> <abe>'
recho a*[^c]
touch a-b aXb
expect '<a-b> <aXb>'
recho a[X-]b
touch .x .y
expect '<Beware> <d> <dd> <de>'
recho [^a-c]*
# Make sure that filenames with embedded globbing characters are handled
# properly
mkdir a\*b
> a\*b/ooo
expect '<a*b/ooo>'
recho a\*b/*
expect '<a*b/ooo>'
recho a\*?/*
expect '<no match>'
cmd='echo !7'
case "$cmd" in
*\\!*) echo match ;;
*) echo no match ;;
esac
expect '<not there>'
file='r.*'
case $file in
*.\*) echo not there ;;
*) echo there ;;
esac
# examples from the Posix.2 spec (d11.2, p. 243)
expect '<abc>'
recho a[b]c
expect '<abc>'
recho a["b"]c
expect '<abc>'
recho a[\b]c
expect '<abc>'
recho a?c
expect '<match 1>'
case abc in
a"b"c) echo 'match 1' ;;
*) echo 'BAD match 1' ;;
esac
expect '<match 2>'
case abc in
a*c) echo 'match 2' ;;
*) echo 'BAD match 2' ;;
esac
expect '<ok 1>'
case abc in
"a?c") echo 'bad 1' ;;
*) echo 'ok 1' ;;
esac
expect '<ok 2>'
case abc in
a\*c) echo 'bad 2' ;;
*) echo 'ok 2' ;;
esac
expect '<ok 3>'
case abc in
a\[b]c) echo 'bad 3' ;;
*) echo 'ok 3' ;;
esac
expect '<ok 4>'
case "$nosuchvar" in
"") echo 'ok 4' ;;
*) echo 'bad 4' ;;
esac
# This is very odd, but sh and ksh seem to agree
expect '<ok 5>'
case abc in
a["\b"]c) echo 'ok 5' ;;
*) echo 'bad 5' ;;
esac
mkdir man
mkdir man/man1
touch man/man1/bash.1
expect '<man/man1/bash.1>'
recho */man*/bash.*
expect '<man/man1/bash.1>'
recho $(echo */man*/bash.*)
expect '<man/man1/bash.1>'
recho "$(echo */man*/bash.*)"
# tests with multiple `*'s
case abc in
a***c) echo ok 1;;
esac
case abc in
a*****?c) echo ok 2;;
esac
case abc in
?*****??) echo ok 3;;
esac
case abc in
*****??) echo ok 4;;
esac
case abc in
*****??c) echo ok 5;;
esac
case abc in
?*****?c) echo ok 6;;
esac
case abc in
?***?****c) echo ok 7;;
esac
case abc in
?***?****?) echo ok 8;;
esac
case abc in
?***?****) echo ok 9;;
esac
case abc in
*******c) echo ok 10;;
esac
case abc in
*******?) echo ok 11;;
esac
case abcdecdhjk in
a*cd**?**??k) echo ok 20;;
esac
case abcdecdhjk in
a**?**cd**?**??k) echo ok 21;;
esac
case abcdecdhjk in
a**?**cd**?**??k***) echo ok 22;;
esac
case abcdecdhjk in
a**?**cd**?**??***k) echo ok 23;;
esac
case abcdecdhjk in
a**?**cd**?**??***k**) echo ok 24;;
esac
case abcdecdhjk in
a****c**?**??*****) echo ok 25;;
esac
case '-' in
[-abc]) echo ok 26 ;;
esac
case '-' in
[abc-]) echo ok 27 ;;
esac
case '\' in
\\) echo ok 28 ;;
esac
case '\' in
[\\]) echo ok 29 ;;
esac
case '\' in
'\') echo ok 30 ;;
esac
case '[' in
[[]) echo ok 31 ;;
esac
# a `[' without a closing `]' is just another character to match, in the
# bash implementation
case '[' in
[) echo ok 32 ;;
esac
case '[abc' in
[*) echo 'ok 33';;
esac
# a right bracket shall lose its special meaning and represent itself in
# a bracket expression if it occurs first in the list. -- POSIX.2 2.8.3.2
case ']' in
[]]) echo ok 34 ;;
esac
case '-' in
[]-]) echo ok 35 ;;
esac
# a backslash should just escape the next character in this context
case p in
[a-\z]) echo ok 36 ;;
esac
# this was a bug in all versions up to bash-2.04-release
case "/tmp" in
[/\\]*) echo ok 37 ;;
esac
# none of these should output anything
case abc in
??**********?****?) echo bad 1;;
esac
case abc in
??**********?****c) echo bad 2;;
esac
case abc in
?************c****?****) echo bad 3;;
esac
case abc in
*c*?**) echo bad 4;;
esac
case abc in
a*****c*?**) echo bad 5;;
esac
case abc in
a********???*******) echo bad 6;;
esac
case 'a' in
[]) echo bad 7 ;;
esac
case '[' in
[abc) echo bad 8;;
esac
# let's start testing the case-insensitive globbing code
recho b*
shopt -s nocaseglob
recho b*
recho [b]*
shopt -u nocaseglob
# make sure set -f works right
set -f
recho *
set +f
# test out the GLOBIGNORE code
GLOBIGNORE='.*:*c:*e:?'
recho *
GLOBIGNORE='.*:*b:*d:?'
recho *
# see if GLOBIGNORE can substitute for `set -f'
GLOBIGNORE='.*:*'
recho *
unset GLOBIGNORE
expect '<man/man1/bash.1>'
recho */man*/bash.*
# make sure null values for GLOBIGNORE have no effect
GLOBIGNORE=
expect '<man/man1/bash.1>'
recho */man*/bash.*
# this is for the benefit of pure coverage, so it writes the pcv file
# in the right place, and for gprof
builtin cd $MYDIR
rm -rf $TESTDIR
exit 0
-1
View File
@@ -1 +0,0 @@
a:b:c
-5
View File
@@ -1,5 +0,0 @@
OIFS="$IFS"
IFS=":$IFS"
eval foo="a:b:c"
IFS="$OIFS"
echo $foo
-1
View File
@@ -1 +0,0 @@
a:b:c
-9
View File
@@ -1,9 +0,0 @@
OIFS=$IFS
IFS=":$IFS"
foo=$(echo a:b:c)
IFS=$OIFS
for i in $foo
do
echo $i
done
-1
View File
@@ -1 +0,0 @@
a:b:c
-9
View File
@@ -1,9 +0,0 @@
OIFS=$IFS
IFS=":$IFS"
foo=`echo a:b:c`
IFS=$OIFS
for i in $foo
do
echo $i
done
-4
View File
@@ -1,4 +0,0 @@
echo before calling input-line.sub
${THIS_SH} < ./input-line.sub
this line for input-line.sub
echo finished with input-line.sub
-6
View File
@@ -1,6 +0,0 @@
set -e
if set +e
then
false
fi
echo hi
-1
View File
@@ -1 +0,0 @@
hi
-81
View File
@@ -1,81 +0,0 @@
#!/bin/bash
typeset -i m2 m1 M n2 n1 N m n
typeset -i MM=5 NN=5
case $# in
0) :
;;
1) MM=$1; NN=$1
;;
2) MM=$1; NN=$2
;;
*) echo 1>&2 "Usage: $0 [m [n]]"
;;
esac
EMPTYLINE=: # echo
echo 'a = { ' # mathematica
let "M=1" # for (M=1; M<=MM; M++)
while let "M <= MM"; do
let "N=1" # for (N=1; N<=NN; N++)
while let "N <= NN"; do
let "m1 = M - 1"
let "m2 = M + 1"
let "n1 = N - 1"
let "n2 = N + 1"
echo -n '{ ' # math
let "m=1" # for(m=1; m<=MM; m++)
while let "m <= MM"; do
let "n=1" # for(n=1; n<=NN; n++)
while let "n <= NN"; do
let "x = (m-m1)*(m-M)*(m-m2)"
let "y = (n-n1)*(n-N)*(n-n2)"
if let "(x*x + (n-N)*(n-N)) * ((m-M)*(m-M) + y*y)"; then
echo -n "0,"
else # neighbour
echo -n "1,"
fi
let "n=n+1"
done
echo -n " "; let "m=m+1" # ". "
done
echo '},'
let "N=N+1"
$EMPTYLINE
done
$EMPTYLINE
let "M=M+1"
done
echo '}'
echo -n 'o = { '
let "m=1"
while let "m <= MM"; do
let "n=1"
while let "n <= NN"; do
echo -n "1,"
let "n=n+1"
done
let "m=m+1"
done
echo " }"
echo 'x = LinearSolve[a,o] '
exit 0
-10
View File
@@ -1,10 +0,0 @@
# originally from Mike Haertel
foo() { case $1 in a*) ;; *) ;; esac ;}
bar() { case $1 in [abc]*) ;; *);; esac ;}
baz() { case $1 in xyzzy) ;; *) ;; esac ;}
for x in /usr/lib/*/*
do
foo $x
bar $x
baz $x
done
-11
View File
@@ -1,11 +0,0 @@
# interactive
# from tty
read -n 3 -p 'enter three chars: ' xyz
echo
echo $xyz
# using readline
read -p 'enter 3 chars: ' -e -n 3 abc
# readline outputs a newline for us, so we don't need the extra echo
echo $abc
-11
View File
@@ -1,11 +0,0 @@
# interactive
# from tty
read -n 3 -p 'enter three chars: ' xyz
echo
echo $xyz
# using readline
read -p 'enter 3 chars: ' -e -n 3 abc
# readline outputs a newline for us, so we don't need the extra echo
echo $abc
-17
View File
@@ -1,17 +0,0 @@
read line1
echo read line 1 \"$line1\"
exec 4<&0
exec 0</dev/tty
read line2
echo line read from tty = \"$line2\"
exec 0<&4
read line3
echo read line 3 \"$line3\"
-12
View File
@@ -1,12 +0,0 @@
This is Geoff Collyer's `sh' regression test. It will run each test
on sh and ../../bash, and on ksh if you have it. I have `real' ksh;
the PD ksh is different and will fail some of the tests.
Expect some small variations in the sh and bash output, since some
of the tests work from the output of `date' or on the current dat
returned by `getdate'.
Don't expect `getdate' to exist unless you're running C News. If you
don't have it, run
make -f getdate.mk getdate
-152
View File
@@ -1,152 +0,0 @@
Newsgroups: comp.os.coherent
Subject: sh clones evaluated (was Re: C News)
Organization: Software Tool & Die Netnews Research Center
References: <138198@allan.sublink.org> <920725204@umunk.GUN.de>
<9207260813.30@rmkhome.UUCP> <1992Jul27.200244.2456@acme.gen.nz>
<Bs0x7K.2pp@world.std.com> <9207291604.00@rmkhome.UUCP>
<Bs84t1.3Fx@world.std.com> <9208011403.38@rmkhome.UUCP>
I've reevaluated the allegedly-sh-compatible shells I have on hand (sh,
bash, ash, zsh and a redistributable ksh). bash seems to have improved
since I last looked at it and seems to run inews and subordinates
correctly, and passes the diagnostic tests I extracted from inews and
anne.jones. ash, zsh and redistributable ksh each fail three of the six
tests. This saddens me, as ash is an elegant and relatively small piece
of work, whereas bash is bloated and complicated.
I've enclosed the test scripts (shx?), driver script (shx) and results
(log) below. A couple caveats: shx4 (a quoting test) uses the C News
getdate command; there may be newer versions of the shells tested - this
evaluation is decidedly informal. Here's a quick summary: sh and bash
passed all tests; ash can't parse "<&$fd" and doesn't understand quoting;
redistributable ksh dumps core on a newline inside backquotes, doesn't
understand quoting, and botches waiting on background processes; zsh
doesn't understand sh quoting (in particular, it sees ! as a job control
character, even inside quotes), and botches waiting for background
processes.
# To unbundle, sh this file
echo log 1>&2
sed 's/^X//' >log <<'!'
X:; ./shx
sh:
X<&$fd ok
nlbq Mon Aug 3 02:45:00 EDT 1992
bang geoff
quote 712824302
setbq defmsgid=<1992Aug3.024502.6176@host>
bgwait sleep done... wait 6187
bash:
X<&$fd ok
nlbq Mon Aug 3 02:45:09 EDT 1992
bang geoff
quote 712824311
setbq defmsgid=<1992Aug3.024512.6212@host>
bgwait sleep done... wait 6223
ash:
X<&$fd shx1: 4: Syntax error: Bad fd number
nlbq Mon Aug 3 02:45:19 EDT 1992
bang geoff
quote getdate: `"now"' not a valid date
setbq defmsgid=<1992Aug3.` echo 024521
bgwait sleep done... wait 6241
ksh:
X<&$fd ok
nlbq ./shx: 6248 Memory fault - core dumped
bang geoff
quote getdate: `"now"' not a valid date
setbq defmsgid=<1992Aug3.024530.6257@host>
bgwait no such job: 6265
wait 6265
sleep done...
zsh:
X<&$fd ok
nlbq Mon Aug 3 02:45:36 EDT 1992
bang shx3: event not found: /s/ [4]
quote 712824337
setbq defmsgid=<..6290@host>
bgwait shx7: unmatched " [9]
sleep done...
X:;
!
echo shx 1>&2
sed 's/^X//' >shx <<'!'
X#! /bin/sh
for cmd in sh bash ash ksh zsh
do
X echo
X echo $cmd:
X for demo in shx?
X do
X $cmd $demo
X done
done
!
echo shx1 1>&2
sed 's/^X//' >shx1 <<'!'
X# ash fails this one
echo -n '<&$fd '
fd=3
echo ok <&$fd
!
echo shx2 1>&2
sed 's/^X//' >shx2 <<'!'
X# pd ksh fails this one
echo -n "nlbq "
date=`
date`
echo "$date"
!
echo shx3 1>&2
sed 's/^X//' >shx3 <<'!'
X# zsh fails this one
echo -n 'bang '
echo 'geoff tty?? Aug 3 02:35' |
X sed -e 's/[ ].*//' -e '/!/s/^.*!//'
!
echo shx4 1>&2
sed 's/^X//' >shx4 <<'!'
X# ash, pd ksh fail this one
echo -n "quote "
expiry="now"
timet="` getdate \"$expiry\" `"
echo "$timet"
!
echo shx5 1>&2
sed 's/^X//' >shx5 <<'!'
X# ash, zsh fail this one
echo -n "setbq "
host=host
date="`date`"
echo defmsgid="`set $date; echo \<$6$2$3.\` echo $4 | tr -d : \`.$$@$host\>`"
!
echo shx7 1>&2
sed 's/^X//' >shx7 <<'!'
X# pd ksh and zsh fail this one
echo -n "bgwait "
X(
X sleep 2
X echo -n "sleep done... "
X) &
waitcmd="wait $!"
eval $waitcmd
echo "$waitcmd"
!
echo shx8 1>&2
sed 's/^X//' >shx8 <<'!'
X# in case gcx7 is really breaks this shell
sleep 3
echo
!
exit 0
-9
View File
@@ -1,9 +0,0 @@
all: getdate
getdate.c: getdate.y
yacc getdate.y
mv y.tab.c getdate.c
getdate: getdate.c
$(CC) -o $@ getdate.c
rm -f getdate.c getdate.o
-553
View File
@@ -1,553 +0,0 @@
%token ID MONTH DAY MERIDIAN NUMBER UNIT MUNIT SUNIT ZONE DAYZONE AGO
%{
/* Steven M. Bellovin (unc!smb) */
/* Dept. of Computer Science */
/* University of North Carolina at Chapel Hill */
/* @(#)getdate.y 2.13 9/16/86 */
#include <stdio.h>
#include <sys/types.h>
#include <ctype.h>
#include <time.h>
#define timezone tmzn /* ugly hack for obscure name clash */
#include <sys/timeb.h>
#define daysec (24L*60L*60L)
static int timeflag, zoneflag, dateflag, dayflag, relflag;
static time_t relsec, relmonth;
static int hh, mm, ss, merid, daylight;
static int dayord, dayreq;
static int month, day, year;
static int ourzone;
#define AM 1
#define PM 2
#define DAYLIGHT 1
#define STANDARD 2
#define MAYBE 3
%}
%%
timedate: /* empty */
| timedate item;
item: tspec =
{timeflag++;}
| zone =
{zoneflag++;}
| dtspec =
{dateflag++;}
| dyspec =
{dayflag++;}
| rspec =
{relflag++;}
| nspec;
nspec: NUMBER =
{if (timeflag && dateflag && !relflag) year = $1;
else {timeflag++;hh = $1/100;mm = $1%100;ss = 0;merid = 24;}};
tspec: NUMBER MERIDIAN =
{hh = $1; mm = 0; ss = 0; merid = $2;}
| NUMBER ':' NUMBER =
{hh = $1; mm = $3; merid = 24;}
| NUMBER ':' NUMBER MERIDIAN =
{hh = $1; mm = $3; merid = $4;}
| NUMBER ':' NUMBER NUMBER =
{hh = $1; mm = $3; merid = 24;
daylight = STANDARD; ourzone = $4%100 + 60*$4/100;}
| NUMBER ':' NUMBER ':' NUMBER =
{hh = $1; mm = $3; ss = $5; merid = 24;}
| NUMBER ':' NUMBER ':' NUMBER MERIDIAN =
{hh = $1; mm = $3; ss = $5; merid = $6;}
| NUMBER ':' NUMBER ':' NUMBER NUMBER =
{hh = $1; mm = $3; ss = $5; merid = 24;
daylight = STANDARD; ourzone = $6%100 + 60*$6/100;};
zone: ZONE =
{ourzone = $1; daylight = STANDARD;}
| DAYZONE =
{ourzone = $1; daylight = DAYLIGHT;};
dyspec: DAY =
{dayord = 1; dayreq = $1;}
| DAY ',' =
{dayord = 1; dayreq = $1;}
| NUMBER DAY =
{dayord = $1; dayreq = $2;};
dtspec: NUMBER '/' NUMBER =
{month = $1; day = $3;}
| NUMBER '/' NUMBER '/' NUMBER =
{month = $1; day = $3; year = $5;}
| MONTH NUMBER =
{month = $1; day = $2;}
| MONTH NUMBER ',' NUMBER =
{month = $1; day = $2; year = $4;}
| NUMBER MONTH =
{month = $2; day = $1;}
| NUMBER MONTH NUMBER =
{month = $2; day = $1; year = $3;};
rspec: NUMBER UNIT =
{relsec += 60L * $1 * $2;}
| NUMBER MUNIT =
{relmonth += $1 * $2;}
| NUMBER SUNIT =
{relsec += $1;}
| UNIT =
{relsec += 60L * $1;}
| MUNIT =
{relmonth += $1;}
| SUNIT =
{relsec++;}
| rspec AGO =
{relsec = -relsec; relmonth = -relmonth;};
%%
static int mdays[12] =
{31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
#define epoch 1970
extern struct tm *localtime();
static time_t
dateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
int mm, dd, yy, h, m, s, mer, zone, dayflag;
{
time_t tod, jdate;
register int i;
time_t timeconv();
if (yy < 0) yy = -yy;
if (yy < 100) yy += 1900;
mdays[1] = 28 + (yy%4 == 0 && (yy%100 != 0 || yy%400 == 0));
if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 ||
dd < 1 || dd > mdays[--mm]) return (-1);
jdate = dd-1;
for (i=0; i<mm; i++) jdate += mdays[i];
for (i = epoch; i < yy; i++) jdate += 365 + (i%4 == 0);
jdate *= daysec;
jdate += zone * 60L;
if ((tod = timeconv(h, m, s, mer)) < 0) return (-1);
jdate += tod;
if (dayflag==DAYLIGHT || (dayflag==MAYBE&&localtime(&jdate)->tm_isdst))
jdate += -1*60*60;
return (jdate);
}
static time_t
dayconv(ord, day, now)
int ord, day; time_t now;
{
register struct tm *loctime;
time_t tod;
time_t daylcorr();
tod = now;
loctime = localtime(&tod);
tod += daysec * ((day - loctime->tm_wday + 7) % 7);
tod += 7*daysec*(ord<=0?ord:ord-1);
return daylcorr(tod, now);
}
static time_t
timeconv(hh, mm, ss, mer)
register int hh, mm, ss, mer;
{
if (mm < 0 || mm > 59 || ss < 0 || ss > 59) return (-1);
switch (mer) {
case AM: if (hh < 1 || hh > 12) return(-1);
return (60L * ((hh%12)*60L + mm)+ss);
case PM: if (hh < 1 || hh > 12) return(-1);
return (60L * ((hh%12 +12)*60L + mm)+ss);
case 24: if (hh < 0 || hh > 23) return (-1);
return (60L * (hh*60L + mm)+ss);
default: return (-1);
}
}
static time_t
monthadd(sdate, relmonth)
time_t sdate, relmonth;
{
struct tm *ltime;
time_t dateconv();
time_t daylcorr();
int mm, yy;
if (relmonth == 0) return 0;
ltime = localtime(&sdate);
mm = 12*ltime->tm_year + ltime->tm_mon + relmonth;
yy = mm/12;
mm = mm%12 + 1;
return daylcorr(dateconv(mm, ltime->tm_mday, yy, ltime->tm_hour,
ltime->tm_min, ltime->tm_sec, 24, ourzone, MAYBE), sdate);
}
static time_t
daylcorr(future, now)
time_t future, now;
{
int fdayl, nowdayl;
nowdayl = (localtime(&now)->tm_hour+1) % 24;
fdayl = (localtime(&future)->tm_hour+1) % 24;
return (future-now) + 60L*60L*(nowdayl-fdayl);
}
static char *lptr;
yylex()
{
extern int yylval;
int sign;
register char c;
register char *p;
char idbuf[20];
int pcnt;
for (;;) {
while (isspace(*lptr)) lptr++;
if (isdigit(c = *lptr) || c == '-' || c == '+') {
if (c== '-' || c == '+') {
if (c=='-') sign = -1;
else sign = 1;
if (!isdigit(*++lptr)) {
/* yylval = sign; return (NUMBER); */
return yylex(); /* skip the '-' sign */
}
} else sign = 1;
yylval = 0;
while (isdigit(c = *lptr++)) yylval = 10*yylval + c - '0';
yylval *= sign;
lptr--;
return (NUMBER);
} else if (isalpha(c)) {
p = idbuf;
while (isalpha(c = *lptr++) || c=='.')
if (p < &idbuf[sizeof(idbuf)-1])
*p++ = c;
*p = '\0';
lptr--;
return (lookup(idbuf));
}
else if (c == '(') {
pcnt = 0;
do {
c = *lptr++;
if (c == '\0') return(c);
else if (c == '(') pcnt++;
else if (c == ')') pcnt--;
} while (pcnt > 0);
}
else return (*lptr++);
}
}
struct table {
char *name;
int type, value;
};
static struct table mdtab[] = {
{"January", MONTH, 1},
{"February", MONTH, 2},
{"March", MONTH, 3},
{"April", MONTH, 4},
{"May", MONTH, 5},
{"June", MONTH, 6},
{"July", MONTH, 7},
{"August", MONTH, 8},
{"September", MONTH, 9},
{"Sept", MONTH, 9},
{"October", MONTH, 10},
{"November", MONTH, 11},
{"December", MONTH, 12},
{"Sunday", DAY, 0},
{"Monday", DAY, 1},
{"Tuesday", DAY, 2},
{"Tues", DAY, 2},
{"Wednesday", DAY, 3},
{"Wednes", DAY, 3},
{"Thursday", DAY, 4},
{"Thur", DAY, 4},
{"Thurs", DAY, 4},
{"Friday", DAY, 5},
{"Saturday", DAY, 6},
{0, 0, 0}};
#define HRS *60
#define HALFHR 30
static struct table mztab[] = {
{"a.m.", MERIDIAN, AM},
{"am", MERIDIAN, AM},
{"p.m.", MERIDIAN, PM},
{"pm", MERIDIAN, PM},
{"nst", ZONE, 3 HRS + HALFHR}, /* Newfoundland */
{"n.s.t.", ZONE, 3 HRS + HALFHR},
{"ast", ZONE, 4 HRS}, /* Atlantic */
{"a.s.t.", ZONE, 4 HRS},
{"adt", DAYZONE, 4 HRS},
{"a.d.t.", DAYZONE, 4 HRS},
{"est", ZONE, 5 HRS}, /* Eastern */
{"e.s.t.", ZONE, 5 HRS},
{"edt", DAYZONE, 5 HRS},
{"e.d.t.", DAYZONE, 5 HRS},
{"cst", ZONE, 6 HRS}, /* Central */
{"c.s.t.", ZONE, 6 HRS},
{"cdt", DAYZONE, 6 HRS},
{"c.d.t.", DAYZONE, 6 HRS},
{"mst", ZONE, 7 HRS}, /* Mountain */
{"m.s.t.", ZONE, 7 HRS},
{"mdt", DAYZONE, 7 HRS},
{"m.d.t.", DAYZONE, 7 HRS},
{"pst", ZONE, 8 HRS}, /* Pacific */
{"p.s.t.", ZONE, 8 HRS},
{"pdt", DAYZONE, 8 HRS},
{"p.d.t.", DAYZONE, 8 HRS},
{"yst", ZONE, 9 HRS}, /* Yukon */
{"y.s.t.", ZONE, 9 HRS},
{"ydt", DAYZONE, 9 HRS},
{"y.d.t.", DAYZONE, 9 HRS},
{"hst", ZONE, 10 HRS}, /* Hawaii */
{"h.s.t.", ZONE, 10 HRS},
{"hdt", DAYZONE, 10 HRS},
{"h.d.t.", DAYZONE, 10 HRS},
{"gmt", ZONE, 0 HRS},
{"g.m.t.", ZONE, 0 HRS},
{"ut", ZONE, 0 HRS},
{"u.t.", ZONE, 0 HRS},
{"bst", DAYZONE, 0 HRS}, /* British Summer Time */
{"b.s.t.", DAYZONE, 0 HRS},
{"eet", ZONE, 0 HRS}, /* European Eastern Time */
{"e.e.t.", ZONE, 0 HRS},
{"eest", DAYZONE, 0 HRS}, /* European Eastern Summer Time */
{"e.e.s.t.", DAYZONE, 0 HRS},
{"met", ZONE, -1 HRS}, /* Middle European Time */
{"m.e.t.", ZONE, -1 HRS},
{"mest", DAYZONE, -1 HRS}, /* Middle European Summer Time */
{"m.e.s.t.", DAYZONE, -1 HRS},
{"wet", ZONE, -2 HRS }, /* Western European Time */
{"w.e.t.", ZONE, -2 HRS },
{"west", DAYZONE, -2 HRS}, /* Western European Summer Time */
{"w.e.s.t.", DAYZONE, -2 HRS},
{"jst", ZONE, -9 HRS}, /* Japan Standard Time */
{"j.s.t.", ZONE, -9 HRS}, /* Japan Standard Time */
/* No daylight savings time */
{"aest", ZONE, -10 HRS}, /* Australian Eastern Time */
{"a.e.s.t.", ZONE, -10 HRS},
{"aesst", DAYZONE, -10 HRS}, /* Australian Eastern Summer Time */
{"a.e.s.s.t.", DAYZONE, -10 HRS},
{"acst", ZONE, -(9 HRS + HALFHR)}, /* Australian Central Time */
{"a.c.s.t.", ZONE, -(9 HRS + HALFHR)},
{"acsst", DAYZONE, -(9 HRS + HALFHR)}, /* Australian Central Summer */
{"a.c.s.s.t.", DAYZONE, -(9 HRS + HALFHR)},
{"awst", ZONE, -8 HRS}, /* Australian Western Time */
{"a.w.s.t.", ZONE, -8 HRS}, /* (no daylight time there, I'm told */
{0, 0, 0}};
static struct table unittb[] = {
{"year", MUNIT, 12},
{"month", MUNIT, 1},
{"fortnight", UNIT, 14*24*60},
{"week", UNIT, 7*24*60},
{"day", UNIT, 1*24*60},
{"hour", UNIT, 60},
{"minute", UNIT, 1},
{"min", UNIT, 1},
{"second", SUNIT, 1},
{"sec", SUNIT, 1},
{0, 0, 0}};
static struct table othertb[] = {
{"tomorrow", UNIT, 1*24*60},
{"yesterday", UNIT, -1*24*60},
{"today", UNIT, 0},
{"now", UNIT, 0},
{"last", NUMBER, -1},
{"this", UNIT, 0},
{"next", NUMBER, 2},
{"first", NUMBER, 1},
/* {"second", NUMBER, 2}, */
{"third", NUMBER, 3},
{"fourth", NUMBER, 4},
{"fifth", NUMBER, 5},
{"sixth", NUMBER, 6},
{"seventh", NUMBER, 7},
{"eigth", NUMBER, 8},
{"ninth", NUMBER, 9},
{"tenth", NUMBER, 10},
{"eleventh", NUMBER, 11},
{"twelfth", NUMBER, 12},
{"ago", AGO, 1},
{0, 0, 0}};
static struct table milzone[] = {
{"a", ZONE, 1 HRS},
{"b", ZONE, 2 HRS},
{"c", ZONE, 3 HRS},
{"d", ZONE, 4 HRS},
{"e", ZONE, 5 HRS},
{"f", ZONE, 6 HRS},
{"g", ZONE, 7 HRS},
{"h", ZONE, 8 HRS},
{"i", ZONE, 9 HRS},
{"k", ZONE, 10 HRS},
{"l", ZONE, 11 HRS},
{"m", ZONE, 12 HRS},
{"n", ZONE, -1 HRS},
{"o", ZONE, -2 HRS},
{"p", ZONE, -3 HRS},
{"q", ZONE, -4 HRS},
{"r", ZONE, -5 HRS},
{"s", ZONE, -6 HRS},
{"t", ZONE, -7 HRS},
{"u", ZONE, -8 HRS},
{"v", ZONE, -9 HRS},
{"w", ZONE, -10 HRS},
{"x", ZONE, -11 HRS},
{"y", ZONE, -12 HRS},
{"z", ZONE, 0 HRS},
{0, 0, 0}};
static
lookup(id)
char *id;
{
#define gotit (yylval=i->value, i->type)
#define getid for(j=idvar, k=id; *j++ = *k++; )
char idvar[20];
register char *j, *k;
register struct table *i;
int abbrev;
getid;
if (strlen(idvar) == 3) abbrev = 1;
else if (strlen(idvar) == 4 && idvar[3] == '.') {
abbrev = 1;
idvar[3] = '\0';
}
else abbrev = 0;
if (islower(*idvar)) *idvar = toupper(*idvar);
for (i = mdtab; i->name; i++) {
k = idvar;
for (j = i->name; *j++ == *k++;) {
if (abbrev && j==i->name+3) return gotit;
if (j[-1] == 0) return gotit;
}
}
getid;
for (i = mztab; i->name; i++)
if (strcmp(i->name, idvar) == 0) return gotit;
for (j = idvar; *j; j++)
if (isupper(*j)) *j = tolower(*j);
for (i=mztab; i->name; i++)
if (strcmp(i->name, idvar) == 0) return gotit;
getid;
for (i=unittb; i->name; i++)
if (strcmp(i->name, idvar) == 0) return gotit;
if (idvar[strlen(idvar)-1] == 's')
idvar[strlen(idvar)-1] = '\0';
for (i=unittb; i->name; i++)
if (strcmp(i->name, idvar) == 0) return gotit;
getid;
for (i = othertb; i->name; i++)
if (strcmp(i->name, idvar) == 0) return gotit;
getid;
if (strlen(idvar) == 1 && isalpha(*idvar)) {
if (isupper(*idvar)) *idvar = tolower(*idvar);
for (i = milzone; i->name; i++)
if (strcmp(i->name, idvar) == 0) return gotit;
}
return(ID);
}
time_t
getdate(p, now)
char *p;
struct timeb *now;
{
#define mcheck(f) if (f>1) err++
time_t monthadd();
int err;
struct tm *lt;
struct timeb ftz;
time_t sdate, tod;
lptr = p;
if (now == ((struct timeb *) NULL)) {
now = &ftz;
ftime(&ftz);
}
lt = localtime(&now->time);
year = lt->tm_year;
month = lt->tm_mon+1;
day = lt->tm_mday;
relsec = 0; relmonth = 0;
timeflag=zoneflag=dateflag=dayflag=relflag=0;
ourzone = now->timezone;
daylight = MAYBE;
hh = mm = ss = 0;
merid = 24;
if (err = yyparse()) return (-1);
mcheck(timeflag);
mcheck(zoneflag);
mcheck(dateflag);
mcheck(dayflag);
if (err) return (-1);
if (dateflag || timeflag || dayflag) {
sdate = dateconv(month,day,year,hh,mm,ss,merid,ourzone,daylight);
if (sdate < 0) return -1;
}
else {
sdate = now->time;
if (relflag == 0)
sdate -= (lt->tm_sec + lt->tm_min*60 +
lt->tm_hour*(60L*60L));
}
sdate += relsec;
sdate += monthadd(sdate, relmonth);
if (dayflag && !dateflag) {
tod = dayconv(dayord, dayreq, sdate);
sdate += tod;
}
return sdate;
}
yyerror(s) char *s;
{}
main(c, v)
int c;
char **v;
{
printf("%d\n", getdate(v[1], (struct timeb *)0));
}
-15
View File
@@ -1,15 +0,0 @@
#! /bin/sh
if ksh -c 'echo ""' >/dev/null 2>&1; then
ksh=ksh
fi
for cmd in sh ../../bash $ksh
do
echo
echo $cmd:
for demo in shx[0-9]
do
$cmd $demo
done
done
-4
View File
@@ -1,4 +0,0 @@
# ash fails this one
echo -n '<&$fd '
fd=3
echo ok <&$fd
-5
View File
@@ -1,5 +0,0 @@
# pd ksh fails this one
echo -n "nlbq "
date=`
date`
echo "$date"
-4
View File
@@ -1,4 +0,0 @@
# zsh fails this one
echo -n 'bang '
echo 'geoff tty?? Aug 3 02:35' |
sed -e 's/[ ].*//' -e '/!/s/^.*!//'
-5
View File
@@ -1,5 +0,0 @@
# ash, pd ksh fail this one
echo -n "quote "
expiry="now"
timet="` getdate \"$expiry\" `"
echo "$timet"
-5
View File
@@ -1,5 +0,0 @@
# ash, zsh fail this one
echo -n "setbq "
host=host
date="`date`"
echo defmsgid="`set $date; echo \<$6$2$3.\` echo $4 | tr -d : \`.$$@$host\>`"
-9
View File
@@ -1,9 +0,0 @@
# pd ksh and zsh fail this one
echo -n "bgwait "
(
sleep 2
echo -n "sleep done... "
) &
waitcmd="wait $!"
eval $waitcmd
echo "$waitcmd"
-3
View File
@@ -1,3 +0,0 @@
# in case gcx7 is really breaks this shell
sleep 3
echo
-13
View File
@@ -1,13 +0,0 @@
#
# show that IFS is only applied to the result of expansions
#
${THIS_SH} ifs-1.test > /tmp/xx
diff /tmp/xx ./ifs-1.right
${THIS_SH} ifs-2.test > /tmp/xx
diff /tmp/xx ./ifs-2.right
${THIS_SH} ifs-3.test > /tmp/xx
diff /tmp/xx ./ifs-3.right
rm -f /tmp/xx
-2
View File
@@ -1,2 +0,0 @@
cat ./input-line-2.sh | ${THIS_SH} > /tmp/xx
diff /tmp/xx input.right && rm -f /tmp/xx
-2
View File
@@ -1,2 +0,0 @@
${THIS_SH} ./minus-e > /tmp/xx
diff /tmp/xx minus-e.right && rm -f /tmp/xx
-1
View File
@@ -1 +0,0 @@
../../bash ./redir-t2.sh < /etc/passwd
-9
View File
@@ -1,9 +0,0 @@
echo before trap
trap 'echo caught sigint' 2
echo after trap
for i in 1 2 3
do
echo $i
sleep 5
done
-7
View File
@@ -1,7 +0,0 @@
echo before loop
for i in 1 2 3
do
echo $i
sleep 5
done
-11
View File
@@ -1,11 +0,0 @@
sleep 5 &
sleep 5 &
sleep 5 &
echo wait 1
wait
echo wait 2
wait
exit
-13
View File
@@ -1,13 +0,0 @@
trap 'echo sigint' 2
sleep 5 &
sleep 5 &
sleep 5 &
echo wait 1
wait
echo wait 2
wait
exit
-9
View File
@@ -1,9 +0,0 @@
touch .file
while set -e ; test -r .file ; do
echo -n "stop loop? "
read reply
case "$reply" in
y*) rm .file non-dash-file ;;
esac
set +e
done
-11
View File
@@ -1,11 +0,0 @@
touch .file
set -e
while set +e ; test -r .file ; do
echo -n "stop loop? [yes to quit] "
read reply
if [ "$reply" = yes ] ; then
rm .file non-dash-file
fi
set -e
done
rm -f .file
-15
View File
@@ -1,15 +0,0 @@
# these will work only if test.c has been compiled with -DPATTERN_MATCHING
# to get =~ and !~
[ a =\~ a ] && echo OK || echo BAD
[ a !~ b ] && echo OK || echo BAD
[ a =\~ \* ] && echo OK || echo BAD
[ a =\~ \? ] && echo OK || echo BAD
[ abc !~ \? ] && echo OK || echo BAD
[ '' =\~ \* ] && echo OK || echo BAD
[ '' !~ \?\* ] && echo OK || echo BAD
[ a =\~ \[abc] ] && echo OK || echo BAD
[ x !~ \[abc] ] && echo OK || echo BAD
-50
View File
@@ -1,50 +0,0 @@
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
: ${THIS_SH:=./bash}
printf "time -c : :\n"
time ${THIS_SH} -c :
printf "time /dev/null:\n"
time ${THIS_SH} /dev/null
printf "\nPOSIX: time -p /dev/null:\n"
time -p ${THIS_SH} /dev/null
printf "\nBSD time /dev/null:\n"
TIMEFORMAT=$'\t%1R real\t%1U user\t%1S sys'
time ${THIS_SH} /dev/null
printf "\nSYSV time /dev/null:\n"
TIMEFORMAT=$'\nreal\t%1R\nuser\t%1U\nsys\t%1S'
time ${THIS_SH} /dev/null
printf "\nksh time /dev/null:\n"
TIMEFORMAT=$'\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS'
time ${THIS_SH} < /dev/null
time (:)
(time :)
times -x
printf "\ntimes:\n"
times
echo
times --
printf "\ntime standalone:\n"
{ time ; echo after; } |& wc -l
exit 0
-25
View File
@@ -1,25 +0,0 @@
#! /bin/bash
i=0
while [ $i -lt $1 ]
do
/bin/sh -c "sleep 4; exit 0" &
rv=$?
pid=$!
eval bg_pid_$i=$pid
echo $$: Job $i: pid is $pid rv=$rv
i=$((i + 1))
done
i=0
while [ $i -lt $1 ]
do
eval wpid=\$bg_pid_$i
echo Waiting for job $i '('pid $wpid')'
wait $wpid
rv=$?
echo Return value is $rv
i=$((i + 1))
done