This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 3.0: (no announcement message available) perl-3.000
authorLarry Wall <larry@wall.org>
Wed, 18 Oct 1989 00:00:00 +0000 (00:00 +0000)
committerLarry Wall <larry@wall.org>
Wed, 18 Oct 1989 00:00:00 +0000 (00:00 +0000)
A few of the new features: (18 Oct)

    * Perl can now handle binary data correctly and has functions to pack and unpack binary structures into arrays or lists. You can now do arbitrary ioctl functions.
    * You can now pass things to subroutines by reference.
    * Debugger enhancements.
    * An array or associative array may now appear in a local() list.
    * Array values may now be interpolated into strings.
    * Subroutine names are now distinguished by prefixing with &. You can call subroutines without using do, and without passing any argument list at all.
    * You can use the new -u switch to cause perl to dump core so that you can run undump and produce a binary executable image. Alternately you can use the "dump" operator after initializing any variables and such.
    * You can now chop lists.
    * Perl now uses /bin/csh to do filename globbing, if available. This means that filenames with spaces or other strangenesses work right.
    * New functions: mkdir and rmdir, getppid, getpgrp and setpgrp, getpriority and setpriority, chroot, ioctl and fcntl, flock, readlink, lstat, rindex, pack and unpack, read, warn, dbmopen and dbmclose, dump, reverse, defined, undef.

194 files changed:
Changes
Configure
Copying [new file with mode: 0644]
EXTERN.h
INTERN.h
MANIFEST
Makefile.SH
PACKINGLIST [new file with mode: 0644]
README
Wishlist
arg.c [deleted file]
arg.h
array.c
array.h
client [new file with mode: 0644]
cmd.c
cmd.h
config.H
config.h.SH
cons.c [new file with mode: 0644]
consarg.c [new file with mode: 0644]
doarg.c [new file with mode: 0644]
doio.c [new file with mode: 0644]
dolist.c [new file with mode: 0644]
dump.c
eg/ADB
eg/changes
eg/down [new file with mode: 0644]
eg/dus
eg/findcp
eg/findtar
eg/g/gcp
eg/g/gcp.man
eg/g/ged
eg/g/gsh
eg/g/gsh.man
eg/muck [new file with mode: 0644]
eg/muck.man [new file with mode: 0644]
eg/myrup
eg/nih
eg/rename [new file with mode: 0644]
eg/rmfrom
eg/scan/scan_df
eg/scan/scan_last
eg/scan/scan_messages
eg/scan/scan_passwd
eg/scan/scan_ps
eg/scan/scan_sudo
eg/scan/scan_suid
eg/scan/scanner
eg/shmkill
eg/van/empty
eg/van/unvanish
eg/van/vanexp
eg/van/vanish
eg/who [new file with mode: 0644]
eval.c
evalargs.xc [new file with mode: 0644]
form.c
form.h
gettest [new file with mode: 0644]
handy.h
hash.c
hash.h
ioctl.pl [new file with mode: 0644]
lib/abbrev.pl [new file with mode: 0644]
lib/complete.pl [new file with mode: 0644]
lib/dumpvar.pl [new file with mode: 0644]
lib/getopt.pl
lib/getopts.pl [new file with mode: 0644]
lib/importenv.pl
lib/look.pl [new file with mode: 0644]
lib/perldb.pl [new file with mode: 0644]
lib/stat.pl
lib/termcap.pl [new file with mode: 0644]
lib/validate.pl [new file with mode: 0644]
makedepend.SH
makedir.SH
makelib.SH [new file with mode: 0644]
malloc.c
patchlevel.h
perl.h
perl.man.1
perl.man.2
perl.man.3 [new file with mode: 0644]
perl.man.4 [new file with mode: 0644]
perl.y
perldb [deleted file]
perldb.man [deleted file]
perly.c
regcomp.c [new file with mode: 0644]
regcomp.h [new file with mode: 0644]
regexec.c [new file with mode: 0644]
regexp.c [deleted file]
regexp.h
server [new file with mode: 0644]
spat.h
stab.c
stab.h
str.c
str.h
t/TEST
t/base.cond
t/base.if
t/base.lex
t/base.pat
t/base.term
t/cmd.elsif
t/cmd.for
t/cmd.mod
t/cmd.subval
t/cmd.switch [new file with mode: 0644]
t/cmd.while
t/comp.cmdopt
t/comp.cpp
t/comp.decl
t/comp.multiline
t/comp.package [new file with mode: 0644]
t/comp.script
t/comp.term
t/io.argv
t/io.dup
t/io.fs
t/io.inplace
t/io.pipe
t/io.print
t/io.tell
t/op.append
t/op.array [new file with mode: 0644]
t/op.auto
t/op.chop
t/op.cond
t/op.dbm [new file with mode: 0644]
t/op.delete
t/op.do
t/op.each
t/op.eval
t/op.exec
t/op.exp
t/op.flip
t/op.fork
t/op.glob [new file with mode: 0644]
t/op.goto
t/op.index [new file with mode: 0644]
t/op.int
t/op.join
t/op.list
t/op.local [new file with mode: 0644]
t/op.magic
t/op.mkdir [new file with mode: 0644]
t/op.oct
t/op.ord
t/op.pack [new file with mode: 0644]
t/op.pat
t/op.push
t/op.range [new file with mode: 0644]
t/op.read [new file with mode: 0644]
t/op.regexp
t/op.repeat
t/op.sleep
t/op.sort [new file with mode: 0644]
t/op.split
t/op.sprintf
t/op.stat
t/op.study
t/op.subst
t/op.substr [new file with mode: 0644]
t/op.time
t/op.undef [new file with mode: 0644]
t/op.unshift
t/op.vec [new file with mode: 0644]
t/op.write [new file with mode: 0644]
t/re_tests
toke.c
util.c
util.h
version.c [deleted file]
x2p/EXTERN.h
x2p/INTERN.h
x2p/Makefile.SH
x2p/a2p.h
x2p/a2p.man
x2p/a2p.y
x2p/a2py.c
x2p/handy.h
x2p/hash.c
x2p/hash.h
x2p/s2p.SH [moved from x2p/s2p with 73% similarity]
x2p/s2p.man
x2p/str.c
x2p/str.h
x2p/util.c
x2p/util.h
x2p/walk.c

diff --git a/Changes b/Changes
index c2f50c2..fdd452d 100644 (file)
--- a/Changes
+++ b/Changes
-New regexp routines derived from Henry Spencer's.
-       Support for /(foo|bar)/.
-       Support for /(foo)*/ and /(foo)+/.
-       \s for whitespace, \S nonwhitespace
-       \d for digit, \D nondigit
+Changes to perl
+---------------
 
-Local variables in blocks, subroutines and evals.
+Apart from little bug fixes, here are the new features:
 
-Recursive subroutine calls are now supported.
+Perl can now handle binary data correctly and has functions to pack and
+unpack binary structures into arrays or lists.  You can now do arbitrary
+ioctl functions.
 
-Array values may now be interpolated into lists:
-       unlink 'foo', 'bar', @trashcan, 'tmp';
+You can do i/o with sockets and select.
 
-File globbing via <*.foo>.
+You can now write packages with their own namespace.
 
-Use of <> in array contexts returns the whole file or glob list:
-       unlink <*.foo>;
+You can now pass things to subroutines by reference.
 
-New iterator for normal arrays, foreach, that allows both read and write:
-       foreach $elem ($array) {
-               $elem =~ s/foo/bar/;
-       }
+The debugger now has hooks in the perl parser so it doesn't get confused.
+The debugger won't interfere with stdin and stdout.  New debugger commands:
+       n               Single step around subroutine call.
+       l min+incr      List incr+1 lines starting at min.
+       l               List incr+1 more lines.
+       l subname       List subroutine.
+       b subname       Set breakpoint at first line of subroutine.
+       S               List subroutine names.
+       D               Delete all breakpoints.
+       A               List line actions.
+       < command       Define command before prompt.
+       > command       Define command after prompt.
+       ! number        Redo command (default previous command).
+       ! -number       Redo numberth to last command.
+       h -number       Display last number commands (default all).
+       p expr          Same as \"print DBout expr\".
 
-Ability to open pipe to a forked off script for secure pipes in setuid scripts.
+The rules are more consistent about where parens are needed and
+where they are not.  In particular, unary operators and list operators now
+behave like functions if they're called like functions.
 
-File inclusion via
-       do 'foo.pl';
+There are some new quoting mechanisms:
+       $foo = q/"'"'"'"'"'"'"/;
+       $foo = qq/"'"''$bar"''/;
+       $foo = q(hi there);
+       $foo = <<'EOF' x 10;
+       Why, it's the old here-is mechanism!
+       EOF
 
-More file tests, including -t to see if, for instance, stdin is
-a terminal.  File tests now behave in a more correct manner.  You can do
-file tests on filehandles as well as filenames.  The special filetests
--T and -B test a file to see if it's text or binary.
+You can now work with array slices (note the initial @):
+       @foo[1,2,3];
+       @foo{'Sun','Mon','Tue','Wed','Thu','Fri','Sat'} = (1,2,3,4,5,6,7);
+       @foo{split} = (1,1,1,1,1,1,1);
 
-An eof can now be used on each file of the <> input for such purposes
-as resetting the line numbers or appending to each file of an inplace edit.
+There's now a range operator that works in array contexts:
+       for (1..15) { ...
+       @foo[3..5] = ('time','for','all');
+       @foo{'Sun','Mon','Tue','Wed','Thu','Fri','Sat'} = 1..7;
 
-Assignments can now function as lvalues, so you can say things like
-       ($HOST = $host) =~ tr/a-z/A-Z/;
-       ($obj = $src) =~ s/\.c$/.o/;
+You can now reference associative arrays as a whole:
+       %abc = %def;
+       %foo = ('Sun',1,'Mon',2,'Tue',3,'Wed',4,'Thu',5,'Fri',6,'Sat',7);
 
-You can now do certain file operations with a variable which holds the name
-of a filehandle, e.g. open(++$incl,$includefilename); $foo = <$incl>;
+Associative arrays can now be bound to a dbm or ndbm file.  Perl automatically
+caches references to the dbm file for you.
 
-You can now a subroutine indirectly through a scalar variable:
-       $which = 'xyz';
-       do $which('foo');       # calls xyz
+An array or associative array can now be assigned to as part of a list, if
+it's the last thing in the list:
+       ($a,$b,@rest) = split;
 
-Warnings are now available (with -w) on use of uninitialized variables and on
-identifiers that are mentioned only once, and on reference to various
-undefined things.
+An array or associative array may now appear in a local() list.
+       local(%assoc);
+       local(@foo) = @_;
 
-The -S switch causes perl to search the PATH for the script so that you can say
-       eval "exec /usr/bin/perl -S $0 $*"
-               if $running_under_some_shell;
+Array values may now be interpolated into strings:
+       `echo @ARGV`;
+       print "first three = @list[0..2]\n";
+       print "@ENV{keys(ENV)}";
+       ($" is used as the delimiter between array elements)
 
-Reset now resets arrays and associative arrays as well as string variables.
+Array sizes may be interpolated into strings:
+       print "The last element is $#foo.\n";
 
-Assigning off the end of an array now nulls out any intervening values.
+Array values may now be returned from subroutines, evals, and do blocks.
 
-$#foo is now an lvalue.  You can preallocate or truncate arrays, or recover
-values lost to prior truncation.
+Lists of values in formats may now be arbitrary expressions, separated
+by commas.
 
-$#foo is now indexed to $[ properly.
+Subroutine names are now distinguished by prefixing with &.  You can call
+subroutines without using do, and without passing any argument list at all:
+       $foo = &min($a,$b,$c);
+       $num = &myrand;
 
-s/foo/bar/i optimization bug fixed.
+You can use the new -u switch to cause perl to dump core so that you can
+run undump and produce a binary executable image.  Alternately you can
+use the "dump" operator after initializing any variables and such.
 
-The $x = "...$x..."; bug is fixed.
+Perl now optimizes splits that are assigned directly to an array, or
+to a list with fewer elements than the split would produce, or that
+split on a constant string.
 
-The @ary = (1); bug is now fixed.  You can even say @ary = 1;
+Perl now optimizes on end matches such as /foo$/;
 
-$= now returns the correct value.
+Perl now recognizes {n,m} in patterns to match preceding item at least n times
+and no more than m times.  Also recognizes {n,} and {n} to match n or more
+times, or exactly n times.  If { occurs in other than this context it is
+still treated as a normal character.
 
-Several of the larger files are now split into smaller pieces for easier
-compilation.
+Perl now optimizes "next" to avoid unnecessary longjmps and subroutine calls.
 
-Pattern matches evaluated in an array context now return ($1, $2...).
+Perl now optimizes appended input: $_ .= <>;
 
-There is now a wait operator.
+Substitutions are faster if the substituted text is constant, especially
+when substituting at the beginning of a string.  This plus the previous
+optimization let you run down a file comparing multiple lines more
+efficiently. (Basically the equivalents of sed's N and D are faster.)
 
-There is now a sort operator.
+Similarly, combinations of shifts and pushes on the same array are much
+faster now--it doesn't copy all the pointers every time you shift (just
+every n times, where n is approximately the length of the array plus 10,
+more if you pre-extend the array), so you can use an array as a shift
+register much more efficiently:
+       push(@ary,shift(@ary));
+or
+       shift(@ary); push(@ary,<>);
 
-The requirement of parens around certain expressions when taking their value
-has been lifted.  In particular, you can say
-       $x = print "foo","bar";
-       $x = unlink "foo","bar";
-       chdir "foo" || die "Can't chdir to foo\n";
+The shift operator used inside subroutines now defaults to shifting
+the @_ array.  You can still shift ARGV explicitly, of course.
+
+The @_ array which is passed to subroutines is a local array, but the
+elements of it are passed by reference now.  This means that if you
+explicitly modify $_[0], you are actually modifying the first argument
+to the routine.  Assignment to another location (such as the usual
+local($foo) = @_ trick) causes a copy of the value, so this will not
+affect most scripts.  However, if you've modified @_ values in the
+subroutine you could be in for a surprise.  I don't believe most people
+will find this a problem, and the long term efficiency gain is worth
+a little confusion.
+
+Perl now detects sequences of references to the same variable and builds
+switch statements internally wherever reasonable.
+
+The substr function can take offsets from the end of the string.
+
+The substr function can be assigned to in order to change the interior of a
+string in place.
+
+The split function can return as part of the returned array any substrings
+matched as part of the delimiter:
+       split(/([-,])/, '1-10,20')
+returns
+       (1,'-',10,',',20)
+
+If you specify a maximum number of fields to split, the truncation of
+trailing null fields is disabled.
+
+You can now chop lists.
+
+Perl now uses /bin/csh to do filename globbing, if available.  This means
+that filenames with spaces or other strangenesses work right.
+
+Perl can now report multiple syntax errors with a single invocation.
+
+Perl syntax errors now give two tokens of context where reasonable.
+
+Perl will now report the possibility of a runaway multi-line string if
+such a string ends on a line with a syntax error.
+
+The assumed assignment in a while now works in the while modifier as
+well as the while statement.
+
+Perl can now warn you if you use numeric == on non-numeric string values.
+
+New functions:
+       mkdir and rmdir
+       getppid
+       getpgrp and setpgrp
+       getpriority and setpriority
+       chroot
+       ioctl and fcntl
+       flock
+       readlink
+       lstat
+       rindex                  - find last occurrence of substring
+       pack and unpack         - turn structures into arrays and vice versa
+       read                    - just what you think
+       warn                    - like die, only not fatal
+       dbmopen and dbmclose    - bind a dbm file to an associative array
+       dump                    - do core dump so you can undump
+       reverse                 - turns an array value end for end
+        defined                 - does an object exist?
+        undef                   - make an object not exist
+       vec                     - treat string as a vector of small integers
+       fileno                  - return the file descriptor for a handle
+       wantarray               - was subroutine called in array context?
+       opendir
+       readdir
+       telldir
+       seekdir
+       rewinddir
+       closedir
+       syscall
+       socket
+       bind
+       connect
+       listen
+       accept
+       shutdown
+       socketpair
+       getsockname
+       getpeername
+       getsockopt
+       setsockopt
+       getpwnam
+       getpwuid
+       getpwent
+       setpwent
+       endpwent
+       getgrnam
+       getgrgid
+       getgrent
+       setgrent
+       endgrent
+       gethostbyname
+       gethostbyaddr
+       gethostent
+       sethostent
+       endhostent
+       getnetbyname
+       getnetbyaddr
+       getnetent
+       setnetent
+       endnetent
+       getprotobyname
+       getprotobynumber
+       getprotoent
+       setprotoent
+       endprotoent
+       getservbyname
+       getservbyport
+       getservent
+       setservent
+       endservent
+
+Changes to s2p
+--------------
+
+In patterns, s2p now translates \{n,m\} correctly to {n,m}.
+
+In patterns, s2p no longer removes backslashes in front of |.
+
+In patterns, s2p now removes backslashes in front of [a-zA-Z0-9].
+
+S2p now makes use of the location of perl as determined by Configure.
+
+
+Changes to a2p
+--------------
+
+A2p can now accurately translate the "in" operator by using perl's new
+"defined" operator.
+
+A2p can now accurately translate the passing of arrays by reference.
 
-The manual is now not lying when it says that perl is generally faster than
-sed.  I hope.
index 81be140..c3c65ea 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -8,7 +8,7 @@
 # and edit it to reflect your system.  Some packages may include samples
 # of config.h for certain machines, so you might look for one of those.)
 #
-# $Header: Configure,v 2.0.1.1 88/06/28 16:24:02 root Exp $
+# $Header: Configure,v 3.0 89/10/18 15:04:55 lwall Locked $
 #
 # Yes, you may rip this off to use in other distribution packages.
 # (Note: this Configure script was generated automatically.  Rather than
@@ -66,38 +66,108 @@ vi=''
 mailx=''
 mail=''
 cpp=''
+perl=''
+emacs=''
+ls=''
+rmail=''
+sendmail=''
+shar=''
+smail=''
+tbl=''
+troff=''
+nroff=''
+uname=''
+uuname=''
+line=''
+chgrp=''
+chmod=''
+lint=''
+sleep=''
+pr=''
+tar=''
+ln=''
+lpr=''
+lp=''
+touch=''
+make=''
+date=''
 Log=''
 Header=''
 bin=''
-cc=''
+byteorder=''
 contains=''
 cppstdin=''
 cppminus=''
+d_bcmp=''
 d_bcopy=''
 d_charsprf=''
 d_crypt=''
+cryptlib=''
 d_dosuid=''
+d_dup2=''
 d_fchmod=''
 d_fchown=''
+d_fcntl=''
+d_flock=''
 d_getgrps=''
+d_gethent=''
+d_getpgrp=''
+d_getprior=''
+d_htonl=''
 d_index=''
+d_ioctl=''
 d_killpg=''
+d_memcmp=''
 d_memcpy=''
+d_mkdir=''
+d_ndbm=''
+d_odbm=''
+d_readdir=''
 d_rename=''
+d_rmdir=''
 d_setegid=''
 d_seteuid=''
+d_setpgrp=''
+d_setprior=''
+d_setregid=''
+d_setresgid=''
+d_setreuid=''
+d_setresuid=''
 d_setrgid=''
 d_setruid=''
+d_socket=''
+d_sockpair=''
+d_oldsock=''
+socketlib=''
+sockethdr=''
 d_statblks=''
 d_stdstdio=''
-d_strcspn=''
 d_strctcpy=''
 d_symlink=''
+d_syscall=''
 d_tminsys=''
+i_systime=''
+d_varargs=''
 d_vfork=''
 d_voidsig=''
+d_vprintf=''
+d_charvspr=''
 gidtype=''
+i_dirent=''
+d_dirnamlen=''
+i_fcntl=''
+i_grp=''
+i_pwd=''
+d_pwquota=''
+d_pwage=''
+i_sysdir=''
+i_sysioctl=''
+i_varargs=''
+i_vfork=''
+intsize=''
 libc=''
+libdbm=''
+libndir=''
 libnm=''
 mallocsrc=''
 mallocobj=''
@@ -110,11 +180,16 @@ small=''
 medium=''
 large=''
 huge=''
+optimize=''
 ccflags=''
 ldflags=''
+cc=''
+libs=''
 n=''
 c=''
 package=''
+randbits=''
+sig_name=''
 spitshell=''
 shsharp=''
 sharpbang=''
@@ -123,6 +198,7 @@ stdchar=''
 uidtype=''
 voidflags=''
 defvoidused=''
+lib=''
 privlib=''
 CONFIG=''
 : set package name
@@ -135,7 +211,7 @@ echo " "
 
 define='define'
 undef='undef'
-libpth='/usr/lib /usr/local/lib /lib'
+libpth='/usr/lib /usr/local/lib /usr/lib/386 /usr/lib/large /lib /lib/386 /lib/large /usr/lib/small /lib/small'
 smallmach='pdp11 i8086 z8000 i80286 iAPX286'
 rmlist='kit[1-9]isdone kit[1-9][0-9]isdone'
 trap 'echo " "; rm -f $rmlist; exit 1' 1 2 3
@@ -149,13 +225,21 @@ if test -f /etc/unixtovms.exe; then
     eunicefix=/etc/unixtovms.exe
 fi
 
+: Now test for existence of everything in MANIFEST
+
+echo "First let's make sure your kit is complete.  Checking..."
+(cd ..; awk '' `awk '$1 !~ /PACKINGLIST/ {print $1}' MANIFEST` >/dev/null || kill $$)
+echo " "
+
 attrlist="mc68000 sun gcos unix ibm gimpel interdata tss os mert pyr"
 attrlist="$attrlist vax pdp11 i8086 z8000 u3b2 u3b5 u3b20 u3b200"
+attrlist="$attrlist hpux hp9000s300 hp9000s500 hp9000s800"
 attrlist="$attrlist ns32000 ns16000 iAPX286 mc300 mc500 mc700 sparc"
 attrlist="$attrlist nsc32000 sinix xenix venix posix ansi M_XENIX"
-attrlist="$attrlist $mc68k __STDC__"
-pth="/usr/ucb /bin /usr/bin /usr/local /usr/local/bin /usr/lbin /etc /usr/lib /lib"
-d_newshome="../../NeWS"
+attrlist="$attrlist $mc68k __STDC__ UTS M_I8086 M_I186 M_I286 M_I386"
+attrlist="$attrlist i186"
+pth="/usr/ucb /bin /usr/bin /usr/local /usr/local/bin /usr/lbin /usr/plx /usr/5bin /vol/local/bin /etc /usr/lib /lib /usr/local/lib /sys5.3/bin /sys5.3/usr/bin /bsd4.3/bin /bsd4.3/usr/bin /bsd4.3/usr/ucb"
+d_newshome="/usr/NeWS"
 defvoidused=7
 
 : some greps do not return status, grrr.
@@ -322,24 +406,25 @@ EOSC
 chmod +x loc
 $eunicefix loc
 loclist="
-expr
-sed
-echo
 cat
-rm
-mv
 cp
-tr
+echo
+expr
+grep
 mkdir
+mv
+rm
+sed
 sort
+tr
 uniq
-grep
 "
 trylist="
-test
-egrep
 Mcc
 cpp
+egrep
+test
+uname
 "
 for file in $loclist; do
     xxx=`loc $file $file $pth`
@@ -382,14 +467,10 @@ test)
     echo "Hopefully test is built into your sh."
     ;;
 /bin/test)
-    echo " "
-    dflt=n
-    rp="Is your "'"'"test"'"'" built into sh? [$dflt] (OK to guess)"
-    echo $n "$rp $c"
-    . myread
-    case "$ans" in
-    y*) test=test ;;
-    esac
+    if sh -c "PATH= test true" >/dev/null 2>&1; then
+       echo "Using the test built into your sh."
+       test=test
+    fi
     ;;
 *)
     test=test
@@ -432,19 +513,37 @@ esac
 rmlist="$rmlist loc"
 
 : get list of predefined functions in a handy place
+if $test -n "$uname"; then
+       os=`$uname -s`
+else
+       os=unknown
+fi
 echo " "
 if test -f /lib/libc.a; then
     echo "Your C library is in /lib/libc.a.  You're normal."
     libc=/lib/libc.a
 else
-    ans=`loc libc.a blurfl/dyick $libpth`
-    if test ! -f $ans; then
+    if test "$os" = DomainOS ; then
+       ans=`loc libc blurfl/dyick $libpth`
+    else
+       ans=`loc libc.a blurfl/dyick $libpth`
+    fi
+    if test ! -f "$ans"; then
        ans=`loc clib blurfl/dyick $libpth`
     fi
-    if test ! -f $ans; then
+    if test ! -f "$ans"; then
        ans=`loc libc blurfl/dyick $libpth`
     fi
-    if test -f $ans; then
+    if test ! -f "$ans"; then
+       ans=`loc Slibc.a blurfl/dyick /usr/lib/386 /lib/386 $libpth`
+    fi
+    if test ! -f "$ans"; then
+       ans=`loc Mlibc.a blurfl/dyick $libpth`
+    fi
+    if test ! -f "$ans"; then
+       ans=`loc Llibc.a blurfl/dyick $libpth`
+    fi
+    if test -f "$ans"; then
        echo "Your C library is in $ans, of all places."
        libc=$ans
     else
@@ -469,25 +568,32 @@ EOM
 fi
 echo " "
 $echo $n "Extracting names from $libc for later perusal...$c"
-nm $libc 2>/dev/null | sed -n -e 's/^.* T _//p' -e 's/^.* T //p' > libc.list
+nm $libc 2>/dev/null >libc.tmp
+$sed -n -e 's/^.* [AT]  *_[_.]*//p' -e 's/^.* [AT] //p' <libc.tmp >libc.list
 if $contains '^printf$' libc.list >/dev/null 2>&1; then
     echo "done"
 else
-    nm $libc 2>/dev/null | sed -n -e 's/^.* D _//p' -e 's/^.* D //p' > libc.list
+    if test "$os" = DomainOS ; then
+        $sed -n -e 's/^__*//' -e 's/^\([a-zA-Z_0-9$]*\).*xtern.*/\1/p' <libc.tmp >libc.list
+    else
+       $sed -n -e 's/^.* D __*//p' -e 's/^.* D //p' <libc.tmp >libc.list
+    fi
+    $contains '^printf$' libc.list >/dev/null 2>&1 || \
+       $sed -n -e 's/^_//' \
+             -e 's/^\([a-zA-Z_0-9]*\).*xtern.*text.*/\1/p' <libc.tmp >libc.list
     if $contains '^printf$' libc.list >/dev/null 2>&1; then
        echo "done"
     else
        echo " "
        echo "nm didn't seem to work right."
        echo "Trying ar instead..."
-       rmlist="$rmlist libc.tmp"
        if ar t $libc > libc.tmp; then
-           sed -e 's/\.o$//' < libc.tmp > libc.list
+           $sed -e 's/\.o$//' < libc.tmp > libc.list
            echo "Ok."
        else
            echo "ar didn't seem to work right."
            echo "Maybe this is a Cray...trying bld instead..."
-           if bld t $libc | sed -e 's/.*\///' -e 's/\.o:.*$//' > libc.list; then
+           if bld t $libc | $sed -e 's/.*\///' -e 's/\.o:.*$//' > libc.list; then
                echo "Ok."
            else
                echo "That didn't work either.  Giving up."
@@ -496,12 +602,19 @@ else
        fi
     fi
 fi
-rmlist="$rmlist libc.list"
+
+inlibc='echo " ";
+if $contains "^$1\$" libc.list >/dev/null 2>&1;
+then echo "$1() found"; eval "$2=$define";
+else echo "$1() not found"; eval "$2=$undef"; fi'
+
+rmlist="$rmlist libc.tmp libc.list"
 
 : make some quick guesses about what we are up against
 echo " "
 $echo $n "Hmm...  $c"
-if $contains SIGTSTP /usr/include/signal.h >/dev/null 2>&1 ; then
+cat /usr/include/signal.h /usr/include/sys/signal.h >foo
+if $contains SIGTSTP foo >/dev/null 2>&1 ; then
     echo "Looks kind of like a BSD system, but we'll see..."
     echo exit 0 >bsd
     echo exit 1 >usg
@@ -557,6 +670,7 @@ else
 fi
 chmod +x bsd usg v7 eunice venix
 $eunicefix bsd usg v7 eunice venix
+rm -rf foo
 rmlist="$rmlist bsd usg v7 eunice venix xenix"
 
 : see if sh knows # comments
@@ -619,287 +733,951 @@ else
 fi
 rm -f try today
 
-: see how we invoke the C preprocessor
-echo " "
-echo "Now, how can we feed standard input to your C preprocessor..."
-cat <<'EOT' >testcpp.c
-#define ABC abc
-#define XYZ xyz
-ABC.XYZ
-EOT
-echo 'Maybe "'$cpp'" will work...'
-$cpp <testcpp.c >testcpp.out 2>&1
-if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-    echo "Yup, it does."
-    cppstdin="$cpp"
-    cppminus='';
-else
-    echo 'Nope, maybe "'$cpp' -" will work...'
-    $cpp - <testcpp.c >testcpp.out 2>&1
-    if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-       echo "Yup, it does."
-       cppstdin="$cpp"
-       cppminus='-';
+: set up shell script to do ~ expansion
+cat >filexp <<EOSS
+$startsh
+: expand filename
+case "\$1" in
+ ~/*|~)
+    echo \$1 | $sed "s|~|\${HOME-\$LOGDIR}|"
+    ;;
+ ~*)
+    if $test -f /bin/csh; then
+       /bin/csh -f -c "glob \$1"
+       echo ""
     else
-       echo 'No such luck...maybe "cc -E" will work...'
-       cc -E <testcpp.c >testcpp.out 2>&1
-       if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-           echo "It works!"
-           cppstdin='cc -E'
-           cppminus='';
-       else
-           echo 'Nixed again...maybe "cc -E -" will work...'
-           cc -E - <testcpp.c >testcpp.out 2>&1
-           if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-               echo "Hooray, it works!  I was beginning to wonder."
-               cppstdin='cc -E'
-               cppminus='-';
-           else
-               echo 'Nope...maybe "cc -P" will work...'
-               cc -P <testcpp.c >testcpp.out 2>&1
-               if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-                   echo "Yup, that does."
-                   cppstdin='cc -P'
-                   cppminus='';
-               else
-                   echo 'Nope...maybe "cc -P -" will work...'
-                   cc -P - <testcpp.c >testcpp.out 2>&1
-                   if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-                       echo "Yup, that does."
-                       cppstdin='cc -P'
-                       cppminus='-';
-                   else
-                       echo 'Hmm...perhaps you already told me...'
-                       case "$cppstdin" in
-                       '') ;;
-                       *) $cppstdin $cppminus <testcpp.c >testcpp.out 2>&1;;
-                       esac
-                       if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-                           echo "Hooray, you did!  I was beginning to wonder."
-                       else
-                           echo 'Uh-uh.  Time to get fancy...'
-                           echo 'Trying (cat >/tmp/$$.c; cc -E /tmp/$$.c; rm /tmp/$$.c)'
-                           cppstdin='(cat >/tmp/$$.c; cc -E /tmp/$$.c; rm /tmp/$$.c)'
-                           cppminus='';
-                           $cppstdin <testcpp.c >testcpp.out 2>&1
-                           if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-                               echo "Eureka!."
-                           else
-                               dflt=blurfl
-                               $echo $n "No dice.  I can't find a C preprocessor.  Name one: $c"
-                               rp='Name a C preprocessor:'
-                               . myread
-                               cppstdin="$ans"
-                               $cppstdin <testcpp.c >testcpp.out 2>&1
-                               if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
-                                   echo "OK, that will do."
-                               else
-                                   echo "Sorry, I can't get that to work.  Go find one."
-                                   exit 1
-                               fi
-                           fi
-                       fi
-                   fi
-               fi
-           fi
+       name=\`$expr x\$1 : '..\([^/]*\)'\`
+       dir=\`$sed -n -e "/^\${name}:/{s/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\).*"'\$'"/\1/" -e p -e q -e '}' </etc/passwd\`
+       if $test ! -d "\$dir"; then
+           me=\`basename \$0\`
+           echo "\$me: can't locate home directory for: \$name" >&2
+           exit 1
        fi
-    fi
-fi
-rm -f testcpp.c testcpp.out
-
-: see if bcopy exists
-echo " "
-if $contains '^bcopy$' libc.list >/dev/null 2>&1; then
-    echo 'bcopy() found.'
-    d_bcopy="$define"
-else
-    echo 'bcopy() not found.'
-    d_bcopy="$undef"
-fi
-
-: see if sprintf is declared as int or pointer to char
-echo " "
-cat >.ucbsprf.c <<'EOF'
-main() { char buf[10]; exit((unsigned long)sprintf(buf,"%s","foo") > 10L); }
-EOF
-if cc .ucbsprf.c -o .ucbsprf >/dev/null 2>&1 && .ucbsprf; then
-    echo "Your sprintf() returns (int)."
-    d_charsprf="$undef"
-else
-    echo "Your sprintf() returns (char*)."
-    d_charsprf="$define"
-fi
-/bin/rm -f .ucbsprf.c .ucbsprf
-
-: see if crypt exists
-echo " "
-if $contains '^crypt$' libc.list >/dev/null 2>&1; then
-    echo 'crypt() found.'
-    d_crypt="$define"
-else
-    echo 'crypt() not found.'
-    d_crypt="$undef"
-fi
-
-: now see if they want to do setuid emulation
-case "$d_dosuid" in
-'') if bsd; then
-       dflt=y
-    else
-       dflt=n
+       case "\$1" in
+       */*)
+           echo \$dir/\`$expr x\$1 : '..[^/]*/\(.*\)'\`
+           ;;
+       *)
+           echo \$dir
+           ;;
+       esac
     fi
     ;;
-*undef*) dflt=n;;
-*) dflt=y;;
-esac
-cat <<EOM
-Some sites have disabled setuid #! scripts because of a bug in the kernel
-that prevents them from being secure.  If you are on such a system, the
-setuid/setgid bits on scripts are currently useless.  It is possible for
-$package to detect those bits and emulate setuid/setgid in a secure fashion
-until a better solution is devised for the kernel problem.
-
-EOM
-rp="Do you want to do setuid/setgid emulation? [$dflt]"
-echo $n "$rp $c"
-. myread
-case "$ans" in
-'') $ans="$dflt";;
-esac
-case "$ans" in
-y*)  d_dosuid="$define";;
-*) d_dosuid="$undef";;
+*)
+    echo \$1
+    ;;
 esac
+EOSS
+chmod +x filexp
+$eunicefix filexp
 
-: see if fchmod exists
-echo " "
-if $contains '^fchmod$' libc.list >/dev/null 2>&1; then
-    echo 'fchmod() found.'
-    d_fchmod="$define"
-else
-    echo 'fchmod() not found.'
-    d_fchmod="$undef"
-fi
-
-: see if fchown exists
-echo " "
-if $contains '^fchown$' libc.list >/dev/null 2>&1; then
-    echo 'fchown() found.'
-    d_fchown="$define"
-else
-    echo 'fchown() not found.'
-    d_fchown="$undef"
-fi
-
-: see if getgroups exists
-echo " "
-if $contains '^getgroups$' libc.list >/dev/null 2>&1; then
-    echo 'getgroups() found.'
-    d_getgrps="$define"
-else
-    echo 'getgroups() not found.'
-    d_getgrps="$undef"
-fi
-
-: index or strcpy
-echo " "
-case "$d_index" in
-n) dflt=n;;
-*) dflt=y;;
+: determine where public executables go
+case "$bin" in
+'')
+    dflt=`loc . /bin /usr/local/bin /usr/lbin /usr/local /usr/bin`
+    ;;
+*)  dflt="$bin"
+    ;;
 esac
-if $contains '^index$' libc.list >/dev/null 2>&1 ; then
-    if $contains '^strchr$' libc.list >/dev/null 2>&1 ; then
-       echo "Your system has both index() and strchr().  Shall I use"
-       rp="index() rather than strchr()? [$dflt]"
+cont=true
+while $test "$cont" ; do
+    echo " "
+    rp="Where do you want to put the public executables? [$dflt]"
+    $echo $n "$rp $c"
+    . myread
+    bin="$ans"
+    bin=`filexp $bin`
+    if test -d $bin; then
+       cont=''
+    else
+       case "$fastread" in
+       yes) dflt=y;;
+       *) dflt=n;;
+       esac
+       rp="Directory $bin doesn't exist.  Use that name anyway? [$dflt]"
        $echo $n "$rp $c"
        . myread
+       dflt=''
        case "$ans" in
-           n*) d_index="$define" ;;
-           *)  d_index="$undef" ;;
+       y*) cont='';;
        esac
-    else
-       d_index="$undef"
-       echo "index() found."
     fi
-else
-    if $contains '^strchr$' libc.list >/dev/null 2>&1 ; then
-       d_index="$define"
-       echo "strchr() found."
-    else
-       echo "No index() or strchr() found!"
-       d_index="$undef"
-    fi
-fi
-
-: see if killpg exists
-echo " "
-if $contains '^killpg$' libc.list >/dev/null 2>&1; then
-    echo 'killpg() found.'
-    d_killpg="$define"
-else
-    echo 'killpg() not found.'
-    d_killpg="$undef"
-fi
+done
 
-: see if memcpy exists
+: determine where manual pages go
+$cat <<EOM
+  
+$package has manual pages that need to be installed in source form.
+EOM
+case "$mansrc" in
+'')
+    dflt=`loc . /usr/man/man1 /usr/man/mann /usr/man/manl /usr/man/local/man1 /usr/man/u_man/man1 /usr/man/man1 /usr/man/man.L`
+    ;;
+*)  dflt="$mansrc"
+    ;;
+esac
+cont=true
+while $test "$cont" ; do
+    echo " "
+    rp="Where do the manual pages (source) go? [$dflt]"
+    $echo $n "$rp $c"
+    . myread
+    mansrc=`filexp "$ans"`
+    if $test -d "$mansrc"; then
+       cont=''
+    else
+       if $test "$fastread" = yes; then
+           dflt=y
+       else
+           dflt=n
+       fi
+       rp="Directory $mansrc doesn't exist.  Use that name anyway? [$dflt]"
+       $echo $n "$rp $c"
+       . myread
+       dflt=''
+       case "$ans" in
+       y*) cont='';;
+       esac
+    fi
+done
+case "$mansrc" in
+*l)
+    manext=l
+    ;;
+*n)
+    manext=n
+    ;;
+*o)
+    manext=l
+    ;;
+*p)
+    manext=n
+    ;;
+*C)
+    manext=C
+    ;;
+*L)
+    manext=L
+    ;;
+*)
+    manext=1
+    ;;
+esac
+
+: see what memory models we can support
+case "$models" in
+'')
+    : We may not use Cppsym or we get a circular dependency through cc.
+    : But this should work regardless of which cc we eventually use.
+    cat >pdp11.c <<'EOP'
+main() {
+#ifdef pdp11
+    exit(0);
+#else
+    exit(1);
+#endif
+}
+EOP
+    cc -o pdp11 pdp11.c >/dev/null 2>&1
+    if pdp11 2>/dev/null; then
+       dflt='unsplit split'
+    else
+       ans=`loc . X /lib/small /lib/large /usr/lib/small /usr/lib/large /lib/medium /usr/lib/medium /lib/huge`
+       case "$ans" in
+       X) dflt='none';;
+       *)  if $test -d /lib/small || $test -d /usr/lib/small; then
+               dflt='small'
+           else
+               dflt=''
+           fi
+           if $test -d /lib/medium || $test -d /usr/lib/medium; then
+               dflt="$dflt medium"
+           fi
+           if $test -d /lib/large || $test -d /usr/lib/large; then
+               dflt="$dflt large"
+           fi
+           if $test -d /lib/huge || $test -d /usr/lib/huge; then
+               dflt="$dflt huge"
+           fi
+       esac
+    fi
+    ;;
+*)  dflt="$models" ;;
+esac
+$cat <<EOM
+Some systems have different model sizes.  On most systems they are called
+small, medium, large, and huge.  On the PDP11 they are called unsplit and
+split.  If your system doesn't support different memory models, say "none".
+If you wish to force everything to one memory model, say "none" here and
+put the appropriate flags later when it asks you for other cc and ld flags.
+Venix systems may wish to put "none" and let the compiler figure things out.
+(In the following question multiple model names should be space separated.)
+
+EOM
+rp="Which models are supported? [$dflt]"
+$echo $n "$rp $c"
+. myread
+models="$ans"
+
+case "$models" in
+none)
+    small=''
+    medium=''
+    large=''
+    huge=''
+    unsplit=''
+    split=''
+    ;;
+*split)
+    case "$split" in
+    '') 
+       if $contains '\-i' $mansrc/man1/ld.1 >/dev/null 2>&1 || \
+          $contains '\-i' $mansrc/man1/cc.1 >/dev/null 2>&1; then
+           dflt='-i'
+       else
+           dflt='none'
+       fi
+       ;;
+    *) dflt="$split";;
+    esac
+    rp="What flag indicates separate I and D space? [$dflt]"
+    $echo $n "$rp $c"
+    . myread
+    case "$ans" in
+    none) ans='';;
+    esac
+    split="$ans"
+    unsplit=''
+    ;;
+*large*|*small*|*medium*|*huge*)
+    case "$models" in
+    *large*)
+       case "$large" in
+       '') dflt='-Ml';;
+       *) dflt="$large";;
+       esac
+       rp="What flag indicates large model? [$dflt]"
+       $echo $n "$rp $c"
+       . myread
+       case "$ans" in
+       none) ans='';
+       esac
+       large="$ans"
+       ;;
+    *) large='';;
+    esac
+    case "$models" in
+    *huge*)
+       case "$huge" in
+       '') dflt='-Mh';;
+       *) dflt="$huge";;
+       esac
+       rp="What flag indicates huge model? [$dflt]"
+       $echo $n "$rp $c"
+       . myread
+       case "$ans" in
+       none) ans='';
+       esac
+       huge="$ans"
+       ;;
+    *) huge="$large";;
+    esac
+    case "$models" in
+    *medium*)
+       case "$medium" in
+       '') dflt='-Mm';;
+       *) dflt="$medium";;
+       esac
+       rp="What flag indicates medium model? [$dflt]"
+       $echo $n "$rp $c"
+       . myread
+       case "$ans" in
+       none) ans='';
+       esac
+       medium="$ans"
+       ;;
+    *) medium="$large";;
+    esac
+    case "$models" in
+    *small*)
+       case "$small" in
+       '') dflt='none';;
+       *) dflt="$small";;
+       esac
+       rp="What flag indicates small model? [$dflt]"
+       $echo $n "$rp $c"
+       . myread
+       case "$ans" in
+       none) ans='';
+       esac
+       small="$ans"
+       ;;
+    *) small='';;
+    esac
+    ;;
+*)
+    echo "Unrecognized memory models--you may have to edit Makefile.SH"
+    ;;
+esac
+
+: see if we need a special compiler
+echo " "
+if usg; then
+    case "$cc" in
+    '')
+       case "$Mcc" in
+       /*) dflt='Mcc'
+           ;;
+       *)
+           case "$large" in
+           -M*)
+               dflt='cc'
+               ;;
+           *)
+               if $contains '\-M' $mansrc/cc.1 >/dev/null 2>&1 ; then
+                   dflt='cc -M'
+               else
+                   dflt='cc'
+               fi
+               ;;
+           esac
+           ;;
+       esac
+       ;;
+    *)  dflt="$cc";;
+    esac
+    $cat <<'EOM'
+  
+On some systems the default C compiler will not resolve multiple global
+references that happen to have the same name.  On some such systems the
+"Mcc" command may be used to force these to be resolved.  On other systems
+a "cc -M" command is required.  (Note that the -M flag on other systems
+indicates a memory model to use!)  If you have the Gnu C compiler, you
+might wish to use that instead.  What command will force resolution on
+EOM
+    $echo $n "this system? [$dflt] $c"
+    rp="Command to resolve multiple refs? [$dflt]"
+    . myread
+    cc="$ans"
+else
+    case "$cc" in
+    '') dflt=cc;;
+    *) dflt="$cc";;
+    esac
+    rp="Use which C compiler? [$dflt]"
+    $echo $n "$rp $c"
+    . myread
+    cc="$ans"
+fi
+case "$cc" in
+gcc*) cpp=`loc gcc-cpp $cpp $pth`;;
+esac
+
+: determine optimize, if desired, or use for debug flag also
+case "$optimize" in
+' ') dflt="none"
+     ;;
+'') dflt="-O";
+    ;;
+*)  dflt="$optimize"
+    ;;
+esac
+cat <<EOH
+Some C compilers have problems with their optimizers, by default, $package
+compiles with the -O flag to use the optimizer.  Alternately, you might
+want to use the symbolic debugger, which uses the -g flag (on traditional
+Unix systems).  Either flag can be specified here.  To use neither flag,
+specify the word "none".
+  
+EOH
+rp="What optimizer/debugger flag should be used? [$dflt]"
+$echo $n "$rp $c"
+. myread
+optimize="$ans"
+case "$optimize" in
+'none') optimize=" "
+     ;;
+esac
+
+case "$ccflags" in
+'') case "$cc" in
+    gcc) dflt='-fpcc_struct_return';;
+    *) dflt='none';;
+    esac
+    ;;
+*) dflt="$ccflags";;
+esac
+echo " "
+rp="Any additional cc flags? [$dflt]"
+$echo $n "$rp $c"
+. myread
+case "$ans" in
+none) ans='';
+esac
+ccflags="$ans"
+
+case "$ldflags" in
+'') if venix; then
+       dflt='-i -z'
+    else
+       dflt='none'
+    fi
+    ;;
+*) dflt="$ldflags";;
+esac
+echo " "
+rp="Any additional ld flags (NOT including libraries)? [$dflt]"
+$echo $n "$rp $c"
+. myread
+case "$ans" in
+none) ans='';
+esac
+ldflags="$ans"
+rmlist="$rmlist pdp11"
+
+case "$libs" in
+'') dflt='none';;
+*) dflt="$libs";;
+esac
+
+$cat <<EOM
+Some versions of Unix support shared libraries, which make
+executables smaller but make load time slightly longer.
+
+On some systems, mostly newer Unix System V's, the shared library
+is included by putting the option "-lc_s" as the last thing on the
+cc command line when linking.  Other systems use shared libraries
+by default.  There may be other libraries needed to compile $package
+on your machine as well.  If your system needs the "-lc_s" option,
+include it here.  Include any other special libraries here as well.
+EOM
+
+echo " "
+rp="Any additional libraries? [$dflt]"
+$echo $n "$rp $c"
+. myread
+case "$ans" in
+none) ans='';
+esac
+libs="$ans"
+
+: check for ordering of bytes in a long
+case "$byteorder" in
+'')
+cat <<'EOM'
+  
+In the following, larger digits indicate more significance.  A big-endian
+machine like a Pyramid or a Motorola 680?0 chip will come out to 4321.  A
+little-endian machine like a Vax or an Intel 80?86 chip would be 1234.  Other
+machines may have weird orders like 3412.  If the test program works the
+default is probably right.  I'm now running the test program...
+EOM
+    $cat >try.c <<'EOCP'
+#include <stdio.h>
+main()
+{
+    int i;
+    union {
+       unsigned long l;
+       char c[4];
+    } u;
+
+    u.l = 0x04030201;
+    printf("%c%c%c%c\n", u.c[0]+'0', u.c[1]+'0', u.c[2]+'0', u.c[3]+'0');
+}
+EOCP
+    if $cc try.c -o try >/dev/null 2>&1 ; then
+       dflt=`try`
+       case "$dflt" in
+       ????) echo "(The test program ran ok.)";;
+       *) echo "(The test program didn't run right for some reason.)";;
+       esac
+    else
+       dflt='4321'
+       echo "(I can't seem to compile the test program.  Guessing big-endian...)"
+    fi
+    ;;
+*)
+    echo " "
+    dflt="$byteorder"
+    ;;
+esac
+rp="What is the order of bytes in a long? [$dflt]"
+$echo $n "$rp $c"
+. myread
+byteorder="$ans"
+$rm -f try.c try
+
+: see how we invoke the C preprocessor
+echo " "
+echo "Now, how can we feed standard input to your C preprocessor..."
+cat <<'EOT' >testcpp.c
+#define ABC abc
+#define XYZ xyz
+ABC.XYZ
+EOT
+echo 'Maybe "'"$cc"' -E" will work...'
+$cc -E <testcpp.c >testcpp.out 2>&1
+if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+    echo "Yup, it does."
+    cppstdin="$cc -E"
+    cppminus='';
+else
+    echo 'Nope, maybe "'$cpp'" will work...'
+    $cpp <testcpp.c >testcpp.out 2>&1
+    if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+       echo "Yup, it does."
+       cppstdin="$cpp"
+       cppminus='';
+    else
+       echo 'No such luck...maybe "'$cpp' -" will work...'
+       $cpp - <testcpp.c >testcpp.out 2>&1
+       if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+           echo "It works!"
+           cppstdin="$cpp"
+           cppminus='-';
+       else
+           echo 'Nixed again...maybe "'"$cc"' -E -" will work...'
+           $cc -E - <testcpp.c >testcpp.out 2>&1
+           if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+               echo "Hooray, it works!  I was beginning to wonder."
+               cppstdin="$cc -E"
+               cppminus='-';
+           else
+               echo 'Nope...maybe "'"$cc"' -P" will work...'
+               $cc -P <testcpp.c >testcpp.out 2>&1
+               if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+                   echo "Yup, that does."
+                   cppstdin="$cc -P"
+                   cppminus='';
+               else
+                   echo 'Nope...maybe "'"$cc"' -P -" will work...'
+                   $cc -P - <testcpp.c >testcpp.out 2>&1
+                   if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+                       echo "Yup, that does."
+                       cppstdin="$cc -P"
+                       cppminus='-';
+                   else
+                       echo 'Hmm...perhaps you already told me...'
+                       case "$cppstdin" in
+                       '') ;;
+                       *) $cppstdin $cppminus <testcpp.c >testcpp.out 2>&1;;
+                       esac
+                       if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+                           echo "Hooray, you did!  I was beginning to wonder."
+                       else
+                           echo 'Uh-uh.  Time to get fancy...'
+                           cd ..
+                           echo 'Trying (cat >/tmp/$$.c; '"$cc"' -E /tmp/$$.c; rm /tmp/$$.c)'
+                           echo 'cat >/tmp/$$.c; '"$cc"' -E /tmp/$$.c; rm /tmp/$$.c' >cppstdin
+                           chmod 755 cppstdin
+                           cppstdin=`pwd`/cppstdin
+                           cppminus='';
+                           cd UU
+                           $cppstdin <testcpp.c >testcpp.out 2>&1
+                           if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+                               echo "Eureka!."
+                           else
+                               dflt=blurfl
+                               $echo $n "No dice.  I can't find a C preprocessor.  Name one: $c"
+                               rp='Name a C preprocessor:'
+                               . myread
+                               cppstdin="$ans"
+                               $cppstdin <testcpp.c >testcpp.out 2>&1
+                               if $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
+                                   echo "OK, that will do."
+                               else
+                                   echo "Sorry, I can't get that to work.  Go find one."
+                                   exit 1
+                               fi
+                           fi
+                       fi
+                   fi
+               fi
+           fi
+       fi
+    fi
+fi
+rm -f testcpp.c testcpp.out
+
+: see if bcmp exists
+set bcmp d_bcmp
+eval $inlibc
+
+: see if bcopy exists
+set bcopy d_bcopy
+eval $inlibc
+
+: see if sprintf is declared as int or pointer to char
+echo " "
+cat >.ucbsprf.c <<'EOF'
+main() { char buf[10]; exit((unsigned long)sprintf(buf,"%s","foo") > 10L); }
+EOF
+if $cc $ccflags .ucbsprf.c -o .ucbsprf >/dev/null 2>&1 && .ucbsprf; then
+    echo "Your sprintf() returns (int)."
+    d_charsprf="$undef"
+else
+    echo "Your sprintf() returns (char*)."
+    d_charsprf="$define"
+fi
+/bin/rm -f .ucbsprf.c .ucbsprf
+
+: see if vprintf exists
+echo " "
+if $contains '^vprintf$' libc.list >/dev/null 2>&1; then
+    echo 'vprintf() found.'
+    d_vprintf="$define"
+    cat >.ucbsprf.c <<'EOF'
+#include <varargs.h>
+
+main() { xxx("foo"); }
+
+xxx(va_alist)
+va_dcl
+{
+    va_list args;
+    char buf[10];
+
+    va_start(args);
+    exit((unsigned long)vsprintf(buf,"%s",args) > 10L);
+}
+EOF
+    if $cc $ccflags .ucbsprf.c -o .ucbsprf >/dev/null 2>&1 && .ucbsprf; then
+       echo "Your vsprintf() returns (int)."
+       d_charvspr="$undef"
+    else
+       echo "Your vsprintf() returns (char*)."
+       d_charvspr="$define"
+    fi
+    /bin/rm -f .ucbsprf.c .ucbsprf
+else
+    echo 'vprintf() not found.'
+    d_vprintf="$undef"
+    d_charvspr="$undef"
+fi
+
+: see if crypt exists
+echo " "
+if $contains '^crypt$' libc.list >/dev/null 2>&1; then
+    echo 'crypt() found.'
+    d_crypt="$define"
+    cryptlib=''
+else
+    cryptlib=`loc Slibcrypt.a "" /lib/386 /lib`
+    if $test -z "$cryptlib"; then
+       cryptlib=`loc Mlibcrypt.a "" /lib/386 /lib`
+    else
+       cryptlib=-lcrypt
+    fi
+    if $test -z "$cryptlib"; then
+       cryptlib=`loc Llibcrypt.a "" /lib/386 /lib`
+    else
+       cryptlib=-lcrypt
+    fi
+    if $test -z "$cryptlib"; then
+       cryptlib=`loc libcrypt.a "" $libpth`
+    else
+       cryptlib=-lcrypt
+    fi
+    if $test -z "$cryptlib"; then
+       echo 'crypt() not found.'
+       d_crypt="$undef"
+    else
+       d_crypt="$define"
+    fi
+fi
+
+: see if this is a dirent system
+echo " "
+if $test -r /usr/include/dirent.h ; then
+    i_dirent="$define"
+    echo "dirent.h found."
+    if $contains 'd_namlen' /usr/include/sys/dirent.h >/dev/null 2>&1; then
+       d_dirnamlen="$define"
+    else
+       d_dirnamlen="$undef"
+    fi
+else
+    i_dirent="$undef"
+    d_dirnamlen="$define"
+    echo "No dirent.h found."
+fi
+
+: now see if they want to do setuid emulation
+case "$d_dosuid" in
+'') dflt=n;;
+*undef*) dflt=n;;
+*) dflt=y;;
+esac
+cat <<EOM
+Some sites have disabled setuid #! scripts because of a bug in the kernel
+that prevents them from being secure.  If you are on such a system, the
+setuid/setgid bits on scripts are currently useless.  It is possible for
+$package to detect those bits and emulate setuid/setgid in a secure fashion
+until a better solution is devised for the kernel problem.
+
+EOM
+rp="Do you want to do setuid/setgid emulation? [$dflt]"
+echo $n "$rp $c"
+. myread
+case "$ans" in
+'') $ans="$dflt";;
+esac
+case "$ans" in
+y*)  d_dosuid="$define";;
+*) d_dosuid="$undef";;
+esac
+
+: see if dup2 exists
+set dup2 d_dup2
+eval $inlibc
+
+: see if fchmod exists
+set fchmod d_fchmod
+eval $inlibc
+
+: see if fchown exists
+set fchown d_fchown
+eval $inlibc
+
+: see if this is an fcntl system
+echo " "
+if $test -r /usr/include/fcntl.h ; then
+    d_fcntl="$define"
+    echo "fcntl.h found."
+else
+    d_fcntl="$undef"
+    echo "No fcntl.h found, but that's ok."
+fi
+
+: see if flock exists
+set flock d_flock
+eval $inlibc
+
+: see if getgroups exists
+set getgroups d_getgrps
+eval $inlibc
+
+: see if gethostent exists
+set gethostent d_gethent
+eval $inlibc
+
+: see if getpgrp exists
+set getpgrp d_getpgrp
+eval $inlibc
+
+: see if getpriority exists
+set getpriority d_getprior
+eval $inlibc
+
+: see if htonl exists
+set htonl d_htonl
+eval $inlibc
+
+: index or strcpy
 echo " "
-if $contains '^memcpy$' libc.list >/dev/null 2>&1; then
-    echo 'memcpy() found.'
-    d_memcpy="$define"
+case "$d_index" in
+n) dflt=n;;
+*) dflt=y;;
+esac
+if $contains '^index$' libc.list >/dev/null 2>&1 ; then
+    if $contains '^strchr$' libc.list >/dev/null 2>&1 ; then
+       echo "Your system has both index() and strchr().  Shall I use"
+       rp="index() rather than strchr()? [$dflt]"
+       $echo $n "$rp $c"
+       . myread
+       case "$ans" in
+           n*) d_index="$define" ;;
+           *)  d_index="$undef" ;;
+       esac
+    else
+       d_index="$undef"
+       echo "index() found."
+    fi
 else
-    echo 'memcpy() not found.'
-    d_memcpy="$undef"
+    if $contains '^strchr$' libc.list >/dev/null 2>&1 ; then
+       d_index="$define"
+       echo "strchr() found."
+    else
+       echo "No index() or strchr() found!"
+       d_index="$undef"
+    fi
 fi
 
-: see if rename exists
+: see if ioctl defs are in sgtty/termio or sys/ioctl
 echo " "
-if $contains '^rename$' libc.list >/dev/null 2>&1; then
-    echo 'rename() found.'
-    d_rename="$define"
+if $test -r /usr/include/sys/ioctl.h ; then
+    d_ioctl="$define"
+    echo "sys/ioctl.h found."
 else
-    echo 'rename() not found.'
-    d_rename="$undef"
+    d_ioctl="$undef"
+    echo "sys/ioctl.h not found, assuming ioctl args are defined in sgtty.h."
 fi
 
-: see if setegid exists
+: see if killpg exists
+set killpg d_killpg
+eval $inlibc
+
+: see if memcmp exists
+set memcmp d_memcmp
+eval $inlibc
+
+: see if memcpy exists
+set memcpy d_memcpy
+eval $inlibc
+
+: see if mkdir exists
+set mkdir d_mkdir
+eval $inlibc
+
+: see if ndbm is available
 echo " "
-if $contains '^setegid$' libc.list >/dev/null 2>&1; then
-    echo 'setegid() found.'
-    d_setegid="$define"
+if $test -r /usr/include/ndbm.h || $test -r /usr/local/include/ndbm.h; then
+    d_ndbm="$define"
+    echo "ndbm.h found."
 else
-    echo 'setegid() not found.'
-    d_setegid="$undef"
+    d_ndbm="$undef"
+    echo "ndbm.h not found."
 fi
 
-: see if seteuid exists
+: see if we have the old dbm
 echo " "
-if $contains '^seteuid$' libc.list >/dev/null 2>&1; then
-    echo 'seteuid() found.'
-    d_seteuid="$define"
+if $test -r /usr/include/dbm.h ; then
+    d_odbm="$define"
+    echo "dbm.h found."
 else
-    echo 'seteuid() not found.'
-    d_seteuid="$undef"
+    d_odbm="$undef"
+    echo "dbm.h not found."
 fi
 
-: see if setrgid exists
+: see if this is an pwd system
 echo " "
-if $contains '^setrgid$' libc.list >/dev/null 2>&1; then
-    echo 'setrgid() found.'
-    d_setrgid="$define"
+if $test -r /usr/include/pwd.h ; then
+    i_pwd="$define"
+    echo "pwd.h found."
+    if $contains 'pw_quota' /usr/include/pwd.h >/dev/null 2>&1; then
+       d_pwquota="$define"
+    else
+       d_pwquota="$undef"
+    fi
+    if $contains 'pw_age' /usr/include/pwd.h >/dev/null 2>&1; then
+       d_pwage="$define"
+    else
+       d_pwage="$undef"
+    fi
 else
-    echo 'setrgid() not found.'
-    d_setrgid="$undef"
+    i_pwd="$undef"
+    d_pwquota="$undef"
+    d_pwage="$undef"
+    echo "No pwd.h found."
 fi
 
+: see if readdir exists
+set readdir d_readdir
+eval $inlibc
+
+: see if rename exists
+set rename d_rename
+eval $inlibc
+
+: see if rmdir exists
+set rmdir d_rmdir
+eval $inlibc
+
+: see if setegid exists
+set setegid d_setegid
+eval $inlibc
+
+: see if seteuid exists
+set seteuid d_seteuid
+eval $inlibc
+
+: see if setpgrp exists
+set setpgrp d_setpgrp
+eval $inlibc
+
+: see if setpriority exists
+set setpriority d_setprior
+eval $inlibc
+
+: see if setregid exists
+set setregid d_setregid
+eval $inlibc
+set setresgid d_setresgid
+eval $inlibc
+
+: see if setreuid exists
+set setreuid d_setreuid
+eval $inlibc
+set setresuid d_setresuid
+eval $inlibc
+
+: see if setrgid exists
+set setrgid d_setrgid
+eval $inlibc
+
 : see if setruid exists
+set setruid d_setruid
+eval $inlibc
+
+socketlib=''
+sockethdr=''
+: see whether socket exists
 echo " "
-if $contains '^setruid$' libc.list >/dev/null 2>&1; then
-    echo 'setruid() found.'
-    d_setruid="$define"
+if $contains socket libc.list >/dev/null 2>&1; then
+    echo "Looks like you have Berkeley networking support."
+    d_socket="$define"
+    : now check for advanced features
+    if $contains setsockopt libc.list >/dev/null 2>&1; then
+       d_oldsock="$undef"
+    else
+       echo "...but it uses the old 4.1c interface, rather than 4.2"
+       d_oldsock="$define"
+    fi
+else
+    : hpux, for one, puts all the socket stuff in socklib.o
+    if $contains socklib libc.list >/dev/null 2>&1; then
+       echo "Looks like you have Berkeley networking support."
+       d_socket="$define"
+       : we will have to assume that it supports the 4.2 BSD interface
+       d_oldsock="$undef"
+    else
+       echo "Hmmm...you don't have Berkeley networking in libc.a..."
+       : look for an optional networking library
+       if test -f /usr/lib/libnet.a; then
+           (ar t /usr/lib/libnet.a ||
+               nm -g /usr/lib/libnet.a) 2>/dev/null >> libc.list
+           if $contains socket libc.list >/dev/null 2>&1; then
+               echo "but the Wollongong group seems to have hacked it in."
+               socketlib="-lnet"
+               sockethdr="-I/usr/netinclude"
+               d_socket="$define"
+               : now check for advanced features
+               if $contains setsockopt libc.list >/dev/null 2>&1; then
+                   d_oldsock="$undef"
+               else
+                   echo "...using the old 4.1c interface, rather than 4.2"
+                   d_oldsock="$define"
+               fi
+           else
+               echo "or even in libnet.a, which is peculiar."
+               d_socket="$undef"
+               d_oldsock="$undef"
+           fi
+       else
+           echo "or anywhere else I see."
+           d_socket="$undef"
+           d_oldsock="$undef"
+       fi
+    fi
+fi
+if $contains socketpair libc.list >/dev/null 2>&1; then
+    d_sockpair="$define"
 else
-    echo 'setruid() not found.'
-    d_setruid="$undef"
+    d_sockpair="$undef"
 fi
 
 : see if stat knows about block sizes
@@ -932,16 +1710,6 @@ else
     d_stdstdio="$undef"
 fi
 
-: see if strcspn exists
-echo " "
-if $contains '^strcspn$' libc.list >/dev/null 2>&1; then
-    echo 'strcspn() found.'
-    d_strcspn="$define"
-else
-    echo 'strcspn() not found.'
-    d_strcspn="$undef"
-fi
-
 : check for structure copying
 echo " "
 echo "Checking to see if your C compiler can copy structs..."
@@ -955,7 +1723,7 @@ main()
        foo = bar;
 }
 EOCP
-if cc -c try.c >/dev/null 2>&1 ; then
+if $cc -c try.c >/dev/null 2>&1 ; then
     d_strctcpy="$define"
     echo "Yup, it can."
 else
@@ -965,35 +1733,43 @@ fi
 $rm -f try.*
 
 : see if symlink exists
-echo " "
-if $contains '^symlink$' libc.list >/dev/null 2>&1; then
-    echo 'symlink() found.'
-    d_symlink="$define"
-else
-    echo 'symlink() not found.'
-    d_symlink="$undef"
-fi
+set symlink d_symlink
+eval $inlibc
+
+: see if syscall exists
+set syscall d_syscall
+eval $inlibc
 
 : see if struct tm is defined in sys/time.h
 echo " "
 if $contains 'struct tm' /usr/include/time.h >/dev/null 2>&1 ; then
     echo "You have struct tm defined in <time.h> rather than <sys/time.h>."
     d_tminsys="$undef"
+    if test -f /usr/include/sys/time.h; then
+       i_systime="$define"
+    else
+       i_systime="$undef"
+    fi
 else
     echo "You have struct tm defined in <sys/time.h> rather than <time.h>."
     d_tminsys="$define"
+    i_systime="$define"
 fi
 
-: see if there is a vfork
+: see if this is a varargs system
 echo " "
-if $contains '^vfork$' libc.list >/dev/null 2>&1 ; then
-    echo "vfork() found."
-    d_vfork="$undef"
+if $test -r /usr/include/varargs.h ; then
+    d_varargs="$define"
+    echo "varargs.h found."
 else
-    echo "No vfork() found--will use fork() instead."
-    d_vfork="$define"
+    d_varargs="$undef"
+    echo "No varargs.h found, but that's ok (I hope)."
 fi
 
+: see if there is a vfork
+set vfork d_vfork
+eval $inlibc
+
 : see if signal is declared as pointer to function returning int or void
 echo " "
 if $contains 'void.*signal' /usr/include/signal.h >/dev/null 2>&1 ; then
@@ -1023,37 +1799,37 @@ void main() {
 #else
 main() {
 #endif
-       extern void *moo();
-       void *(*goo)();
+       extern void moo();      /* function returning void */
+       void (*goo)();          /* ptr to func returning void */
 #if TRY & 2
        void (*foo[10])();
 #endif
 
 #if TRY & 4
-       if(*goo == moo) {
+       if(goo == moo) {
                exit(0);
        }
 #endif
        exit(0);
 }
 EOCP
-    if cc -S -DTRY=7 try.c >.out 2>&1 ; then
-       voidflags=7
-       echo "It appears to support void fully."
+    if $cc -S -DTRY=$defvoidused try.c >.out 2>&1 ; then
+       voidflags=$defvoidused
+       echo "It appears to support void."
        if $contains warning .out >/dev/null 2>&1; then
            echo "However, you might get some warnings that look like this:"
            $cat .out
        fi
     else
-       echo "Hmm, you compiler has some difficulty with void.  Checking further..."
-       if cc -S -DTRY=1 try.c >/dev/null 2>&1 ; then
+       echo "Hmm, your compiler has some difficulty with void.  Checking further..."
+       if $cc -S -DTRY=1 try.c >/dev/null 2>&1 ; then
            echo "It supports 1..."
-           if cc -S -DTRY=3 try.c >/dev/null 2>&1 ; then
+           if $cc -S -DTRY=3 try.c >/dev/null 2>&1 ; then
                voidflags=3
                echo "And it supports 2 but not 4."
            else
                echo "It doesn't support 2..."
-               if cc -S -DTRY=3 try.c >/dev/null 2>&1 ; then
+               if $cc -S -DTRY=5 try.c >/dev/null 2>&1 ; then
                    voidflags=5
                    echo "But it supports 4."
                else
@@ -1097,444 +1873,261 @@ $echo $n "$rp $c"
 . myread
 gidtype="$ans"
 
-: set up shell script to do ~ expansion
-cat >filexp <<EOSS
-$startsh
-: expand filename
-case "\$1" in
- ~/*|~)
-    echo \$1 | $sed "s|~|\${HOME-\$LOGDIR}|"
-    ;;
- ~*)
-    if $test -f /bin/csh; then
-       /bin/csh -f -c "glob \$1"
-       echo ""
-    else
-       name=\`$expr x\$1 : '..\([^/]*\)'\`
-       dir=\`$sed -n -e "/^\${name}:/{s/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\).*"'\$'"/\1/" -e p -e q -e '}' </etc/passwd\`
-       if $test ! -d "\$dir"; then
-           me=\`basename \$0\`
-           echo "\$me: can't locate home directory for: \$name" >&2
-           exit 1
-       fi
-       case "\$1" in
-       */*)
-           echo \$dir/\`$expr x\$1 : '..[^/]*/\(.*\)'\`
-           ;;
-       *)
-           echo \$dir
-           ;;
-       esac
-    fi
-    ;;
-*)
-    echo \$1
-    ;;
-esac
-EOSS
-chmod +x filexp
-$eunicefix filexp
-
-: determine where private executables go
-case "$privlib" in
-'')
-    dflt=/usr/lib/perl
-    test -d /usr/local/lib && dflt=/usr/local/lib/perl
-    ;;
-*)  dflt="$privlib"
-    ;;
-esac
-$cat <<EOM
+: see if this is an fcntl system
+echo " "
+if $test -r /usr/include/fcntl.h ; then
+    i_fcntl="$define"
+    echo "fcntl.h found."
+else
+    i_fcntl="$undef"
+    echo "No fcntl.h found, but that's ok."
+fi
 
-The perl package has some perl subroutine libraries that should be put in
-a directory that is accessible by everyone.  Where do you want to put these
-EOM
-$echo $n "libraries? [$dflt] $c"
-rp="Put perl libraries where? [$dflt]"
-. myread
-privlib=`filexp $ans`
+: see if this is an grp system
+echo " "
+if $test -r /usr/include/grp.h ; then
+    i_grp="$define"
+    echo "grp.h found."
+else
+    i_grp="$undef"
+    echo "No grp.h found."
+fi
 
-: see what type of char stdio uses.
+: see if this is a sys/dir.h system
 echo " "
-if $contains 'unsigned.*char.*_ptr;' /usr/include/stdio.h >/dev/null 2>&1 ; then
-    echo "Your stdio uses unsigned chars."
-    stdchar="unsigned char"
+if $test -r /usr/include/sys/dir.h ; then
+    i_sysdir="$define"
+    echo "sysdir.h found."
 else
-    echo "Your stdio uses signed chars."
-    stdchar="char"
+    i_sysdir="$undef"
+    echo "No sysdir.h found."
 fi
 
-: see what type uids are declared as in the kernel
-case "$uidtype" in
-'')
-    if $contains 'uid_t;' /usr/include/sys/types.h >/dev/null 2>&1 ; then
-       dflt='uid_t';
-    else
-       set `grep '_ruid;' /usr/include/sys/user.h 2>/dev/null` unsigned short
-       case $1 in
-       unsigned) dflt="$1 $2" ;;
-       *) dflt="$1" ;;
-       esac
-    fi
-    ;;
-*)  dflt="$uidtype"
-    ;;
-esac
-cont=true
+: see if ioctl defs are in sgtty/termio or sys/ioctl
 echo " "
-rp="What type are user ids on this system declared as? [$dflt]"
-$echo $n "$rp $c"
-. myread
-uidtype="$ans"
+if $test -r /usr/include/sys/ioctl.h ; then
+    i_sysioctl="$define"
+    echo "sys/ioctl.h found."
+else
+    i_sysioctl="$undef"
+    echo "sys/ioctl.h not found, assuming ioctl args are defined in sgtty.h."
+fi
 
-: preserve RCS keywords in files with variable substitution, grrr
-Log='$Log'
-Header='$Header'
+: see if this is a varargs system
+echo " "
+if $test -r /usr/include/varargs.h ; then
+    i_varargs="$define"
+    echo "varargs.h found."
+else
+    i_varargs="$undef"
+    echo "No varargs.h found, but that's ok (I hope)."
+fi
 
-: determine where public executables go
-case "$bin" in
-'')
-    dflt=`loc . /bin /usr/local/bin /usr/lbin /usr/local /usr/bin`
-    ;;
-*)  dflt="$bin"
-    ;;
-esac
-cont=true
-while $test "$cont" ; do
-    echo " "
-    rp="Where do you want to put the public executables? [$dflt]"
-    $echo $n "$rp $c"
-    . myread
-    bin="$ans"
-    bin=`filexp $bin`
-    if test -d $bin; then
-       cont=''
-    else
-       dflt=n
-       rp="Directory $bin doesn't exist.  Use that name anyway? [$dflt]"
-       $echo $n "$rp $c"
-       . myread
-       dflt=''
-       case "$ans" in
-       y*) cont='';;
-       esac
-    fi
-done
+: see if this is a vfork system
+echo " "
+if $test -r /usr/include/vfork.h ; then
+    i_vfork="$define"
+    echo "vfork.h found."
+else
+    i_vfork="$undef"
+    echo "No vfork.h found."
+fi
 
-: determine where manual pages go
-case "$mansrc" in
+: check for length of integer
+echo " "
+case "$intsize" in
 '')
-    dflt=`loc . /usr/man/man1 /usr/man/mann /usr/man/local/man1 /usr/man/u_man/man1 /usr/man/man1`
-    ;;
-*)  dflt="$mansrc"
-    ;;
-esac
-cont=true
-while $test "$cont" ; do
-    echo " "
-    rp="Where do the manual pages (source) go? [$dflt]"
-    $echo $n "$rp $c"
-    . myread
-    mansrc=`filexp "$ans"`
-    if test -d $mansrc; then
-       cont=''
+    echo "Checking to see how big your integers are..."
+    $cat >try.c <<'EOCP'
+#include <stdio.h>
+main()
+{
+    printf("%d\n", sizeof(int));
+}
+EOCP
+    if $cc try.c -o try >/dev/null 2>&1 ; then
+       dflt=`try`
     else
-       dflt=n
-       rp="Directory $mansrc doesn't exist.  Use that name anyway? [$dflt]"
-       $echo $n "$rp $c"
-       . myread
-       dflt=''
-       case "$ans" in
-       y*) cont='';;
-       esac
-    fi
-done
-case "$mansrc" in
-*l)
-    manext=l
-    ;;
-*n)
-    manext=n
-    ;;
-*C)
-    manext=C
-    ;;
-*)
-    manext=1
-    ;;
-esac
-
-: get C preprocessor symbols handy
-echo " "
-echo $attrlist | $tr '[ - ]' '[\012-\012]' >Cppsym.know
-$cat <<EOSS >Cppsym
-$startsh
-case "\$1" in
--l) list=true
-    shift
-    ;;
-esac
-unknown=''
-case "\$list\$#" in
-1|2)
-    for sym do
-       if $contains "^\$1$" Cppsym.true >/dev/null 2>&1; then
-           exit 0
-       elif $contains "^\$1$" Cppsym.know >/dev/null 2>&1; then
-               :
-       else
-           unknown="\$unknown \$sym"
-       fi
-    done
-    set X \$unknown
-    shift
+       dflt='4'
+       echo "(I can't seem to compile the test program.  Guessing...)"
+    fi
     ;;
-esac
-case \$# in
-0) exit 1;;
-esac
-echo \$* | $tr '[ - ]' '[\012-\012]' | $sed -e 's/\(.*\)/\\
-#ifdef \1\\
-exit 0; _ _ _ _\1\\     \1\\
-#endif\\
-/' >/tmp/Cppsym\$\$
-echo exit 1 >>/tmp/Cppsym\$\$
-$cppstdin $cppminus </tmp/Cppsym\$\$ >/tmp/Cppsym2\$\$
-case "\$list" in
-true) awk 'NF > 5 {print substr(\$6,2,100)}' </tmp/Cppsym2\$\$ ;;
 *)
-    sh /tmp/Cppsym2\$\$
-    status=\$?
+    dflt="$intsize"
     ;;
 esac
-$rm -f /tmp/Cppsym\$\$ /tmp/Cppsym2\$\$
-exit \$status
-EOSS
-chmod +x Cppsym
-$eunicefix Cppsym
-echo "Your C preprocessor defines the following symbols:"
-Cppsym -l $attrlist >Cppsym.true
-cat Cppsym.true
-rmlist="$rmlist Cppsym Cppsym.know Cppsym.true"
+rp="What is the size of an integer (in bytes)? [$dflt]"
+$echo $n "$rp $c"
+. myread
+intsize="$ans"
+$rm -f try.c try
 
-: see what memory models we can support
-case "$models" in
+: determine where private executables go
+case "$privlib" in
 '')
-    if Cppsym pdp11; then
-       dflt='unsplit split'
-    else
-       ans=`loc . X /lib/small /lib/large /usr/lib/small /usr/lib/large /lib/medium /usr/lib/medium /lib/huge`
-       case "$ans" in
-       X) dflt='none';;
-       *)  if $test -d /lib/small || $test -d /usr/lib/small; then
-               dflt='small'
-           else
-               dflt=''
-           fi
-           if $test -d /lib/medium || $test -d /usr/lib/medium; then
-               dflt="$dflt medium"
-           fi
-           if $test -d /lib/large || $test -d /usr/lib/large; then
-               dflt="$dflt large"
-           fi
-           if $test -d /lib/huge || $test -d /usr/lib/huge; then
-               dflt="$dflt huge"
-           fi
-       esac
-    fi
+    dflt=/usr/lib/$package
+    test -d /usr/local/lib && dflt=/usr/local/lib/$package
+    ;;
+*)  dflt="$privlib"
     ;;
-*)  dflt="$models" ;;
 esac
 $cat <<EOM
-Some systems have different model sizes.  On most systems they are called
-small, medium, large, and huge.  On the PDP11 they are called unsplit and
-split.  If your system doesn't support different memory models, say "none".
-If you wish to force everything to one memory model, say "none" here and
-put the appropriate flags later when it asks you for other cc and ld flags.
-Venix systems may wish to put "none" and let the compiler figure things out.
-(In the following question multiple model names should be space separated.)
 
+The $package package has some auxiliary files that should be put in a library
+that is accessible by everyone.  Where do you want to put these "private"
 EOM
-rp="Which models are supported? [$dflt]"
-$echo $n "$rp $c"
+$echo $n "but accessible files? [$dflt] $c"
+rp="Put private files where? [$dflt]"
 . myread
-models="$ans"
+privlib="$ans"
 
-case "$models" in
-none)
-    small=''
-    medium=''
-    large=''
-    huge=''
-    unsplit=''
-    split=''
+: check for size of random number generator
+echo " "
+case "$randbits" in
+'')
+    echo "Checking to see how many bits your rand function produces..."
+    $cat >try.c <<'EOCP'
+#include <stdio.h>
+main()
+{
+    register int i;
+    register unsigned long tmp;
+    register unsigned long max = 0L;
+
+    for (i=1000; i; i--) {
+       tmp = (unsigned long)rand();
+       if (tmp > max) max = tmp;
+    }
+    for (i=0; max; i++)
+       max /= 2;
+    printf("%d\n",i);
+}
+EOCP
+    if $cc try.c -o try >/dev/null 2>&1 ; then
+       dflt=`try`
+    else
+       dflt='?'
+       echo "(I can't seem to compile the test program...)"
+    fi
     ;;
-*split)
-    case "$split" in
-    '') 
-       if $contains '\-i' $mansrc/ld.1 >/dev/null 2>&1 || \
-          $contains '\-i' $mansrc/cc.1 >/dev/null 2>&1; then
-           dflt='-i'
-       else
-           dflt='none'
-       fi
-       ;;
-    *) dflt="$split";;
-    esac
-    rp="What flag indicates separate I and D space? [$dflt]"
-    $echo $n "$rp $c"
-    . myread
-    case "$ans" in
-    none) ans='';;
-    esac
-    split="$ans"
-    unsplit=''
+*)
+    dflt="$randbits"
     ;;
-*large*|*small*|*medium*|*huge*)
-    case "$model" in
-    *large*)
-       case "$large" in
-       '') dflt='-Ml';;
-       *) dflt="$large";;
-       esac
-       rp="What flag indicates large model? [$dflt]"
-       $echo $n "$rp $c"
-       . myread
-       case "$ans" in
-       none) ans='';
-       esac
-       large="$ans"
-       ;;
-    *) large='';;
-    esac
-    case "$model" in
-    *huge*)
-       case "$huge" in
-       '') dflt='-Mh';;
-       *) dflt="$huge";;
-       esac
-       rp="What flag indicates huge model? [$dflt]"
-       $echo $n "$rp $c"
-       . myread
-       case "$ans" in
-       none) ans='';
-       esac
-       huge="$ans"
-       ;;
-    *) huge="$large";;
-    esac
-    case "$model" in
-    *medium*)
-       case "$medium" in
-       '') dflt='-Mm';;
-       *) dflt="$medium";;
-       esac
-       rp="What flag indicates medium model? [$dflt]"
-       $echo $n "$rp $c"
-       . myread
-       case "$ans" in
-       none) ans='';
-       esac
-       medium="$ans"
-       ;;
-    *) medium="$large";;
-    esac
-    case "$model" in
-    *small*)
-       case "$small" in
-       '') dflt='none';;
-       *) dflt="$small";;
-       esac
-       rp="What flag indicates small model? [$dflt]"
-       $echo $n "$rp $c"
-       . myread
-       case "$ans" in
-       none) ans='';
+esac
+rp="How many bits does your rand() function produce? [$dflt]"
+$echo $n "$rp $c"
+. myread
+randbits="$ans"
+$rm -f try.c try
+
+: generate list of signal names
+echo " "
+case "$sig_name" in
+'')
+    echo "Generating a list of signal names..."
+    set X `kill -l 2>/dev/null`
+    shift
+    case $# in
+    0)  echo 'kill -l' >/tmp/foo$$
+       set X `/bin/csh -f </tmp/foo$$`
+       shift
+       case $# in
+       0)set HUP INT QUIT ILL TRAP IOT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM
+           ;;
        esac
-       small="$ans"
        ;;
-    *) small='';;
     esac
-    ;;
-*)
-    echo "Unrecognized memory models--you may have to edit Makefile.SH"
+    sig_name="ZERO $*"
     ;;
 esac
+echo "Signals are: $sig_name"
 
-case "$ccflags" in
-'') dflt='none';;
-*) dflt="$ccflags";;
-esac
+: see what type of char stdio uses.
 echo " "
-rp="Any additional cc flags? [$dflt]"
-$echo $n "$rp $c"
-. myread
-case "$ans" in
-none) ans='';
-esac
-ccflags="$ans"
+if $contains 'unsigned.*char.*_ptr;' /usr/include/stdio.h >/dev/null 2>&1 ; then
+    echo "Your stdio uses unsigned chars."
+    stdchar="unsigned char"
+else
+    echo "Your stdio uses signed chars."
+    stdchar="char"
+fi
 
-case "$ldflags" in
-'') if venix; then
-       dflt='-i -z'
+: see what type uids are declared as in the kernel
+case "$uidtype" in
+'')
+    if $contains 'uid_t;' /usr/include/sys/types.h >/dev/null 2>&1 ; then
+       dflt='uid_t';
     else
-       dflt='none'
+       set `grep '_ruid;' /usr/include/sys/user.h 2>/dev/null` unsigned short
+       case $1 in
+       unsigned) dflt="$1 $2" ;;
+       *) dflt="$1" ;;
+       esac
     fi
     ;;
-*) dflt="$ldflags";;
+*)  dflt="$uidtype"
+    ;;
 esac
+cont=true
 echo " "
-rp="Any additional ld flags? [$dflt]"
+rp="What type are user ids on this system declared as? [$dflt]"
 $echo $n "$rp $c"
 . myread
-case "$ans" in
-none) ans='';
-esac
-ldflags="$ans"
+uidtype="$ans"
 
-: see if we need a special compiler
+: preserve RCS keywords in files with variable substitution, grrr
+Log='$Log'
+Header='$Header'
+
+
+: see if we should include -ldbm
 echo " "
-if usg; then
-    case "$cc" in
-    '')
-       case "$Mcc" in
-       /*) dflt='Mcc'
-           ;;
-       *)
-           case "$large" in
-           -M*)
-               dflt='cc'
-               ;;
-           *)
-               if $contains '\-M' $mansrc/cc.1 >/dev/null 2>&1 ; then
-                   dflt='cc -M'
-               else
-                   dflt='cc'
-               fi
-               ;;
-           esac
-           ;;
-       esac
+if $test -r /usr/lib/libdbm.a || $test -r /usr/local/lib/libdbm.a ; then
+    echo "-ldbm found."
+    libdbm='-ldbm'
+else
+    ans=`loc libdbm.a x $libpth`
+    case "$ans" in
+    x)
+       echo "No dbm library found."
+       libdbm=''
+       ;;
+    *)
+       echo "DBM library found in $ans."
+       libdbm="$ans"
        ;;
-    *)  dflt="$cc";;
     esac
-    $cat <<'EOM'
-On some systems the default C compiler will not resolve multiple global
-references that happen to have the same name.  On some such systems the
-"Mcc" command may be used to force these to be resolved.  On other systems
-a "cc -M" command is required.  (Note that the -M flag on other systems
-indicates a memory model to use!)  What command will force resolution on
-EOM
-    $echo $n "this system? [$dflt] $c"
-    rp="Command to resolve multiple refs? [$dflt]"
-    . myread
-    cc="$ans"
+fi
+
+: see if we should include -lndir
+echo " "
+if $test -r /usr/lib/libndir.a || $test -r /usr/local/lib/libndir.a ; then
+    echo "New directory library found."
+    libndir='-lndir'
 else
-    echo "Not a USG system--assuming cc can resolve multiple definitions."
-    cc=cc
+    ans=`loc libndir.a x $libpth`
+    case "$ans" in
+    x)
+       echo "No ndir library found."
+       libndir=''
+       ;;
+    *)
+       echo "New directory library found in $ans."
+       libndir="$ans"
+       ;;
+    esac
 fi
+case "$libndir" in
+'') ;;
+*)
+    case "$d_readdir" in
+    $define)
+       echo "Since you have readdir in the C library, I'll ignore $libndir"
+       libndir=''
+       ;;
+    esac
+    ;;
+esac
 
 : see if we should include -lnm
 echo " "
@@ -1623,38 +2216,108 @@ vi='$vi'
 mailx='$mailx'
 mail='$mail'
 cpp='$cpp'
+perl='$perl'
+emacs='$emacs'
+ls='$ls'
+rmail='$rmail'
+sendmail='$sendmail'
+shar='$shar'
+smail='$smail'
+tbl='$tbl'
+troff='$troff'
+nroff='$nroff'
+uname='$uname'
+uuname='$uuname'
+line='$line'
+chgrp='$chgrp'
+chmod='$chmod'
+lint='$lint'
+sleep='$sleep'
+pr='$pr'
+tar='$tar'
+ln='$ln'
+lpr='$lpr'
+lp='$lp'
+touch='$touch'
+make='$make'
+date='$date'
 Log='$Log'
 Header='$Header'
 bin='$bin'
-cc='$cc'
+byteorder='$byteorder'
 contains='$contains'
 cppstdin='$cppstdin'
 cppminus='$cppminus'
+d_bcmp='$d_bcmp'
 d_bcopy='$d_bcopy'
 d_charsprf='$d_charsprf'
 d_crypt='$d_crypt'
+cryptlib='$cryptlib'
 d_dosuid='$d_dosuid'
+d_dup2='$d_dup2'
 d_fchmod='$d_fchmod'
 d_fchown='$d_fchown'
+d_fcntl='$d_fcntl'
+d_flock='$d_flock'
 d_getgrps='$d_getgrps'
+d_gethent='$d_gethent'
+d_getpgrp='$d_getpgrp'
+d_getprior='$d_getprior'
+d_htonl='$d_htonl'
 d_index='$d_index'
+d_ioctl='$d_ioctl'
 d_killpg='$d_killpg'
+d_memcmp='$d_memcmp'
 d_memcpy='$d_memcpy'
+d_mkdir='$d_mkdir'
+d_ndbm='$d_ndbm'
+d_odbm='$d_odbm'
+d_readdir='$d_readdir'
 d_rename='$d_rename'
+d_rmdir='$d_rmdir'
 d_setegid='$d_setegid'
 d_seteuid='$d_seteuid'
+d_setpgrp='$d_setpgrp'
+d_setprior='$d_setprior'
+d_setregid='$d_setregid'
+d_setresgid='$d_setresgid'
+d_setreuid='$d_setreuid'
+d_setresuid='$d_setresuid'
 d_setrgid='$d_setrgid'
 d_setruid='$d_setruid'
+d_socket='$d_socket'
+d_sockpair='$d_sockpair'
+d_oldsock='$d_oldsock'
+socketlib='$socketlib'
+sockethdr='$sockethdr'
 d_statblks='$d_statblks'
 d_stdstdio='$d_stdstdio'
-d_strcspn='$d_strcspn'
 d_strctcpy='$d_strctcpy'
 d_symlink='$d_symlink'
+d_syscall='$d_syscall'
 d_tminsys='$d_tminsys'
+i_systime='$i_systime'
+d_varargs='$d_varargs'
 d_vfork='$d_vfork'
 d_voidsig='$d_voidsig'
+d_vprintf='$d_vprintf'
+d_charvspr='$d_charvspr'
 gidtype='$gidtype'
+i_dirent='$i_dirent'
+d_dirnamlen='$d_dirnamlen'
+i_fcntl='$i_fcntl'
+i_grp='$i_grp'
+i_pwd='$i_pwd'
+d_pwquota='$d_pwquota'
+d_pwage='$d_pwage'
+i_sysdir='$i_sysdir'
+i_sysioctl='$i_sysioctl'
+i_varargs='$i_varargs'
+i_vfork='$i_vfork'
+intsize='$intsize'
 libc='$libc'
+libdbm='$libdbm'
+libndir='$libndir'
 libnm='$libnm'
 mallocsrc='$mallocsrc'
 mallocobj='$mallocobj'
@@ -1667,11 +2330,16 @@ small='$small'
 medium='$medium'
 large='$large'
 huge='$huge'
+optimize='$optimize'
 ccflags='$ccflags'
 ldflags='$ldflags'
+cc='$cc'
+libs='$libs'
 n='$n'
 c='$c'
 package='$package'
+randbits='$randbits'
+sig_name='$sig_name'
 spitshell='$spitshell'
 shsharp='$shsharp'
 sharpbang='$sharpbang'
@@ -1680,6 +2348,7 @@ stdchar='$stdchar'
 uidtype='$uidtype'
 voidflags='$voidflags'
 defvoidused='$defvoidused'
+lib='$lib'
 privlib='$privlib'
 CONFIG=true
 EOT
@@ -1742,8 +2411,7 @@ EOM
     $echo $n "$rp $c"
     . UU/myread
     case "$ans" in
-    y*) make depend
-       echo "Now you must run a make."
+    y*) make depend && echo "Now you must run a make."
        ;;
     *)  echo "You must run 'make depend' then 'make'."
        ;;
diff --git a/Copying b/Copying
new file mode 100644 (file)
index 0000000..3c68f02
--- /dev/null
+++ b/Copying
@@ -0,0 +1,248 @@
+                   GNU GENERAL PUBLIC LICENSE
+                    Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+                    675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The license agreements of most software companies try to keep users
+at the mercy of those companies.  By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must tell them their rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License.  The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications.  Each
+licensee is addressed as "you".
+
+  1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program.  You may charge a fee for the physical act of
+transferring a copy.
+
+  2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+    a) cause the modified files to carry prominent notices stating that
+    you changed the files and the date of any change; and
+
+    b) cause the whole of any work that you distribute or publish, that
+    in whole or in part contains the Program or any part thereof, either
+    with or without modifications, to be licensed at no charge to all
+    third parties under the terms of this General Public License (except
+    that you may choose to grant warranty protection to some or all
+    third parties, at your option).
+
+    c) If the modified program normally reads commands interactively when
+    run, you must cause it, when started running for such interactive use
+    in the simplest and most usual way, to print or display an
+    announcement including an appropriate copyright notice and a notice
+    that there is no warranty (or else, saying that you provide a
+    warranty) and that users may redistribute the program under these
+    conditions, and telling the user how to view a copy of this General
+    Public License.
+
+    d) You may charge a fee for the physical act of transferring a
+    copy, and you may at your option offer warranty protection in
+    exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+\f
+  3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+    a) accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    b) accompany it with a written offer, valid for at least three
+    years, to give any third party free (except for a nominal charge
+    for the cost of distribution) a complete machine-readable copy of the
+    corresponding source code, to be distributed under the terms of
+    Paragraphs 1 and 2 above; or,
+
+    c) accompany it with the information you received as to where the
+    corresponding source code may be obtained.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it.  For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+  4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License.  However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+  5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions.  You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+\f
+  7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+  8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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 1, 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, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19xx name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License.  Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  program `Gnomovision' (a program to direct compilers to make passes
+  at assemblers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+That's all there is to it!
index 793da6d..19651c0 100644 (file)
--- a/EXTERN.h
+++ b/EXTERN.h
@@ -1,8 +1,13 @@
-/* $Header: EXTERN.h,v 2.0 88/06/05 00:07:46 root Exp $
+/* $Header: EXTERN.h,v 3.0 89/10/18 15:06:03 lwall Locked $
+ *
+ *    Copyright (c) 1989, Larry Wall
+ *
+ *    You may distribute under the terms of the GNU General Public License
+ *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       EXTERN.h,v $
- * Revision 2.0  88/06/05  00:07:46  root
- * Baseline version 2.0.
+ * Revision 3.0  89/10/18  15:06:03  lwall
+ * 3.0 baseline
  * 
  */
 
index a070e53..d18b30c 100644 (file)
--- a/INTERN.h
+++ b/INTERN.h
@@ -1,8 +1,13 @@
-/* $Header: INTERN.h,v 2.0 88/06/05 00:07:49 root Exp $
+/* $Header: INTERN.h,v 3.0 89/10/18 15:06:25 lwall Locked $
+ *
+ *    Copyright (c) 1989, Larry Wall
+ *
+ *    You may distribute under the terms of the GNU General Public License
+ *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       INTERN.h,v $
- * Revision 2.0  88/06/05  00:07:49  root
- * Baseline version 2.0.
+ * Revision 3.0  89/10/18  15:06:25  lwall
+ * 3.0 baseline
  * 
  */
 
index 39abd2a..edd1931 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
-After all the perl kits are run you should have the following files:
-
-Filename               Kit Description
---------               --- -----------
-Changes                 13 Differences between 1.0 level 29 and 2.0 level 0
-Configure                6 Run this first
-EXTERN.h                 6 Included before foreign .h files
-INTERN.h                15 Included before domestic .h files
-MANIFEST                11 This list of files
-Makefile.SH             13 Precursor to Makefile
-README                   1 The Instructions
-Wishlist                 4 Some things that may or may not happen
-arg.c                    1 Expression evaluation
-arg.h                   12 Public declarations for the above
-array.c                 13 Numerically subscripted arrays
-array.h                 15 Public declarations for the above
-cmd.c                   10 Command interpreter
-cmd.h                   13 Public declarations for the above
-config.H                13 Sample config.h
-config.h.SH             11 Produces config.h.
-dump.c                  12 Debugging output
-eg/ADB                  15 An adb wrapper to put in your crash dir
-eg/README                1 Intro to example perl scripts
-eg/changes              15 A program to list recently changed files
-eg/dus                  15 A program to do du -s on non-mounted dirs
-eg/findcp               14 A find wrapper that implements a -cp switch
-eg/findtar              15 A find wrapper that pumps out a tar file
-eg/g/gcp                14 A program to do a global rcp
-eg/g/gcp.man            14 Manual page for gcp
-eg/g/ged                 1 A program to do a global edit
-eg/g/ghosts             15 A sample /etc/ghosts file
-eg/g/gsh                10 A program to do a global rsh
-eg/g/gsh.man            14 Manual page for gsh
-eg/myrup                15 A program to find lightly loaded machines
-eg/nih                  15 Script to insert #! workaround
-eg/rmfrom               15 A program to feed doomed filenames to
-eg/scan/scan_df         14 Scan for filesystem anomalies
-eg/scan/scan_last       14 Scan for login anomalies
-eg/scan/scan_messages   13 Scan for console message anomalies
-eg/scan/scan_passwd     15 Scan for passwd file anomalies
-eg/scan/scan_ps         15 Scan for process anomalies
-eg/scan/scan_sudo       14 Scan for sudo anomalies
-eg/scan/scan_suid        8 Scan for setuid anomalies
-eg/scan/scanner         14 An anomaly reporter
-eg/shmkill              15 A program to remove unused shared memory
-eg/van/empty            15 A program to empty the trashcan
-eg/van/unvanish         14 A program to undo what vanish does
-eg/van/vanexp           15 A program to expire vanished files
-eg/van/vanish           14 A program to put files in a trashcan
-eval.c                   8 The expression evaluator
-form.c                  12 Format processing
-form.h                  15 Public declarations for the above
-handy.h                 15 Handy definitions
-hash.c                  12 Associative arrays
-hash.h                  14 Public declarations for the above
-lib/getopt.pl           14 Perl library supporting option parsing
-lib/importenv.pl        15 Perl routine to get environment into variables.
-lib/stat.pl             15 Perl library supporting stat function
-makedepend.SH            5 Precursor to makedepend
-makedir.SH              14 Precursor to makedir
-malloc.c                11 A version of malloc you might not want
-patchlevel.h            12 The current patch level of perl
-perl.h                  12 Global declarations
-perl.man.1               5 The manual page(s), first half
-perl.man.2               3 The manual page(s), second half
-perl.y                  10 Yacc grammar for perl
-perldb                  11 Perl symbolic debugger
-perldb.man              13 Manual page for perl debugger
-perlsh                  15 A poor man's perl shell.
-perly.c                  4 The perl compiler
-regexp.c                 2 String matching
-regexp.h                14 Public declarations for the above
-spat.h                  14 Search pattern declarations
-stab.c                   6 Symbol table stuff
-stab.h                   3 Public declarations for the above
-str.c                    7 String handling package
-str.h                   14 Public declarations for the above
-t/README                 1 Instructions for regression tests
-t/TEST                  14 The regression tester
-t/base.cond             15 See if conditionals work
-t/base.if               15 See if if works
-t/base.lex              15 See if lexical items work
-t/base.pat              15 See if pattern matching works
-t/base.term             15 See if various terms work
-t/cmd.elsif             15 See if else-if works
-t/cmd.for               15 See if for loops work
-t/cmd.mod               15 See if statement modifiers work
-t/cmd.subval            14 See if subroutine values work
-t/cmd.while             14 See if while loops work
-t/comp.cmdopt           13 See if command optimization works
-t/comp.cpp              15 See if C preprocessor works
-t/comp.decl             15 See if declarations work
-t/comp.multiline        15 See if multiline strings work
-t/comp.script           14 See if script invokation works
-t/comp.term             15 See if more terms work
-t/io.argv               15 See if ARGV stuff works
-t/io.dup                15 See if >& works right
-t/io.fs                 12 See if directory manipulations work
-t/io.inplace            15 See if inplace editing works
-t/io.pipe               15 See if secure pipes work
-t/io.print              15 See if print commands work
-t/io.tell               13 See if file seeking works
-t/op.append             15 See if . works
-t/op.auto               14 See if autoincrement et all work
-t/op.chop               15 See if chop works
-t/op.cond                5 See if conditional expressions work
-t/op.delete             15 See if delete works
-t/op.do                 14 See if subroutines work
-t/op.each               14 See if associative iterators work
-t/op.eval               14 See if eval operator works
-t/op.exec               15 See if exec and system work
-t/op.exp                15 See if math functions work
-t/op.flip               15 See if range operator works
-t/op.fork               15 See if fork works
-t/op.goto               15 See if goto works
-t/op.int                15 See if int works
-t/op.join               15 See if join works
-t/op.list               14 See if array lists work
-t/op.magic              15 See if magic variables work
-t/op.oct                15 See if oct and hex work
-t/op.ord                15 See if ord works
-t/op.pat                14 See if esoteric patterns work
-t/op.push               15 See if push and pop work
-t/op.regexp             15 See if regular expressions work
-t/op.repeat             15 See if x operator works
-t/op.sleep              15 See if sleep works
-t/op.split               7 See if split works
-t/op.sprintf            15 See if sprintf works
-t/op.stat               11 See if stat works
-t/op.study              14 See if study works
-t/op.subst              14 See if substitutions work
-t/op.time               14 See if time functions work
-t/op.unshift            15 See if unshift works
-t/re_tests              13 Input file for op.regexp
-toke.c                   9 The tokener
-util.c                   8 Utility routines
-util.h                  15 Public declarations for the above
-version.c               15 Prints version of perl
-x2p/EXTERN.h            15 Same as above
-x2p/INTERN.h            15 Same as above
-x2p/Makefile.SH          4 Precursor to Makefile
-x2p/a2p.h               13 Global declarations
-x2p/a2p.man             12 Manual page for awk to perl translator
-x2p/a2p.y               12 A yacc grammer for awk
-x2p/a2py.c               9 Awk compiler, sort of
-x2p/handy.h             15 Handy definitions
-x2p/hash.c              13 Associative arrays again
-x2p/hash.h              14 Public declarations for the above
-x2p/s2p                 10 Sed to perl translator
-x2p/s2p.man              9 Manual page for     sed to perl translator
-x2p/str.c               11 String handling package
-x2p/str.h               15 Public declarations for the above
-x2p/util.c              13 Utility routines
-x2p/util.h              15 Public declarations for the above
-x2p/walk.c               7 Parse tree walker
+Changes                        Differences between 2.0 level 18 and 3.0 level 0
+Configure              Run this first
+Copying                        The GNU General Public License
+EXTERN.h               Included before foreign .h files
+INTERN.h               Included before domestic .h files
+MANIFEST               This list of files
+Makefile.SH            Precursor to Makefile
+PACKINGLIST            Which files came from which kits
+README                 The Instructions
+Wishlist               Some things that may or may not happen
+arg.h                  Public declarations for the above
+array.c                        Numerically subscripted arrays
+array.h                        Public declarations for the above
+client                 A client to test sockets
+cmd.c                  Command interpreter
+cmd.h                  Public declarations for the above
+config.H               Sample config.h
+config.h.SH            Produces config.h
+cons.c                 Routines to construct cmd nodes of a parse tree
+consarg.c              Routines to construct arg nodes of a parse tree
+doarg.c                        Scalar expression evaluation
+doio.c                 I/O operations
+dolist.c               Array expression evaluation
+dump.c                 Debugging output
+eg/ADB                 An adb wrapper to put in your crash dir
+eg/README              Intro to example perl scripts
+eg/changes             A program to list recently changed files
+eg/down                        A program to do things to subdirectories
+eg/dus                 A program to do du -s on non-mounted dirs
+eg/findcp              A find wrapper that implements a -cp switch
+eg/findtar             A find wrapper that pumps out a tar file
+eg/g/gcp               A program to do a global rcp
+eg/g/gcp.man           Manual page for gcp
+eg/g/ged               A program to do a global edit
+eg/g/ghosts            A sample /etc/ghosts file
+eg/g/gsh               A program to do a global rsh
+eg/g/gsh.man           Manual page for gsh
+eg/muck                        A program to find missing make dependencies
+eg/muck.man            Manual page for muck
+eg/myrup               A program to find lightly loaded machines
+eg/nih                 Script to insert #! workaround
+eg/rename              A program to rename files
+eg/rmfrom              A program to feed doomed filenames to
+eg/scan/scan_df                Scan for filesystem anomalies
+eg/scan/scan_last      Scan for login anomalies
+eg/scan/scan_messages  Scan for console message anomalies
+eg/scan/scan_passwd    Scan for passwd file anomalies
+eg/scan/scan_ps                Scan for process anomalies
+eg/scan/scan_sudo      Scan for sudo anomalies
+eg/scan/scan_suid      Scan for setuid anomalies
+eg/scan/scanner                An anomaly reporter
+eg/shmkill             A program to remove unused shared memory
+eg/van/empty           A program to empty the trashcan
+eg/van/unvanish                A program to undo what vanish does
+eg/van/vanexp          A program to expire vanished files
+eg/van/vanish          A program to put files in a trashcan
+eg/who                 A sample who program
+eval.c                 The expression evaluator
+evalargs.xc            The arg evaluator of eval.c
+form.c                 Format processing
+form.h                 Public declarations for the above
+gettest                        A little script to test the get* routines
+handy.h                        Handy definitions
+hash.c                 Associative arrays
+hash.h                 Public declarations for the above
+ioctl.pl               Sample ioctl.pl
+lib/abbrev.pl          An abbreviation table builder
+lib/look.pl            A "look" equivalent
+lib/complete.pl                A command completion subroutine
+lib/dumpvar.pl         A variable dumper
+lib/getopt.pl          Perl library supporting option parsing
+lib/getopts.pl         Perl library supporting option parsing
+lib/importenv.pl       Perl routine to get environment into variables
+lib/perldb.pl          Perl debugging routines
+lib/stat.pl            Perl library supporting stat function
+lib/termcap.pl         Perl library supporting termcap usage
+lib/validate.pl                Perl library supporting wholesale file mode validation
+makedepend.SH          Precursor to makedepend
+makedir.SH             Precursor to makedir
+makelib.SH             A thing to turn C .h file into perl .h files
+malloc.c               A version of malloc you might not want
+patchlevel.h           The current patch level of perl
+perl.h                 Global declarations
+perl.man.1             The manual page(s), first fourth
+perl.man.2             The manual page(s), second fourth
+perl.man.3             The manual page(s), third fourth
+perl.man.4             The manual page(s), fourth fourth
+perl.y                 Yacc grammar for perl
+perlsh                 A poor man's perl shell
+perly.c                        main()
+regcomp.c              Regular expression compiler
+regcomp.h              Private declarations for above
+regexp.h               Public declarations for the above
+regexec.c              Regular expression evaluator
+server                 A server to test sockets
+spat.h                 Search pattern declarations
+stab.c                 Symbol table stuff
+stab.h                 Public declarations for the above
+str.c                  String handling package
+str.h                  Public declarations for the above
+t/README               Instructions for regression tests
+t/TEST                 The regression tester
+t/base.cond            See if conditionals work
+t/base.if              See if if works
+t/base.lex             See if lexical items work
+t/base.pat             See if pattern matching works
+t/base.term            See if various terms work
+t/cmd.elsif            See if else-if works
+t/cmd.for              See if for loops work
+t/cmd.mod              See if statement modifiers work
+t/cmd.subval           See if subroutine values work
+t/cmd.switch           See if switch optimizations work
+t/cmd.while            See if while loops work
+t/comp.cmdopt          See if command optimization works
+t/comp.cpp             See if C preprocessor works
+t/comp.decl            See if declarations work
+t/comp.multiline       See if multiline strings work
+t/comp.package         See if packages work
+t/comp.script          See if script invokation works
+t/comp.term            See if more terms work
+t/io.argv              See if ARGV stuff works
+t/io.dup               See if >& works right
+t/io.fs                        See if directory manipulations work
+t/io.inplace           See if inplace editing works
+t/io.pipe              See if secure pipes work
+t/io.print             See if print commands work
+t/io.tell              See if file seeking works
+t/op.append            See if . works
+t/op.array             See if array operations work
+t/op.auto              See if autoincrement et all work
+t/op.chop              See if chop works
+t/op.cond              See if conditional expressions work
+t/op.dbm               See if dbm binding works
+t/op.delete            See if delete works
+t/op.do                        See if subroutines work
+t/op.each              See if associative iterators work
+t/op.eval              See if eval operator works
+t/op.exec              See if exec and system work
+t/op.exp               See if math functions work
+t/op.flip              See if range operator works
+t/op.fork              See if fork works
+t/op.glob              See if <*> works
+t/op.goto              See if goto works
+t/op.index             See if index works
+t/op.int               See if int works
+t/op.join              See if join works
+t/op.list              See if array lists work
+t/op.local             See if local works
+t/op.magic             See if magic variables work
+t/op.mkdir             See if mkdir works
+t/op.oct               See if oct and hex work
+t/op.ord               See if ord works
+t/op.pack              See if pack and unpack work
+t/op.pat               See if esoteric patterns work
+t/op.push              See if push and pop work
+t/op.range             See if .. works
+t/op.read              See if read() works
+t/op.regexp            See if regular expressions work
+t/op.repeat            See if x operator works
+t/op.sleep             See if sleep works
+t/op.sort              See if sort works
+t/op.split             See if split works
+t/op.sprintf           See if sprintf works
+t/op.stat              See if stat works
+t/op.study             See if study works
+t/op.subst             See if substitutions work
+t/op.substr            See if substr works
+t/op.time              See if time functions work
+t/op.undef             See if undef works
+t/op.unshift           See if unshift works
+t/op.vec               See if vectors work
+t/op.write             See if write works
+t/re_tests             Input file for op.regexp
+toke.c                 The tokener
+util.c                 Utility routines
+util.h                 Public declarations for the above
+x2p/EXTERN.h           Same as above
+x2p/INTERN.h           Same as above
+x2p/Makefile.SH                Precursor to Makefile
+x2p/a2p.h              Global declarations
+x2p/a2p.man            Manual page for awk to perl translator
+x2p/a2p.y              A yacc grammer for awk
+x2p/a2py.c             Awk compiler, sort of
+x2p/handy.h            Handy definitions
+x2p/hash.c             Associative arrays again
+x2p/hash.h             Public declarations for the above
+x2p/s2p.SH             Sed to perl translator
+x2p/s2p.man            Manual page for sed to perl translator
+x2p/str.c              String handling package
+x2p/str.h              Public declarations for the above
+x2p/util.c             Utility routines
+x2p/util.h             Public declarations for the above
+x2p/walk.c             Parse tree walker
index 931a3af..6e66a4c 100644 (file)
@@ -25,24 +25,19 @@ esac
 
 echo "Extracting Makefile (with variable substitutions)"
 cat >Makefile <<!GROK!THIS!
-# $Header: Makefile.SH,v 2.0.1.1 88/06/28 16:26:04 root Exp $
+# $Header: Makefile.SH,v 3.0 89/10/18 15:06:43 lwall Locked $
 #
 # $Log:        Makefile.SH,v $
-# Revision 2.0.1.1  88/06/28  16:26:04  root
-# patch1: support for DOSUID
-# patch1: realclean now knows about ~ extension
-# 
-# Revision 2.0  88/06/05  00:07:54  root
-# Baseline version 2.0.
-# 
+# Revision 3.0  89/10/18  15:06:43  lwall
+# 3.0 baseline
 # 
 
 CC = $cc
 bin = $bin
-lib = $privlib
+privlib = $privlib
 mansrc = $mansrc
 manext = $manext
-CFLAGS = $ccflags -O
+CFLAGS = $ccflags $optimize $sockethdr
 LDFLAGS = $ldflags
 SMALL = $small
 LARGE = $large $split
@@ -50,37 +45,47 @@ mallocsrc = $mallocsrc
 mallocobj = $mallocobj
 SLN = $sln
 
-libs = $libnm -lm
+libs = $libnm -lm $libdbm $libs $libndir $socketlib
 
-public = perl perldb $suidperl
+public = perl taintperl $suidperl
 
 !GROK!THIS!
 
 cat >>Makefile <<'!NO!SUBS!'
 private = 
 
-manpages = perl.man perldb.man
+MAKE = make
+
+manpages = perl.man
 
 util =
 
 sh = Makefile.SH makedepend.SH
 
 h1 = EXTERN.h INTERN.h arg.h array.h cmd.h config.h form.h handy.h
-h2 = hash.h perl.h regexp.h spat.h stab.h str.h util.h
+h2 = hash.h perl.h regcomp.h regexp.h spat.h stab.h str.h util.h
 
 h = $(h1) $(h2)
 
-c1 = arg.c array.c cmd.c dump.c eval.c form.c hash.c $(mallocsrc)
-c2 = perly.c regexp.c stab.c str.c toke.c util.c version.c
+c1 = array.c cmd.c cons.c consarg.c doarg.c doio.c dolist.c dump.c
+c2 = eval.c form.c hash.c $(mallocsrc) perly.c regcomp.c regexec.c
+c3 = stab.c str.c toke.c util.c
+
+c = $(c1) $(c2) $(c3)
+
+obj1 = array.o cmd.o cons.o consarg.o doarg.o doio.o dolist.o dump.o
+obj2 = eval.o form.o hash.o $(mallocobj) perly.o regcomp.o regexec.o
+obj3 = stab.o str.o toke.o util.o
 
-c = $(c1) $(c2)
+obj = $(obj1) $(obj2) $(obj3)
 
-obj1 = arg.o array.o cmd.o dump.o eval.o form.o hash.o $(mallocobj)
-obj2 = regexp.o stab.o str.o toke.o util.o version.o
+tobj1 = tarray.o tcmd.o tcons.o tconsarg.o tdoarg.o tdoio.o tdolist.o tdump.o
+tobj2 = teval.o tform.o thash.o $(mallocobj) tregcomp.o tregexec.o
+tobj3 = tstab.o tstr.o ttoke.o tutil.o
 
-obj = $(obj1) $(obj2)
+tobj = $(tobj1) $(tobj2) $(tobj3)
 
-lintflags = -phbvxac
+lintflags = -hbvxac
 
 addedbyconf = Makefile.old bsd eunice filexp loc pdp11 usg v7
 
@@ -90,57 +95,183 @@ SHELL = /bin/sh
 .c.o:
        $(CC) -c $(CFLAGS) $(LARGE) $*.c
 
-all: $(public) $(private) $(util)
+all: $(public) $(private) $(util) perl.man x2p/all
        touch all
 
-perl: perly.o $(obj) perl.o
-       $(CC) $(LDFLAGS) $(LARGE) perly.o $(obj) perl.o $(libs) -o perl
+x2p/all:
+       cd x2p; $(MAKE) all
 
-!NO!SUBS!
+# This is the standard version that contains no "taint" checks and is
+# used for all scripts that aren't set-id or running under something set-id.
 
-case "$d_dosuid" in
-*define*)
-    cat >>Makefile <<'!NO!SUBS!'
+perl: perl.o $(obj)
+       $(CC) $(LARGE) $(LDFLAGS) $(obj) perl.o $(libs) -o perl
+
+# This version, if specified in Configure, does ONLY those scripts which need
+# set-id emulation.  Suidperl must be setuid root.  It contains the "taint"
+# checks as well as the special code to validate that the script in question
+# has been invoked correctly.
 
-suidperl: sperly.o $(obj) perl.o
-       $(CC) $(LDFLAGS) $(LARGE) sperly.o $(obj) perl.o $(libs) -o suidperl
+suidperl: tperl.o sperly.o $(tobj)
+       $(CC) $(LARGE) $(LDFLAGS) sperly.o $(tobj) tperl.o $(libs) -o suidperl
 
-sperly.o: perly.c
+# This version interprets scripts that are already set-id either via a wrapper
+# or through the kernel allowing set-id scripts (bad idea).  Taintperl must
+# NOT be setuid to root or anything else.  The only difference between it
+# and normal perl is the presence of the "taint" checks.
+
+taintperl: tperl.o tperly.o $(tobj)
+       $(CC) $(LARGE) $(LDFLAGS) tperly.o $(tobj) tperl.o $(libs) -o taintperl
+
+# Replicating all this junk is yucky, but I don't see a portable way to fix it.
+
+tperl.o: perl.c perly.h perl.h EXTERN.h regexp.h util.h INTERN.h handy.h \
+    config.h stab.h
+       /bin/rm -f tperl.c
+       $(SLN) perl.c tperl.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tperl.c
+       /bin/rm -f tperl.c
+
+tperly.o: perly.c
+       /bin/rm -f tperly.c
+       $(SLN) perly.c tperly.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tperly.c
+       /bin/rm -f tperly.c
+
+sperly.o: perly.c perl.h handy.h perly.h patchlevel.h
        /bin/rm -f sperly.c
-       ln perly.c sperly.c
-       $(CC) -c -DIAMSUID $(CFLAGS) $(LARGE) sperly.c
+       $(SLN) perly.c sperly.c
+       $(CC) -c -DTAINT -DIAMSUID $(CFLAGS) $(LARGE) sperly.c
        /bin/rm -f sperly.c
-!NO!SUBS!
-    ;;
-esac
 
-cat >>Makefile <<'!NO!SUBS!'
+tarray.o: array.c
+       /bin/rm -f tarray.c
+       $(SLN) array.c tarray.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tarray.c
+       /bin/rm -f tarray.c
+
+tcmd.o: cmd.c
+       /bin/rm -f tcmd.c
+       $(SLN) cmd.c tcmd.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tcmd.c
+       /bin/rm -f tcmd.c
+
+tcons.o: cons.c
+       /bin/rm -f tcons.c
+       $(SLN) cons.c tcons.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tcons.c
+       /bin/rm -f tcons.c
+
+tconsarg.o: consarg.c
+       /bin/rm -f tconsarg.c
+       $(SLN) consarg.c tconsarg.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tconsarg.c
+       /bin/rm -f tconsarg.c
+
+tdoarg.o: doarg.c
+       /bin/rm -f tdoarg.c
+       $(SLN) doarg.c tdoarg.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdoarg.c
+       /bin/rm -f tdoarg.c
+
+tdoio.o: doio.c
+       /bin/rm -f tdoio.c
+       $(SLN) doio.c tdoio.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdoio.c
+       /bin/rm -f tdoio.c
+
+tdolist.o: dolist.c
+       /bin/rm -f tdolist.c
+       $(SLN) dolist.c tdolist.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdolist.c
+       /bin/rm -f tdolist.c
+
+tdump.o: dump.c
+       /bin/rm -f tdump.c
+       $(SLN) dump.c tdump.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tdump.c
+       /bin/rm -f tdump.c
+
+teval.o: eval.c
+       /bin/rm -f teval.c
+       $(SLN) eval.c teval.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) teval.c
+       /bin/rm -f teval.c
+
+tform.o: form.c
+       /bin/rm -f tform.c
+       $(SLN) form.c tform.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tform.c
+       /bin/rm -f tform.c
+
+thash.o: hash.c
+       /bin/rm -f thash.c
+       $(SLN) hash.c thash.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) thash.c
+       /bin/rm -f thash.c
+
+tregcomp.o: regcomp.c
+       /bin/rm -f tregcomp.c
+       $(SLN) regcomp.c tregcomp.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tregcomp.c
+       /bin/rm -f tregcomp.c
+
+tregexec.o: regexec.c
+       /bin/rm -f tregexec.c
+       $(SLN) regexec.c tregexec.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tregexec.c
+       /bin/rm -f tregexec.c
+
+tstab.o: stab.c
+       /bin/rm -f tstab.c
+       $(SLN) stab.c tstab.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tstab.c
+       /bin/rm -f tstab.c
+
+tstr.o: str.c
+       /bin/rm -f tstr.c
+       $(SLN) str.c tstr.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tstr.c
+       /bin/rm -f tstr.c
+
+ttoke.o: toke.c
+       /bin/rm -f ttoke.c
+       $(SLN) toke.c ttoke.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) ttoke.c
+       /bin/rm -f ttoke.c
+
+tutil.o: util.c
+       /bin/rm -f tutil.c
+       $(SLN) util.c tutil.c
+       $(CC) -c -DTAINT $(CFLAGS) $(LARGE) tutil.c
+       /bin/rm -f tutil.c
 
 perl.c perly.h: perl.y
-       @ echo Expect 37 shift/reduce errors...
+       @ echo Expect 25 shift/reduce errors...
        yacc -d perl.y
        mv y.tab.c perl.c
        mv y.tab.h perly.h
 
-perl.o: perl.c perly.h perl.h EXTERN.h regexp.h util.h INTERN.h handy.h config.h
+perl.o: perl.c perly.h perl.h EXTERN.h regexp.h util.h INTERN.h handy.h \
+    config.h arg.h stab.h
        $(CC) -c $(CFLAGS) $(LARGE) perl.c
 
-# if a .h file depends on another .h file...
-$(h):
-       touch $@
-
-perl.man: perl.man.1 perl.man.2
-       cat perl.man.1 perl.man.2 >perl.man
+perl.man: perl.man.1 perl.man.2 perl.man.3 perl.man.4 patchlevel.h perl
+       ./perl  -e '($$r,$$p)=$$]=~/(\d+\.\d+).*\n\D*(\d+)/;' \
+               -e 'print ".ds RP Release $$r Patchlevel $$p\n";' >perl.man
+       cat perl.man.[1-4] >>perl.man
 
-install: perl perl.man
+install: all
 # won't work with csh
        export PATH || exit 1
+       - rm -f $(bin)/perl.old $(bin)/suidperl $(bin)/taintperl
        - mv $(bin)/perl $(bin)/perl.old 2>/dev/null
        - if test `pwd` != $(bin); then cp $(public) $(bin); fi
        - cd $(bin); \
 for pub in $(public); do \
 chmod +x `basename $$pub`; \
 done
+       - chmod 755 $(bin)/taintperl 2>/dev/null
 !NO!SUBS!
 
 case "$d_dosuid" in
@@ -154,13 +285,12 @@ esac
 cat >>Makefile <<'!NO!SUBS!'
        - test $(bin) = /usr/bin || rm -f /usr/bin/perl
        - test $(bin) = /usr/bin || $(SLN) $(bin)/perl /usr/bin || cp $(bin)/perl /usr/bin
-       chmod +x makedir
-       - ./makedir $(lib)
+       - sh ./makedir $(privlib)
        - \
-if test `pwd` != $(lib); then \
-cp $(private) lib/*.pl $(lib); \
+if test `pwd` != $(privlib); then \
+cp $(private) lib/*.pl $(privlib); \
 fi
-#      cd $(lib); \
+#      cd $(privlib); \
 #for priv in $(private); do \
 #chmod +x `basename $$priv`; \
 #done
@@ -169,12 +299,17 @@ for page in $(manpages); do \
 cp $$page $(mansrc)/`basename $$page .man`.$(manext); \
 done; \
 fi
+       cd x2p; $(MAKE) install
 
 clean:
-       rm -f *.o
+       rm -f *.o all perl taintperl perl.man
+       cd x2p; $(MAKE) clean
 
 realclean:
-       rm -f perl *.orig */*.orig *~ */*~ *.o core $(addedbyconf)
+       cd x2p; $(MAKE) realclean
+       rm -f perl *.orig */*.orig *~ */*~ *.o core $(addedbyconf) perl.man
+       rm -f perl.c perly.h t/perl Makefile config.h makedepend makedir
+       rm -f x2p/Makefile
 
 # The following lint has practically everything turned on.  Unfortunately,
 # you have to wade through a lot of mumbo jumbo that can't be suppressed.
@@ -188,9 +323,10 @@ depend: makedepend
        - test -f perly.h || cp /dev/null perly.h
        ./makedepend
        - test -s perly.h || /bin/rm -f perly.h
+       cd x2p; $(MAKE) depend
 
 test: perl
-       chmod +x t/TEST t/base.* t/comp.* t/cmd.* t/io.* t/op.*
+       - chmod +x t/TEST t/base.* t/comp.* t/cmd.* t/io.* t/op.*; \
        cd t && (rm -f perl; $(SLN) ../perl .) && ./perl TEST
 
 clist:
diff --git a/PACKINGLIST b/PACKINGLIST
new file mode 100644 (file)
index 0000000..1232dec
--- /dev/null
@@ -0,0 +1,197 @@
+After all the perl kits are run you should have the following files:
+
+Filename               Kit Description
+--------               --- -----------
+Changes                 20 Differences between 2.0 level 18 and 3.0 level 0
+Configure                2 Run this first
+Copying                 10 The GNU General Public License
+EXTERN.h                24 Included before foreign .h files
+INTERN.h                24 Included before domestic .h files
+MANIFEST                20 This list of files
+Makefile.SH             19 Precursor to Makefile
+PACKINGLIST             18 Which files came from which kits
+README                   1 The Instructions
+Wishlist                24 Some things that may or may not happen
+arg.h                   11 Public declarations for the above
+array.c                 21 Numerically subscripted arrays
+array.h                 24 Public declarations for the above
+client                  24 A client to test sockets
+cmd.c                   15 Command interpreter
+cmd.h                   21 Public declarations for the above
+config.H                15 Sample config.h
+config.h.SH             14 Produces config.h
+cons.c                  10 Routines to construct cmd nodes of a parse tree
+consarg.c               14 Routines to construct arg nodes of a parse tree
+doarg.c                 11 Scalar expression evaluation
+doio.c                   7 I/O operations
+dolist.c                16 Array expression evaluation
+dump.c                  20 Debugging output
+eg/ADB                  24 An adb wrapper to put in your crash dir
+eg/README                1 Intro to example perl scripts
+eg/changes              23 A program to list recently changed files
+eg/down                 24 A program to do things to subdirectories
+eg/dus                  24 A program to do du -s on non-mounted dirs
+eg/findcp               17 A find wrapper that implements a -cp switch
+eg/findtar              24 A find wrapper that pumps out a tar file
+eg/g/gcp                22 A program to do a global rcp
+eg/g/gcp.man            23 Manual page for gcp
+eg/g/ged                24 A program to do a global edit
+eg/g/ghosts             22 A sample /etc/ghosts file
+eg/g/gsh                22 A program to do a global rsh
+eg/g/gsh.man            21 Manual page for gsh
+eg/muck                 22 A program to find missing make dependencies
+eg/muck.man             24 Manual page for muck
+eg/myrup                23 A program to find lightly loaded machines
+eg/nih                  24 Script to insert #! workaround
+eg/rename               24 A program to rename files
+eg/rmfrom               24 A program to feed doomed filenames to
+eg/scan/scan_df         23 Scan for filesystem anomalies
+eg/scan/scan_last       23 Scan for login anomalies
+eg/scan/scan_messages   21 Scan for console message anomalies
+eg/scan/scan_passwd      6 Scan for passwd file anomalies
+eg/scan/scan_ps         24 Scan for process anomalies
+eg/scan/scan_sudo       23 Scan for sudo anomalies
+eg/scan/scan_suid       22 Scan for setuid anomalies
+eg/scan/scanner         23 An anomaly reporter
+eg/shmkill              23 A program to remove unused shared memory
+eg/van/empty            24 A program to empty the trashcan
+eg/van/unvanish         23 A program to undo what vanish does
+eg/van/vanexp           24 A program to expire vanished files
+eg/van/vanish           23 A program to put files in a trashcan
+eg/who                  24 A sample who program
+eval.c                   3 The expression evaluator
+evalargs.xc             19 The arg evaluator of eval.c
+form.c                  20 Format processing
+form.h                  24 Public declarations for the above
+gettest                 24 A little script to test the get* routines
+handy.h                 22 Handy definitions
+hash.c                  18 Associative arrays
+hash.h                  23 Public declarations for the above
+ioctl.pl                21 Sample ioctl.pl
+lib/abbrev.pl           24 An abbreviation table builder
+lib/complete.pl         23 A command completion subroutine
+lib/dumpvar.pl          24 A variable dumper
+lib/getopt.pl           23 Perl library supporting option parsing
+lib/getopts.pl          24 Perl library supporting option parsing
+lib/importenv.pl        24 Perl routine to get environment into variables
+lib/look.pl             23 A "look" equivalent
+lib/perldb.pl           18 Perl debugging routines
+lib/stat.pl             24 Perl library supporting stat function
+lib/termcap.pl          22 Perl library supporting termcap usage
+lib/validate.pl         21 Perl library supporting wholesale file mode validation
+makedepend.SH           21 Precursor to makedepend
+makedir.SH              23 Precursor to makedir
+makelib.SH              21 A thing to turn C .h file into perl .h files
+malloc.c                19 A version of malloc you might not want
+patchlevel.h            10 The current patch level of perl
+perl.h                   8 Global declarations
+perl.man.1               1 The manual page(s), first fourth
+perl.man.2               9 The manual page(s), second fourth
+perl.man.3               8 The manual page(s), third fourth
+perl.man.4               6 The manual page(s), fourth fourth
+perl.y                  12 Yacc grammar for perl
+perlsh                  24 A poor man's perl shell
+perly.c                 17 main()
+regcomp.c               12 Regular expression compiler
+regcomp.h                7 Private declarations for above
+regexec.c               13 Regular expression evaluator
+regexp.h                23 Public declarations for the above
+server                  24 A server to test sockets
+spat.h                  23 Search pattern declarations
+stab.c                   9 Symbol table stuff
+stab.h                  20 Public declarations for the above
+str.c                   13 String handling package
+str.h                   14 Public declarations for the above
+t/README                 1 Instructions for regression tests
+t/TEST                  23 The regression tester
+t/base.cond             24 See if conditionals work
+t/base.if               24 See if if works
+t/base.lex              23 See if lexical items work
+t/base.pat              24 See if pattern matching works
+t/base.term             24 See if various terms work
+t/cmd.elsif             24 See if else-if works
+t/cmd.for               23 See if for loops work
+t/cmd.mod               24 See if statement modifiers work
+t/cmd.subval            22 See if subroutine values work
+t/cmd.switch            12 See if switch optimizations work
+t/cmd.while             22 See if while loops work
+t/comp.cmdopt           22 See if command optimization works
+t/comp.cpp              24 See if C preprocessor works
+t/comp.decl             24 See if declarations work
+t/comp.multiline        24 See if multiline strings work
+t/comp.package          24 See if packages work
+t/comp.script           24 See if script invokation works
+t/comp.term             23 See if more terms work
+t/io.argv               23 See if ARGV stuff works
+t/io.dup                24 See if >& works right
+t/io.fs                 22 See if directory manipulations work
+t/io.inplace            24 See if inplace editing works
+t/io.pipe               24 See if secure pipes work
+t/io.print              24 See if print commands work
+t/io.tell               23 See if file seeking works
+t/op.append             24 See if . works
+t/op.array              22 See if array operations work
+t/op.auto               18 See if autoincrement et all work
+t/op.chop               24 See if chop works
+t/op.cond               24 See if conditional expressions work
+t/op.dbm                22 See if dbm binding works
+t/op.delete             24 See if delete works
+t/op.do                 23 See if subroutines work
+t/op.each               23 See if associative iterators work
+t/op.eval               23 See if eval operator works
+t/op.exec               24 See if exec and system work
+t/op.exp                 1 See if math functions work
+t/op.flip               24 See if range operator works
+t/op.fork               24 See if fork works
+t/op.glob               24 See if <*> works
+t/op.goto               24 See if goto works
+t/op.index              24 See if index works
+t/op.int                24 See if int works
+t/op.join               24 See if join works
+t/op.list               10 See if array lists work
+t/op.local              24 See if local works
+t/op.magic              23 See if magic variables work
+t/op.mkdir              24 See if mkdir works
+t/op.oct                24 See if oct and hex work
+t/op.ord                24 See if ord works
+t/op.pack               24 See if pack and unpack work
+t/op.pat                22 See if esoteric patterns work
+t/op.push               15 See if push and pop work
+t/op.range              24 See if .. works
+t/op.read               24 See if read() works
+t/op.regexp             24 See if regular expressions work
+t/op.repeat             23 See if x operator works
+t/op.sleep               8 See if sleep works
+t/op.sort               24 See if sort works
+t/op.split              13 See if split works
+t/op.sprintf            24 See if sprintf works
+t/op.stat               21 See if stat works
+t/op.study              23 See if study works
+t/op.subst              21 See if substitutions work
+t/op.substr             23 See if substr works
+t/op.time               23 See if time functions work
+t/op.undef              23 See if undef works
+t/op.unshift            24 See if unshift works
+t/op.vec                24 See if vectors work
+t/op.write              23 See if write works
+t/re_tests              22 Input file for op.regexp
+toke.c                   5 The tokener
+util.c                  17 Utility routines
+util.h                  24 Public declarations for the above
+x2p/EXTERN.h            24 Same as above
+x2p/INTERN.h            24 Same as above
+x2p/Makefile.SH         22 Precursor to Makefile
+x2p/a2p.h               20 Global declarations
+x2p/a2p.man             20 Manual page for awk to perl translator
+x2p/a2p.y               19 A yacc grammer for awk
+x2p/a2py.c              16 Awk compiler, sort of
+x2p/handy.h             24 Handy definitions
+x2p/hash.c              21 Associative arrays again
+x2p/hash.h              23 Public declarations for the above
+x2p/s2p.SH              18 Sed to perl translator
+x2p/s2p.man             22 Manual page for sed to perl translator
+x2p/str.c               19 String handling package
+x2p/str.h               23 Public declarations for the above
+x2p/util.c              15 Utility routines
+x2p/util.h              24 Public declarations for the above
+x2p/walk.c               4 Parse tree walker
diff --git a/README b/README
index 0fb953a..ba603da 100644 (file)
--- a/README
+++ b/README
@@ -1,10 +1,22 @@
 
-                       Perl Kit, Version 2.0
+                       Perl Kit, Version 3.0
 
-                   Copyright (c) 1988, Larry Wall
+                   Copyright (c) 1989, Larry Wall
+
+    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 1, 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, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-You may copy the perl kit in whole or in part as long as you don't try to
-make money off it, or pretend that you wrote it.
 --------------------------------------------------------------------------
 
 Perl is a language that combines some of the features of C, sed, awk and shell.
@@ -13,7 +25,7 @@ See the manual page for more hype.
 Perl will probably not run on machines with a small address space.
 
 Please read all the directions below before you proceed any further, and
-then follow them carefully.  Failure to do so may void your warranty. :-)
+then follow them carefully.
 
 After you have unpacked your kit, you should have all the files listed
 in MANIFEST.
@@ -58,7 +70,7 @@ Installation
 
 6)  make install
 
-    This will put perl into a public directory (normally /usr/local/bin).
+    This will put perl into a public directory (such as /usr/local/bin).
     It will also try to put the man pages in a reasonable place.  It will not
     nroff the man page, however.  You may need to be root to do this.  If
     you are not root, you must own the directories in question and you should
@@ -66,10 +78,7 @@ Installation
 
 7)  Read the manual entry before running perl.
 
-8)  Go down to the x2p directory and do a "make depend, a "make" and a
-    "make install" to create the awk to perl and sed to perl translators.
-
-9)  IMPORTANT!  Help save the world!  Communicate any problems and suggested
+8)  IMPORTANT!  Help save the world!  Communicate any problems and suggested
     patches to me, lwall@jpl-devvax.jpl.nasa.gov (Larry Wall), so we can
     keep the world in sync.  If you have a problem, there's someone else
     out there who either has had or will have the same problem.
@@ -83,3 +92,9 @@ Installation
     perl and aren't sure how many patches there are, write to me and I'll
     send any you don't have.  Your current patch level is shown in patchlevel.h.
 
+
+Just a personal note:  I want you to know that I create nice things like this
+because it pleases the Author of my story.  If this bothers you, then your
+notion of Authorship needs some revision.  But you can use perl anyway. :-)
+
+                                                       The author.
index 04e757d..13954af 100644 (file)
--- a/Wishlist
+++ b/Wishlist
@@ -1,4 +1,6 @@
-date support
-case statement
-ioctl() support
-random numbers
+ctime to time support
+better format pictures
+pager?
+built-in cpp
+perl to C translator
+multi-threading
diff --git a/arg.c b/arg.c
deleted file mode 100644 (file)
index 4cdb889..0000000
--- a/arg.c
+++ /dev/null
@@ -1,1834 +0,0 @@
-/* $Header: arg.c,v 2.0 88/06/05 00:08:04 root Exp $
- *
- * $Log:       arg.c,v $
- * Revision 2.0  88/06/05  00:08:04  root
- * Baseline version 2.0.
- * 
- */
-
-#include "EXTERN.h"
-#include "perl.h"
-
-#include <signal.h>
-#include <errno.h>
-
-extern int errno;
-
-STR *
-do_match(arg,retary,sarg,ptrmaxsarg,sargoff,cushion)
-register ARG *arg;
-STR ***retary;
-register STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    register SPAT *spat = arg[2].arg_ptr.arg_spat;
-    register char *t;
-    register char *s = str_get(sarg[1]);
-    char *strend = s + sarg[1]->str_cur;
-
-    if (!spat)
-       return &str_yes;
-    if (!s)
-       fatal("panic: do_match");
-    if (retary) {
-       *retary = sarg;         /* assume no match */
-       *ptrmaxsarg = sargoff;
-    }
-    if (spat->spat_flags & SPAT_USED) {
-#ifdef DEBUGGING
-       if (debug & 8)
-           deb("2.SPAT USED\n");
-#endif
-       return &str_no;
-    }
-    if (spat->spat_runtime) {
-       t = str_get(eval(spat->spat_runtime,Null(STR***),-1));
-#ifdef DEBUGGING
-       if (debug & 8)
-           deb("2.SPAT /%s/\n",t);
-#endif
-       spat->spat_regexp = regcomp(t,spat->spat_flags & SPAT_FOLD,1);
-       if (!*spat->spat_regexp->precomp && lastspat)
-           spat = lastspat;
-       if (regexec(spat->spat_regexp, s, strend, TRUE, 0,
-         sarg[1]->str_pok & 4 ? sarg[1] : Nullstr)) {
-           if (spat->spat_regexp->subbase)
-               curspat = spat;
-           lastspat = spat;
-           goto gotcha;
-       }
-       else
-           return &str_no;
-    }
-    else {
-#ifdef DEBUGGING
-       if (debug & 8) {
-           char ch;
-
-           if (spat->spat_flags & SPAT_ONCE)
-               ch = '?';
-           else
-               ch = '/';
-           deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
-       }
-#endif
-       if (!*spat->spat_regexp->precomp && lastspat)
-           spat = lastspat;
-       t = s;
-       if (hint) {
-           if (hint < s || hint > strend)
-               fatal("panic: hint in do_match");
-           s = hint;
-           hint = Nullch;
-           if (spat->spat_regexp->regback >= 0) {
-               s -= spat->spat_regexp->regback;
-               if (s < t)
-                   s = t;
-           }
-           else
-               s = t;
-       }
-       else if (spat->spat_short) {
-           if (spat->spat_flags & SPAT_SCANFIRST) {
-               if (sarg[1]->str_pok == 5) {
-                   if (screamfirst[spat->spat_short->str_rare] < 0)
-                       goto nope;
-                   else if (!(s = screaminstr(sarg[1],spat->spat_short)))
-                       goto nope;
-                   else if (spat->spat_flags & SPAT_ALL)
-                       goto yup;
-               }
-               else if (!(s = fbminstr(s, strend, spat->spat_short)))
-                   goto nope;
-               else if (spat->spat_flags & SPAT_ALL)
-                   goto yup;
-               else if (spat->spat_regexp->regback >= 0) {
-                   ++*(long*)&spat->spat_short->str_nval;
-                   s -= spat->spat_regexp->regback;
-                   if (s < t)
-                       s = t;
-               }
-               else
-                   s = t;
-           }
-           else if (!multiline && (*spat->spat_short->str_ptr != *s ||
-             strnNE(spat->spat_short->str_ptr, s, spat->spat_slen) ))
-               goto nope;
-           if (--*(long*)&spat->spat_short->str_nval < 0) {
-               str_free(spat->spat_short);
-               spat->spat_short = Nullstr;     /* opt is being useless */
-           }
-       }
-       if (regexec(spat->spat_regexp, s, strend, s == t, 0,
-         sarg[1]->str_pok & 4 ? sarg[1] : Nullstr)) {
-           if (spat->spat_regexp->subbase)
-               curspat = spat;
-           lastspat = spat;
-           if (spat->spat_flags & SPAT_ONCE)
-               spat->spat_flags |= SPAT_USED;
-           goto gotcha;
-       }
-       else
-           return &str_no;
-    }
-    /*NOTREACHED*/
-
-  gotcha:
-    if (retary && curspat == spat) {
-       int iters, i, len;
-
-       iters = spat->spat_regexp->nparens;
-       *ptrmaxsarg = iters + sargoff;
-       sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-         (iters+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-
-       for (i = 1; i <= iters; i++) {
-           sarg[i] = str_static(&str_no);
-           if (s = spat->spat_regexp->startp[i]) {
-               len = spat->spat_regexp->endp[i] - s;
-               if (len > 0)
-                   str_nset(sarg[i],s,len);
-           }
-       }
-       *retary = sarg;
-    }
-    return &str_yes;
-
-yup:
-    ++*(long*)&spat->spat_short->str_nval;
-    return &str_yes;
-
-nope:
-    ++*(long*)&spat->spat_short->str_nval;
-    return &str_no;
-}
-
-int
-do_subst(str,arg)
-STR *str;
-register ARG *arg;
-{
-    register SPAT *spat;
-    register STR *dstr;
-    register char *s = str_get(str);
-    char *strend = s + str->str_cur;
-    register char *m;
-
-    spat = arg[2].arg_ptr.arg_spat;
-    if (!spat || !s)
-       fatal("panic: do_subst");
-    else if (spat->spat_runtime) {
-       m = str_get(eval(spat->spat_runtime,Null(STR***),-1));
-       spat->spat_regexp = regcomp(m,spat->spat_flags & SPAT_FOLD,1);
-    }
-#ifdef DEBUGGING
-    if (debug & 8) {
-       deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
-    }
-#endif
-    if (!*spat->spat_regexp->precomp && lastspat)
-       spat = lastspat;
-    m = s;
-    if (hint) {
-       if (hint < s || hint > strend)
-           fatal("panic: hint in do_match");
-       s = hint;
-       hint = Nullch;
-       if (spat->spat_regexp->regback >= 0) {
-           s -= spat->spat_regexp->regback;
-           if (s < m)
-               s = m;
-       }
-       else
-           s = m;
-    }
-    else if (spat->spat_short) {
-       if (spat->spat_flags & SPAT_SCANFIRST) {
-           if (str->str_pok == 5) {
-               if (screamfirst[spat->spat_short->str_rare] < 0)
-                   goto nope;
-               else if (!(s = screaminstr(str,spat->spat_short)))
-                   goto nope;
-           }
-           else if (!(s = fbminstr(s, strend, spat->spat_short)))
-               goto nope;
-           else if (spat->spat_regexp->regback >= 0) {
-               ++*(long*)&spat->spat_short->str_nval;
-               s -= spat->spat_regexp->regback;
-               if (s < m)
-                   s = m;
-           }
-           else
-               s = m;
-       }
-       else if (!multiline && (*spat->spat_short->str_ptr != *s ||
-         strnNE(spat->spat_short->str_ptr, s, spat->spat_slen) ))
-           goto nope;
-       if (--*(long*)&spat->spat_short->str_nval < 0) {
-           str_free(spat->spat_short);
-           spat->spat_short = Nullstr; /* opt is being useless */
-       }
-    }
-    if (regexec(spat->spat_regexp, s, strend, s == m, 1,
-      str->str_pok & 4 ? str : Nullstr)) {
-       int iters = 0;
-
-       dstr = str_new(str_len(str));
-       str_nset(dstr,m,s-m);
-       if (spat->spat_regexp->subbase)
-           curspat = spat;
-       lastspat = spat;
-       do {
-           m = spat->spat_regexp->startp[0];
-           if (iters++ > 10000)
-               fatal("Substitution loop");
-           if (spat->spat_regexp->subbase)
-               s = spat->spat_regexp->subbase;
-           str_ncat(dstr,s,m-s);
-           s = spat->spat_regexp->endp[0];
-           str_scat(dstr,eval(spat->spat_repl,Null(STR***),-1));
-           if (spat->spat_flags & SPAT_ONCE)
-               break;
-       } while (regexec(spat->spat_regexp, s, strend, FALSE, 1, Nullstr));
-       str_cat(dstr,s);
-       str_replace(str,dstr);
-       STABSET(str);
-       return iters;
-    }
-    return 0;
-
-nope:
-    ++*(long*)&spat->spat_short->str_nval;
-    return 0;
-}
-
-int
-do_trans(str,arg)
-STR *str;
-register ARG *arg;
-{
-    register char *tbl;
-    register char *s;
-    register int matches = 0;
-    register int ch;
-
-    tbl = arg[2].arg_ptr.arg_cval;
-    s = str_get(str);
-    if (!tbl || !s)
-       fatal("panic: do_trans");
-#ifdef DEBUGGING
-    if (debug & 8) {
-       deb("2.TBL\n");
-    }
-#endif
-    while (*s) {
-       if (ch = tbl[*s & 0377]) {
-           matches++;
-           *s = ch;
-       }
-       s++;
-    }
-    STABSET(str);
-    return matches;
-}
-
-int
-do_split(spat,retary,sarg,ptrmaxsarg,sargoff,cushion)
-register SPAT *spat;
-STR ***retary;
-register STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    register char *s = str_get(sarg[1]);
-    char *strend = s + sarg[1]->str_cur;
-    register STR *dstr;
-    register char *m;
-    register ARRAY *ary;
-    static ARRAY *myarray = Null(ARRAY*);
-    int iters = 0;
-    int i;
-
-    if (!spat || !s)
-       fatal("panic: do_split");
-    else if (spat->spat_runtime) {
-       m = str_get(eval(spat->spat_runtime,Null(STR***),-1));
-       if (!*m || (*m == ' ' && !m[1])) {
-           m = "\\s+";
-           spat->spat_flags |= SPAT_SKIPWHITE;
-       }
-       if (spat->spat_runtime->arg_type == O_ITEM &&
-         spat->spat_runtime[1].arg_type == A_SINGLE) {
-           arg_free(spat->spat_runtime);       /* it won't change, so */
-           spat->spat_runtime = Nullarg;       /* no point compiling again */
-       }
-       spat->spat_regexp = regcomp(m,spat->spat_flags & SPAT_FOLD,1);
-    }
-#ifdef DEBUGGING
-    if (debug & 8) {
-       deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
-    }
-#endif
-    if (retary)
-       ary = myarray;
-    else
-       ary = spat->spat_repl[1].arg_ptr.arg_stab->stab_array;
-    if (!ary)
-       myarray = ary = anew(Nullstab);
-    ary->ary_fill = -1;
-    if (spat->spat_flags & SPAT_SKIPWHITE) {
-       while (isspace(*s))
-           s++;
-    }
-    if (spat->spat_short) {
-       i = spat->spat_short->str_cur;
-       while (*s && (m = fbminstr(s, strend, spat->spat_short))) {
-           dstr = str_new(m-s);
-           str_nset(dstr,s,m-s);
-           astore(ary, iters++, dstr);
-           if (iters > 10000)
-               fatal("Substitution loop");
-           s = m + i;
-       }
-    }
-    else {
-       while (*s && regexec(spat->spat_regexp, s, strend, (iters == 0), 1,
-         Nullstr)) {
-           m = spat->spat_regexp->startp[0];
-           if (spat->spat_regexp->subbase)
-               s = spat->spat_regexp->subbase;
-           dstr = str_new(m-s);
-           str_nset(dstr,s,m-s);
-           astore(ary, iters++, dstr);
-           if (iters > 10000)
-               fatal("Substitution loop");
-           s = spat->spat_regexp->endp[0];
-       }
-    }
-    if (*s) {                  /* ignore field after final "whitespace" */
-       dstr = str_new(0);      /*   if they interpolate, it's null anyway */
-       str_set(dstr,s);
-       astore(ary, iters++, dstr);
-    }
-    else {
-       while (iters > 0 && !*str_get(afetch(ary,iters-1)))
-           iters--;
-    }
-    if (retary) {
-       *ptrmaxsarg = iters + sargoff;
-       sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-         (iters+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-
-       for (i = 1; i <= iters; i++)
-           sarg[i] = afetch(ary,i-1);
-       *retary = sarg;
-    }
-    return iters;
-}
-
-void
-do_join(arg,delim,str)
-register ARG *arg;
-register char *delim;
-register STR *str;
-{
-    STR **tmpary;      /* must not be register */
-    register STR **elem;
-    register int items;
-
-    (void)eval(arg[2].arg_ptr.arg_arg,&tmpary,-1);
-    items = (int)str_gnum(*tmpary);
-    elem = tmpary+1;
-    if (items-- > 0)
-       str_sset(str,*elem++);
-    for (; items > 0; items--,elem++) {
-       str_cat(str,delim);
-       str_scat(str,*elem);
-    }
-    STABSET(str);
-    safefree((char*)tmpary);
-}
-
-FILE *
-forkopen(name,mode)
-char *name;
-char *mode;
-{
-    int pfd[2];
-
-    if (pipe(pfd) < 0)
-       return Nullfp;
-    while ((forkprocess = fork()) == -1) {
-       if (errno != EAGAIN)
-           return Nullfp;
-       sleep(5);
-    }
-    if (*mode == 'w') {
-       if (forkprocess) {
-           close(pfd[0]);
-           return fdopen(pfd[1],"w");
-       }
-       else {
-           close(pfd[1]);
-           close(0);
-           dup(pfd[0]);        /* substitute our pipe for stdin */
-           close(pfd[0]);
-           return Nullfp;
-       }
-    }
-    else {
-       if (forkprocess) {
-           close(pfd[1]);
-           return fdopen(pfd[0],"r");
-       }
-       else {
-           close(pfd[0]);
-           close(1);
-           if (dup(pfd[1]) == 0)
-               dup(pfd[1]);    /* substitute our pipe for stdout */
-           close(pfd[1]);
-           return Nullfp;
-       }
-    }
-}
-
-bool
-do_open(stab,name)
-STAB *stab;
-register char *name;
-{
-    FILE *fp;
-    int len = strlen(name);
-    register STIO *stio = stab->stab_io;
-    char *myname = savestr(name);
-    int result;
-    int fd;
-
-    name = myname;
-    forkprocess = 1;           /* assume true if no fork */
-    while (len && isspace(name[len-1]))
-       name[--len] = '\0';
-    if (!stio)
-       stio = stab->stab_io = stio_new();
-    if (stio->fp) {
-       fd = fileno(stio->fp);
-       if (stio->type == '|')
-           result = pclose(stio->fp);
-       else if (stio->type != '-')
-           result = fclose(stio->fp);
-       else
-           result = 0;
-       if (result == EOF && fd > 2)
-           fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
-             stab->stab_name);
-       stio->fp = Nullfp;
-    }
-    stio->type = *name;
-    if (*name == '|') {
-       for (name++; isspace(*name); name++) ;
-       if (strNE(name,"-"))
-           fp = popen(name,"w");
-       else {
-           fp = forkopen(name,"w");
-           stio->subprocess = forkprocess;
-           stio->type = '%';
-       }
-    }
-    else if (*name == '>' && name[1] == '>') {
-       stio->type = 'a';
-       for (name += 2; isspace(*name); name++) ;
-       fp = fopen(name,"a");
-    }
-    else if (*name == '>' && name[1] == '&') {
-       for (name += 2; isspace(*name); name++) ;
-       if (isdigit(*name))
-           fd = atoi(name);
-       else {
-           stab = stabent(name,FALSE);
-           if (stab->stab_io && stab->stab_io->fp) {
-               fd = fileno(stab->stab_io->fp);
-               stio->type = stab->stab_io->type;
-           }
-           else
-               fd = -1;
-       }
-       fp = fdopen(dup(fd),stio->type == 'a' ? "a" :
-         (stio->type == '<' ? "r" : "w") );
-    }
-    else if (*name == '>') {
-       for (name++; isspace(*name); name++) ;
-       if (strEQ(name,"-")) {
-           fp = stdout;
-           stio->type = '-';
-       }
-       else
-           fp = fopen(name,"w");
-    }
-    else {
-       if (*name == '<') {
-           for (name++; isspace(*name); name++) ;
-           if (strEQ(name,"-")) {
-               fp = stdin;
-               stio->type = '-';
-           }
-           else
-               fp = fopen(name,"r");
-       }
-       else if (name[len-1] == '|') {
-           name[--len] = '\0';
-           while (len && isspace(name[len-1]))
-               name[--len] = '\0';
-           for (; isspace(*name); name++) ;
-           if (strNE(name,"-")) {
-               fp = popen(name,"r");
-               stio->type = '|';
-           }
-           else {
-               fp = forkopen(name,"r");
-               stio->subprocess = forkprocess;
-               stio->type = '%';
-           }
-       }
-       else {
-           stio->type = '<';
-           for (; isspace(*name); name++) ;
-           if (strEQ(name,"-")) {
-               fp = stdin;
-               stio->type = '-';
-           }
-           else
-               fp = fopen(name,"r");
-       }
-    }
-    safefree(myname);
-    if (!fp)
-       return FALSE;
-    if (stio->type &&
-      stio->type != '|' && stio->type != '-' && stio->type != '%') {
-       if (fstat(fileno(fp),&statbuf) < 0) {
-           fclose(fp);
-           return FALSE;
-       }
-       if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
-           (statbuf.st_mode & S_IFMT) != S_IFCHR) {
-           fclose(fp);
-           return FALSE;
-       }
-    }
-    stio->fp = fp;
-    return TRUE;
-}
-
-FILE *
-nextargv(stab)
-register STAB *stab;
-{
-    register STR *str;
-    char *oldname;
-    int filemode,fileuid,filegid;
-
-    while (alen(stab->stab_array) >= 0) {
-       str = ashift(stab->stab_array);
-       str_sset(stab->stab_val,str);
-       STABSET(stab->stab_val);
-       oldname = str_get(stab->stab_val);
-       if (do_open(stab,oldname)) {
-           if (inplace) {
-               filemode = statbuf.st_mode;
-               fileuid = statbuf.st_uid;
-               filegid = statbuf.st_gid;
-               if (*inplace) {
-                   str_cat(str,inplace);
-#ifdef RENAME
-                   rename(oldname,str->str_ptr);
-#else
-                   UNLINK(str->str_ptr);
-                   link(oldname,str->str_ptr);
-                   UNLINK(oldname);
-#endif
-               }
-               else {
-                   UNLINK(oldname);
-               }
-               sprintf(tokenbuf,">%s",oldname);
-               errno = 0;              /* in case sprintf set errno */
-               do_open(argvoutstab,tokenbuf);
-               defoutstab = argvoutstab;
-#ifdef FCHMOD
-               fchmod(fileno(argvoutstab->stab_io->fp),filemode);
-#else
-               chmod(oldname,filemode);
-#endif
-#ifdef FCHOWN
-               fchown(fileno(argvoutstab->stab_io->fp),fileuid,filegid);
-#else
-               chown(oldname,fileuid,filegid);
-#endif
-           }
-           str_free(str);
-           return stab->stab_io->fp;
-       }
-       else
-           fprintf(stderr,"Can't open %s\n",str_get(str));
-       str_free(str);
-    }
-    if (inplace) {
-       do_close(argvoutstab,FALSE);
-       defoutstab = stabent("stdout",TRUE);
-    }
-    return Nullfp;
-}
-
-bool
-do_close(stab,explicit)
-STAB *stab;
-bool explicit;
-{
-    bool retval = FALSE;
-    register STIO *stio = stab->stab_io;
-    int status;
-    int tmp;
-
-    if (!stio) {               /* never opened */
-       if (dowarn && explicit)
-           warn("Close on unopened file <%s>",stab->stab_name);
-       return FALSE;
-    }
-    if (stio->fp) {
-       if (stio->type == '|')
-           retval = (pclose(stio->fp) >= 0);
-       else if (stio->type == '-')
-           retval = TRUE;
-       else {
-           retval = (fclose(stio->fp) != EOF);
-           if (stio->type == '%' && stio->subprocess) {
-               while ((tmp = wait(&status)) != stio->subprocess && tmp != -1)
-                   ;
-               if (tmp == -1)
-                   statusvalue = -1;
-               else
-                   statusvalue = (unsigned)status & 0xffff;
-           }
-       }
-       stio->fp = Nullfp;
-    }
-    if (explicit)
-       stio->lines = 0;
-    stio->type = ' ';
-    return retval;
-}
-
-bool
-do_eof(stab)
-STAB *stab;
-{
-    register STIO *stio;
-    int ch;
-
-    if (!stab)                 /* eof() */
-       stio = argvstab->stab_io;
-    else
-       stio = stab->stab_io;
-
-    if (!stio)
-       return TRUE;
-
-    while (stio->fp) {
-
-#ifdef STDSTDIO                        /* (the code works without this) */
-       if (stio->fp->_cnt)             /* cheat a little, since */
-           return FALSE;               /* this is the most usual case */
-#endif
-
-       ch = getc(stio->fp);
-       if (ch != EOF) {
-           ungetc(ch, stio->fp);
-           return FALSE;
-       }
-       if (!stab) {                    /* not necessarily a real EOF yet? */
-           if (!nextargv(argvstab))    /* get another fp handy */
-               return TRUE;
-       }
-       else
-           return TRUE;                /* normal fp, definitely end of file */
-    }
-    return TRUE;
-}
-
-long
-do_tell(stab)
-STAB *stab;
-{
-    register STIO *stio;
-
-    if (!stab)
-       goto phooey;
-
-    stio = stab->stab_io;
-    if (!stio || !stio->fp)
-       goto phooey;
-
-    return ftell(stio->fp);
-
-phooey:
-    if (dowarn)
-       warn("tell() on unopened file");
-    return -1L;
-}
-
-bool
-do_seek(stab, pos, whence)
-STAB *stab;
-long pos;
-int whence;
-{
-    register STIO *stio;
-
-    if (!stab)
-       goto nuts;
-
-    stio = stab->stab_io;
-    if (!stio || !stio->fp)
-       goto nuts;
-
-    return fseek(stio->fp, pos, whence) >= 0;
-
-nuts:
-    if (dowarn)
-       warn("seek() on unopened file");
-    return FALSE;
-}
-
-static CMD *sortcmd;
-static STAB *firststab = Nullstab;
-static STAB *secondstab = Nullstab;
-
-do_sort(arg,stab,retary,sarg,ptrmaxsarg,sargoff,cushion)
-register ARG *arg;
-STAB *stab;
-STR ***retary;
-register STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    STR **tmpary;      /* must not be register */
-    register STR **elem;
-    register bool retval;
-    register int max;
-    register int i;
-    int sortcmp();
-    int sortsub();
-    STR *oldfirst;
-    STR *oldsecond;
-
-    (void)eval(arg[1].arg_ptr.arg_arg,&tmpary,-1);
-    max = (int)str_gnum(*tmpary);
-
-    if (retary) {
-       sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-         (max+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-       for (i = 1; i <= max; i++)
-           sarg[i] = tmpary[i];
-       *retary = sarg;
-       if (max > 1) {
-           if (stab->stab_sub && (sortcmd = stab->stab_sub->cmd)) {
-               if (!firststab) {
-                   firststab = stabent("a",TRUE);
-                   secondstab = stabent("b",TRUE);
-               }
-               oldfirst = firststab->stab_val;
-               oldsecond = secondstab->stab_val;
-               qsort((char*)(sarg+1),max,sizeof(STR*),sortsub);
-               firststab->stab_val = oldfirst;
-               secondstab->stab_val = oldsecond;
-           }
-           else
-               qsort((char*)(sarg+1),max,sizeof(STR*),sortcmp);
-       }
-       while (max > 0 && !sarg[max])
-           max--;
-       *ptrmaxsarg = max + sargoff;
-    }
-    safefree((char*)tmpary);
-    return max;
-}
-
-int
-sortcmp(str1,str2)
-STR **str1;
-STR **str2;
-{
-    char *tmps;
-
-    if (!*str1)
-       return -1;
-    if (!*str2)
-       return 1;
-    tmps = str_get(*str1);
-    return strcmp(tmps,str_get(*str2));
-}
-
-int
-sortsub(str1,str2)
-STR **str1;
-STR **str2;
-{
-    STR *str;
-
-    if (!*str1)
-       return -1;
-    if (!*str2)
-       return 1;
-    firststab->stab_val = *str1;
-    secondstab->stab_val = *str2;
-    return (int)str_gnum(cmd_exec(sortcmd));
-}
-
-do_stat(arg,retary,sarg,ptrmaxsarg,sargoff,cushion)
-register ARG *arg;
-STR ***retary;
-register STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    register ARRAY *ary;
-    static ARRAY *myarray = Null(ARRAY*);
-    int max = 13;
-    register int i;
-
-    ary = myarray;
-    if (!ary)
-       myarray = ary = anew(Nullstab);
-    ary->ary_fill = -1;
-    if (arg[1].arg_type == A_LVAL) {
-       tmpstab = arg[1].arg_ptr.arg_stab;
-       if (!tmpstab->stab_io ||
-         fstat(fileno(tmpstab->stab_io->fp),&statbuf) < 0) {
-           max = 0;
-       }
-    }
-    else
-       if (stat(str_get(sarg[1]),&statbuf) < 0)
-           max = 0;
-
-    if (retary) {
-       if (max) {
-           apush(ary,str_nmake((double)statbuf.st_dev));
-           apush(ary,str_nmake((double)statbuf.st_ino));
-           apush(ary,str_nmake((double)statbuf.st_mode));
-           apush(ary,str_nmake((double)statbuf.st_nlink));
-           apush(ary,str_nmake((double)statbuf.st_uid));
-           apush(ary,str_nmake((double)statbuf.st_gid));
-           apush(ary,str_nmake((double)statbuf.st_rdev));
-           apush(ary,str_nmake((double)statbuf.st_size));
-           apush(ary,str_nmake((double)statbuf.st_atime));
-           apush(ary,str_nmake((double)statbuf.st_mtime));
-           apush(ary,str_nmake((double)statbuf.st_ctime));
-#ifdef STATBLOCKS
-           apush(ary,str_nmake((double)statbuf.st_blksize));
-           apush(ary,str_nmake((double)statbuf.st_blocks));
-#else
-           apush(ary,str_make(""));
-           apush(ary,str_make(""));
-#endif
-       }
-       *ptrmaxsarg = max + sargoff;
-       sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-         (max+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-       for (i = 1; i <= max; i++)
-           sarg[i] = afetch(ary,i-1);
-       *retary = sarg;
-    }
-    return max;
-}
-
-do_tms(retary,sarg,ptrmaxsarg,sargoff,cushion)
-STR ***retary;
-STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    register ARRAY *ary;
-    static ARRAY *myarray = Null(ARRAY*);
-    int max = 4;
-    register int i;
-
-    ary = myarray;
-    if (!ary)
-       myarray = ary = anew(Nullstab);
-    ary->ary_fill = -1;
-    times(&timesbuf);
-
-#ifndef HZ
-#define HZ 60
-#endif
-
-    if (retary) {
-       if (max) {
-           apush(ary,str_nmake(((double)timesbuf.tms_utime)/HZ));
-           apush(ary,str_nmake(((double)timesbuf.tms_stime)/HZ));
-           apush(ary,str_nmake(((double)timesbuf.tms_cutime)/HZ));
-           apush(ary,str_nmake(((double)timesbuf.tms_cstime)/HZ));
-       }
-       *ptrmaxsarg = max + sargoff;
-       sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-         (max+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-       for (i = 1; i <= max; i++)
-           sarg[i] = afetch(ary,i-1);
-       *retary = sarg;
-    }
-    return max;
-}
-
-do_time(tmbuf,retary,sarg,ptrmaxsarg,sargoff,cushion)
-struct tm *tmbuf;
-STR ***retary;
-STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    register ARRAY *ary;
-    static ARRAY *myarray = Null(ARRAY*);
-    int max = 9;
-    register int i;
-
-    ary = myarray;
-    if (!ary)
-       myarray = ary = anew(Nullstab);
-    ary->ary_fill = -1;
-    if (!tmbuf)
-       max = 0;
-
-    if (retary) {
-       if (max) {
-           apush(ary,str_nmake((double)tmbuf->tm_sec));
-           apush(ary,str_nmake((double)tmbuf->tm_min));
-           apush(ary,str_nmake((double)tmbuf->tm_hour));
-           apush(ary,str_nmake((double)tmbuf->tm_mday));
-           apush(ary,str_nmake((double)tmbuf->tm_mon));
-           apush(ary,str_nmake((double)tmbuf->tm_year));
-           apush(ary,str_nmake((double)tmbuf->tm_wday));
-           apush(ary,str_nmake((double)tmbuf->tm_yday));
-           apush(ary,str_nmake((double)tmbuf->tm_isdst));
-       }
-       *ptrmaxsarg = max + sargoff;
-       sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-         (max+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-       for (i = 1; i <= max; i++)
-           sarg[i] = afetch(ary,i-1);
-       *retary = sarg;
-    }
-    return max;
-}
-
-void
-do_sprintf(str,len,sarg)
-register STR *str;
-register int len;
-register STR **sarg;
-{
-    register char *s;
-    register char *t;
-    bool dolong;
-    char ch;
-    static STR *sargnull = &str_no;
-
-    str_set(str,"");
-    len--;                     /* don't count pattern string */
-    sarg++;
-    for (s = str_get(*(sarg++)); *s; len--) {
-       if (len <= 0 || !*sarg) {
-           sarg = &sargnull;
-           len = 0;
-       }
-       dolong = FALSE;
-       for (t = s; *t && *t != '%'; t++) ;
-       if (!*t)
-           break;              /* not enough % patterns, oh well */
-       for (t++; *sarg && *t && t != s; t++) {
-           switch (*t) {
-           case '\0':
-               t--;
-               break;
-           case '%':
-               ch = *(++t);
-               *t = '\0';
-               sprintf(buf,s);
-               s = t;
-               *(t--) = ch;
-               break;
-           case 'l':
-               dolong = TRUE;
-               break;
-           case 'D': case 'X': case 'O':
-               dolong = TRUE;
-               /* FALL THROUGH */
-           case 'd': case 'x': case 'o': case 'c': case 'u':
-               ch = *(++t);
-               *t = '\0';
-               if (dolong)
-                   sprintf(buf,s,(long)str_gnum(*(sarg++)));
-               else
-                   sprintf(buf,s,(int)str_gnum(*(sarg++)));
-               s = t;
-               *(t--) = ch;
-               break;
-           case 'E': case 'e': case 'f': case 'G': case 'g':
-               ch = *(++t);
-               *t = '\0';
-               sprintf(buf,s,str_gnum(*(sarg++)));
-               s = t;
-               *(t--) = ch;
-               break;
-           case 's':
-               ch = *(++t);
-               *t = '\0';
-               if (strEQ(s,"%s")) {    /* some printfs fail on >128 chars */
-                   *buf = '\0';
-                   str_scat(str,*(sarg++));  /* so handle simple case */
-               }
-               else
-                   sprintf(buf,s,str_get(*(sarg++)));
-               s = t;
-               *(t--) = ch;
-               break;
-           }
-       }
-       str_cat(str,buf);
-    }
-    if (*s)
-       str_cat(str,s);
-    STABSET(str);
-}
-
-bool
-do_print(str,fp)
-register STR *str;
-FILE *fp;
-{
-    if (!fp) {
-       if (dowarn)
-           warn("print to unopened file");
-       return FALSE;
-    }
-    if (!str)
-       return FALSE;
-    if (ofmt &&
-      ((str->str_nok && str->str_nval != 0.0) || str_gnum(str) != 0.0) )
-       fprintf(fp, ofmt, str->str_nval);
-    else
-       fputs(str_get(str),fp);
-    return TRUE;
-}
-
-bool
-do_aprint(arg,fp)
-register ARG *arg;
-register FILE *fp;
-{
-    STR **tmpary;      /* must not be register */
-    register STR **elem;
-    register bool retval;
-    register int items;
-
-    if (!fp) {
-       if (dowarn)
-           warn("print to unopened file");
-       return FALSE;
-    }
-    (void)eval(arg[1].arg_ptr.arg_arg,&tmpary,-1);
-    items = (int)str_gnum(*tmpary);
-    if (arg->arg_type == O_PRTF) {
-       do_sprintf(arg->arg_ptr.arg_str,items,tmpary);
-       retval = do_print(arg->arg_ptr.arg_str,fp);
-    }
-    else {
-       retval = FALSE;
-       for (elem = tmpary+1; items > 0; items--,elem++) {
-           if (retval && ofs)
-               fputs(ofs, fp);
-           retval = do_print(*elem, fp);
-           if (!retval)
-               break;
-       }
-       if (ors)
-           fputs(ors, fp);
-    }
-    safefree((char*)tmpary);
-    return retval;
-}
-
-bool
-do_aexec(arg)
-register ARG *arg;
-{
-    STR **tmpary;      /* must not be register */
-    register STR **elem;
-    register char **a;
-    register int items;
-    char **argv;
-
-    (void)eval(arg[1].arg_ptr.arg_arg,&tmpary,-1);
-    items = (int)str_gnum(*tmpary);
-    if (items) {
-       argv = (char**)safemalloc((items+1)*sizeof(char*));
-       a = argv;
-       for (elem = tmpary+1; items > 0; items--,elem++) {
-           if (*elem)
-               *a++ = str_get(*elem);
-           else
-               *a++ = "";
-       }
-       *a = Nullch;
-       execvp(argv[0],argv);
-       safefree((char*)argv);
-    }
-    safefree((char*)tmpary);
-    return FALSE;
-}
-
-bool
-do_exec(str)
-STR *str;
-{
-    register char **a;
-    register char *s;
-    char **argv;
-    char *cmd = str_get(str);
-
-    /* see if there are shell metacharacters in it */
-
-    for (s = cmd; *s; s++) {
-       if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`",*s)) {
-           execl("/bin/sh","sh","-c",cmd,(char*)0);
-           return FALSE;
-       }
-    }
-    argv = (char**)safemalloc(((s - cmd) / 2 + 2)*sizeof(char*));
-
-    a = argv;
-    for (s = cmd; *s;) {
-       while (isspace(*s)) s++;
-       if (*s)
-           *(a++) = s;
-       while (*s && !isspace(*s)) s++;
-       if (*s)
-           *s++ = '\0';
-    }
-    *a = Nullch;
-    if (argv[0])
-       execvp(argv[0],argv);
-    safefree((char*)argv);
-    return FALSE;
-}
-
-STR *
-do_push(arg,ary)
-register ARG *arg;
-register ARRAY *ary;
-{
-    STR **tmpary;      /* must not be register */
-    register STR **elem;
-    register STR *str = &str_no;
-    register int items;
-
-    (void)eval(arg[1].arg_ptr.arg_arg,&tmpary,-1);
-    items = (int)str_gnum(*tmpary);
-    for (elem = tmpary+1; items > 0; items--,elem++) {
-       str = str_new(0);
-       if (*elem)
-           str_sset(str,*elem);
-       apush(ary,str);
-    }
-    safefree((char*)tmpary);
-    return str;
-}
-
-do_unshift(arg,ary)
-register ARG *arg;
-register ARRAY *ary;
-{
-    STR **tmpary;      /* must not be register */
-    register STR **elem;
-    register STR *str = &str_no;
-    register int i;
-    register int items;
-
-    (void)eval(arg[1].arg_ptr.arg_arg,&tmpary,-1);
-    items = (int)str_gnum(*tmpary);
-    aunshift(ary,items);
-    i = 0;
-    for (elem = tmpary+1; i < items; i++,elem++) {
-       str = str_new(0);
-       str_sset(str,*elem);
-       astore(ary,i,str);
-    }
-    safefree((char*)tmpary);
-}
-
-apply(type,arg,sarg)
-int type;
-register ARG *arg;
-STR **sarg;
-{
-    STR **tmpary;      /* must not be register */
-    register STR **elem;
-    register int items;
-    register int val;
-    register int val2;
-    char *s;
-
-    if (sarg) {
-       tmpary = sarg;
-       items = 0;
-       for (elem = tmpary+1; *elem; elem++)
-           items++;
-    }
-    else {
-       (void)eval(arg[1].arg_ptr.arg_arg,&tmpary,-1);
-       items = (int)str_gnum(*tmpary);
-    }
-    switch (type) {
-    case O_CHMOD:
-       if (--items > 0) {
-           val = (int)str_gnum(tmpary[1]);
-           for (elem = tmpary+2; *elem; elem++)
-               if (chmod(str_get(*elem),val))
-                   items--;
-       }
-       break;
-    case O_CHOWN:
-       if (items > 2) {
-           items -= 2;
-           val = (int)str_gnum(tmpary[1]);
-           val2 = (int)str_gnum(tmpary[2]);
-           for (elem = tmpary+3; *elem; elem++)
-               if (chown(str_get(*elem),val,val2))
-                   items--;
-       }
-       else
-           items = 0;
-       break;
-    case O_KILL:
-       if (--items > 0) {
-           val = (int)str_gnum(tmpary[1]);
-           if (val < 0) {
-               val = -val;
-               for (elem = tmpary+2; *elem; elem++)
-#ifdef KILLPG
-                   if (killpg((int)(str_gnum(*elem)),val))     /* BSD */
-#else
-                   if (kill(-(int)(str_gnum(*elem)),val))      /* SYSV */
-#endif
-                       items--;
-           }
-           else {
-               for (elem = tmpary+2; *elem; elem++)
-                   if (kill((int)(str_gnum(*elem)),val))
-                       items--;
-           }
-       }
-       break;
-    case O_UNLINK:
-       for (elem = tmpary+1; *elem; elem++) {
-           s = str_get(*elem);
-           if (euid || unsafe) {
-               if (UNLINK(s))
-                   items--;
-           }
-           else {      /* don't let root wipe out directories without -U */
-               if (stat(s,&statbuf) < 0 ||
-                 (statbuf.st_mode & S_IFMT) == S_IFDIR )
-                   items--;
-               else {
-                   if (UNLINK(s))
-                       items--;
-               }
-           }
-       }
-       break;
-    case O_UTIME:
-       if (items > 2) {
-           struct {
-               long    atime,
-                       mtime;
-           } utbuf;
-
-           utbuf.atime = (long)str_gnum(tmpary[1]);    /* time accessed */
-           utbuf.mtime = (long)str_gnum(tmpary[2]);    /* time modified */
-           items -= 2;
-           for (elem = tmpary+3; *elem; elem++)
-               if (utime(str_get(*elem),&utbuf))
-                   items--;
-       }
-       else
-           items = 0;
-       break;
-    }
-    if (!sarg)
-       safefree((char*)tmpary);
-    return items;
-}
-
-STR *
-do_subr(arg,sarg)
-register ARG *arg;
-register STR **sarg;
-{
-    register SUBR *sub;
-    ARRAY *savearray;
-    STR *str;
-    STAB *stab;
-    char *oldfile = filename;
-    int oldsave = savestack->ary_fill;
-    int oldtmps_base = tmps_base;
-
-    if (arg[2].arg_type == A_WORD)
-       stab = arg[2].arg_ptr.arg_stab;
-    else
-       stab = stabent(str_get(arg[2].arg_ptr.arg_stab->stab_val),TRUE);
-    if (!stab) {
-       if (dowarn)
-           warn("Undefined subroutine called");
-       return &str_no;
-    }
-    sub = stab->stab_sub;
-    if (!sub) {
-       if (dowarn)
-           warn("Undefined subroutine \"%s\" called", stab->stab_name);
-       return &str_no;
-    }
-    savearray = defstab->stab_array;
-    defstab->stab_array = anew(defstab);
-    if (arg[1].arg_flags & AF_SPECIAL)
-       (void)do_push(arg,defstab->stab_array);
-    else if (arg[1].arg_type != A_NULL) {
-       str = str_new(0);
-       str_sset(str,sarg[1]);
-       apush(defstab->stab_array,str);
-    }
-    sub->depth++;
-    if (sub->depth >= 2) {     /* save temporaries on recursion? */
-       if (sub->depth == 100 && dowarn)
-           warn("Deep recursion on subroutine \"%s\"",stab->stab_name);
-       savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
-    }
-    filename = sub->filename;
-    tmps_base = tmps_max;
-
-    str = cmd_exec(sub->cmd);          /* so do it already */
-
-    sub->depth--;      /* assuming no longjumps out of here */
-    afree(defstab->stab_array);  /* put back old $_[] */
-    defstab->stab_array = savearray;
-    filename = oldfile;
-    tmps_base = oldtmps_base;
-    if (savestack->ary_fill > oldsave) {
-       str = str_static(str);  /* in case restore wipes old str */
-       restorelist(oldsave);
-    }
-    return str;
-}
-
-void
-do_assign(retstr,arg,sarg)
-STR *retstr;
-register ARG *arg;
-register STR **sarg;
-{
-    STR **tmpary;      /* must not be register */
-    register ARG *larg = arg[1].arg_ptr.arg_arg;
-    register STR **elem;
-    register STR *str;
-    register ARRAY *ary;
-    register int i;
-    register int items;
-    STR *tmpstr;
-
-    if (arg[2].arg_flags & AF_SPECIAL) {
-       (void)eval(arg[2].arg_ptr.arg_arg,&tmpary,-1);
-       items = (int)str_gnum(*tmpary);
-    }
-    else {
-       tmpary = sarg;
-       sarg[1] = sarg[2];
-       sarg[2] = Nullstr;
-       items = 1;
-    }
-
-    if (arg->arg_flags & AF_COMMON) {  /* always true currently, alas */
-       if (*(tmpary+1)) {
-           for (i=2,elem=tmpary+2; i <= items; i++,elem++) {
-               *elem = str_static(*elem);
-           }
-       }
-    }
-    if (larg->arg_type == O_LIST) {
-       for (i=1,elem=tmpary+1; i <= larg->arg_len; i++) {
-           switch (larg[i].arg_type) {
-           case A_STAB:
-           case A_LVAL:
-               str = STAB_STR(larg[i].arg_ptr.arg_stab);
-               break;
-           case A_LEXPR:
-               str = eval(larg[i].arg_ptr.arg_arg,Null(STR***),-1);
-               break;
-           }
-           if (larg->arg_flags & AF_LOCAL) {
-               apush(savestack,str);   /* save pointer */
-               tmpstr = str_new(0);
-               str_sset(tmpstr,str);
-               apush(savestack,tmpstr); /* save value */
-           }
-           if (*elem)
-               str_sset(str,*(elem++));
-           else
-               str_set(str,"");
-           STABSET(str);
-       }
-    }
-    else {                     /* should be an array name */
-       ary = larg[1].arg_ptr.arg_stab->stab_array;
-       for (i=0,elem=tmpary+1; i < items; i++) {
-           str = str_new(0);
-           if (*elem)
-               str_sset(str,*(elem++));
-           astore(ary,i,str);
-       }
-       ary->ary_fill = items - 1;/* they can get the extra ones back by */
-    }                          /*   setting $#ary larger than old fill */
-    str_numset(retstr,(double)items);
-    STABSET(retstr);
-    if (tmpary != sarg);
-       safefree((char*)tmpary);
-}
-
-int
-do_kv(hash,kv,retary,sarg,ptrmaxsarg,sargoff,cushion)
-HASH *hash;
-int kv;
-STR ***retary;
-register STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    register ARRAY *ary;
-    int max = 0;
-    int i;
-    static ARRAY *myarray = Null(ARRAY*);
-    register HENT *entry;
-
-    ary = myarray;
-    if (!ary)
-       myarray = ary = anew(Nullstab);
-    ary->ary_fill = -1;
-
-    hiterinit(hash);
-    while (entry = hiternext(hash)) {
-       max++;
-       if (kv == O_KEYS)
-           apush(ary,str_make(hiterkey(entry)));
-       else
-           apush(ary,str_make(str_get(hiterval(entry))));
-    }
-    if (retary) { /* array wanted */
-       *ptrmaxsarg = max + sargoff;
-       sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-         (max+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-       for (i = 1; i <= max; i++)
-           sarg[i] = afetch(ary,i-1);
-       *retary = sarg;
-    }
-    return max;
-}
-
-STR *
-do_each(hash,retary,sarg,ptrmaxsarg,sargoff,cushion)
-HASH *hash;
-STR ***retary;
-STR **sarg;
-int *ptrmaxsarg;
-int sargoff;
-int cushion;
-{
-    static STR *mystr = Nullstr;
-    STR *retstr;
-    HENT *entry = hiternext(hash);
-
-    if (mystr) {
-       str_free(mystr);
-       mystr = Nullstr;
-    }
-
-    if (retary) { /* array wanted */
-       if (entry) {
-           *ptrmaxsarg = 2 + sargoff;
-           sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-             (2+2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-           sarg[1] = mystr = str_make(hiterkey(entry));
-           retstr = sarg[2] = hiterval(entry);
-           *retary = sarg;
-       }
-       else {
-           *ptrmaxsarg = sargoff;
-           sarg = (STR**)saferealloc((char*)(sarg - sargoff),
-             (2+cushion+sargoff)*sizeof(STR*)) + sargoff;
-           retstr = Nullstr;
-           *retary = sarg;
-       }
-    }
-    else
-       retstr = hiterval(entry);
-       
-    return retstr;
-}
-
-int
-mystat(arg,str)
-ARG *arg;
-STR *str;
-{
-    STIO *stio;
-
-    if (arg[1].arg_flags & AF_SPECIAL) {
-       stio = arg[1].arg_ptr.arg_stab->stab_io;
-       if (stio && stio->fp)
-           return fstat(fileno(stio->fp), &statbuf);
-       else {
-           if (dowarn)
-               warn("Stat on unopened file <%s>",
-                 arg[1].arg_ptr.arg_stab->stab_name);
-           return -1;
-       }
-    }
-    else
-       return stat(str_get(str),&statbuf);
-}
-
-STR *
-do_fttext(arg,str)
-register ARG *arg;
-STR *str;
-{
-    int i;
-    int len;
-    int odd = 0;
-    STDCHAR tbuf[512];
-    register STDCHAR *s;
-    register STIO *stio;
-
-    if (arg[1].arg_flags & AF_SPECIAL) {
-       stio = arg[1].arg_ptr.arg_stab->stab_io;
-       if (stio && stio->fp) {
-#ifdef STDSTDIO
-           if (stio->fp->_cnt <= 0) {
-               i = getc(stio->fp);
-               ungetc(i,stio->fp);
-           }
-           if (stio->fp->_cnt <= 0)    /* null file is anything */
-               return &str_yes;
-           len = stio->fp->_cnt + (stio->fp->_ptr - stio->fp->_base);
-           s = stio->fp->_base;
-#else
-           fatal("-T and -B not implemented on filehandles\n");
-#endif
-       }
-       else {
-           if (dowarn)
-               warn("Test on unopened file <%s>",
-                 arg[1].arg_ptr.arg_stab->stab_name);
-           return &str_no;
-       }
-    }
-    else {
-       i = open(str_get(str),0);
-       if (i < 0)
-           return &str_no;
-       len = read(i,tbuf,512);
-       if (len <= 0)           /* null file is anything */
-           return &str_yes;
-       close(i);
-       s = tbuf;
-    }
-
-    /* now scan s to look for textiness */
-
-    for (i = 0; i < len; i++,s++) {
-       if (!*s) {                      /* null never allowed in text */
-           odd += len;
-           break;
-       }
-       else if (*s & 128)
-           odd++;
-       else if (*s < 32 &&
-         *s != '\n' && *s != '\r' && *s != '\b' &&
-         *s != '\t' && *s != '\f' && *s != 27)
-           odd++;
-    }
-
-    if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
-       return &str_no;
-    else
-       return &str_yes;
-}
-
-int
-do_study(str)
-STR *str;
-{
-    register char *s = str_get(str);
-    register int pos = str->str_cur;
-    register int ch;
-    register int *sfirst;
-    register int *snext;
-    static int maxscream = -1;
-    static STR *lastscream = Nullstr;
-
-    if (lastscream && lastscream->str_pok == 5)
-       lastscream->str_pok &= ~4;
-    lastscream = str;
-    if (pos <= 0)
-       return 0;
-    if (pos > maxscream) {
-       if (maxscream < 0) {
-           maxscream = pos + 80;
-           screamfirst = (int*)safemalloc((MEM_SIZE)(256 * sizeof(int)));
-           screamnext = (int*)safemalloc((MEM_SIZE)(maxscream * sizeof(int)));
-       }
-       else {
-           maxscream = pos + pos / 4;
-           screamnext = (int*)saferealloc((char*)screamnext,
-               (MEM_SIZE)(maxscream * sizeof(int)));
-       }
-    }
-
-    sfirst = screamfirst;
-    snext = screamnext;
-
-    if (!sfirst || !snext)
-       fatal("do_study: out of memory");
-
-    for (ch = 256; ch; --ch)
-       *sfirst++ = -1;
-    sfirst -= 256;
-
-    while (--pos >= 0) {
-       ch = s[pos];
-       if (sfirst[ch] >= 0)
-           snext[pos] = sfirst[ch] - pos;
-       else
-           snext[pos] = -pos;
-       sfirst[ch] = pos;
-    }
-
-    str->str_pok |= 4;
-    return 1;
-}
-
-init_eval()
-{
-#define A(e1,e2,e3) (e1+(e2<<1)+(e3<<2))
-    opargs[O_ITEM] =           A(1,0,0);
-    opargs[O_ITEM2] =          A(0,0,0);
-    opargs[O_ITEM3] =          A(0,0,0);
-    opargs[O_CONCAT] =         A(1,1,0);
-    opargs[O_MATCH] =          A(1,0,0);
-    opargs[O_NMATCH] =         A(1,0,0);
-    opargs[O_SUBST] =          A(1,0,0);
-    opargs[O_NSUBST] =         A(1,0,0);
-    opargs[O_ASSIGN] =         A(1,1,0);
-    opargs[O_MULTIPLY] =       A(1,1,0);
-    opargs[O_DIVIDE] =         A(1,1,0);
-    opargs[O_MODULO] =         A(1,1,0);
-    opargs[O_ADD] =            A(1,1,0);
-    opargs[O_SUBTRACT] =       A(1,1,0);
-    opargs[O_LEFT_SHIFT] =     A(1,1,0);
-    opargs[O_RIGHT_SHIFT] =    A(1,1,0);
-    opargs[O_LT] =             A(1,1,0);
-    opargs[O_GT] =             A(1,1,0);
-    opargs[O_LE] =             A(1,1,0);
-    opargs[O_GE] =             A(1,1,0);
-    opargs[O_EQ] =             A(1,1,0);
-    opargs[O_NE] =             A(1,1,0);
-    opargs[O_BIT_AND] =                A(1,1,0);
-    opargs[O_XOR] =            A(1,1,0);
-    opargs[O_BIT_OR] =         A(1,1,0);
-    opargs[O_AND] =            A(1,0,0);       /* don't eval arg 2 (yet) */
-    opargs[O_OR] =             A(1,0,0);       /* don't eval arg 2 (yet) */
-    opargs[O_COND_EXPR] =      A(1,0,0);       /* don't eval args 2 or 3 */
-    opargs[O_COMMA] =          A(1,1,0);
-    opargs[O_NEGATE] =         A(1,0,0);
-    opargs[O_NOT] =            A(1,0,0);
-    opargs[O_COMPLEMENT] =     A(1,0,0);
-    opargs[O_WRITE] =          A(1,0,0);
-    opargs[O_OPEN] =           A(1,1,0);
-    opargs[O_TRANS] =          A(1,0,0);
-    opargs[O_NTRANS] =         A(1,0,0);
-    opargs[O_CLOSE] =          A(0,0,0);
-    opargs[O_ARRAY] =          A(1,0,0);
-    opargs[O_HASH] =           A(1,0,0);
-    opargs[O_LARRAY] =         A(1,0,0);
-    opargs[O_LHASH] =          A(1,0,0);
-    opargs[O_PUSH] =           A(1,0,0);
-    opargs[O_POP] =            A(0,0,0);
-    opargs[O_SHIFT] =          A(0,0,0);
-    opargs[O_SPLIT] =          A(1,0,0);
-    opargs[O_LENGTH] =         A(1,0,0);
-    opargs[O_SPRINTF] =                A(1,0,0);
-    opargs[O_SUBSTR] =         A(1,1,1);
-    opargs[O_JOIN] =           A(1,0,0);
-    opargs[O_SLT] =            A(1,1,0);
-    opargs[O_SGT] =            A(1,1,0);
-    opargs[O_SLE] =            A(1,1,0);
-    opargs[O_SGE] =            A(1,1,0);
-    opargs[O_SEQ] =            A(1,1,0);
-    opargs[O_SNE] =            A(1,1,0);
-    opargs[O_SUBR] =           A(1,0,0);
-    opargs[O_PRINT] =          A(1,1,0);
-    opargs[O_CHDIR] =          A(1,0,0);
-    opargs[O_DIE] =            A(1,0,0);
-    opargs[O_EXIT] =           A(1,0,0);
-    opargs[O_RESET] =          A(1,0,0);
-    opargs[O_LIST] =           A(0,0,0);
-    opargs[O_EOF] =            A(1,0,0);
-    opargs[O_TELL] =           A(1,0,0);
-    opargs[O_SEEK] =           A(1,1,1);
-    opargs[O_LAST] =           A(1,0,0);
-    opargs[O_NEXT] =           A(1,0,0);
-    opargs[O_REDO] =           A(1,0,0);
-    opargs[O_GOTO] =           A(1,0,0);
-    opargs[O_INDEX] =          A(1,1,0);
-    opargs[O_TIME] =           A(0,0,0);
-    opargs[O_TMS] =            A(0,0,0);
-    opargs[O_LOCALTIME] =      A(1,0,0);
-    opargs[O_GMTIME] =         A(1,0,0);
-    opargs[O_STAT] =           A(1,0,0);
-    opargs[O_CRYPT] =          A(1,1,0);
-    opargs[O_EXP] =            A(1,0,0);
-    opargs[O_LOG] =            A(1,0,0);
-    opargs[O_SQRT] =           A(1,0,0);
-    opargs[O_INT] =            A(1,0,0);
-    opargs[O_PRTF] =           A(1,1,0);
-    opargs[O_ORD] =            A(1,0,0);
-    opargs[O_SLEEP] =          A(1,0,0);
-    opargs[O_FLIP] =           A(1,0,0);
-    opargs[O_FLOP] =           A(0,1,0);
-    opargs[O_KEYS] =           A(0,0,0);
-    opargs[O_VALUES] =         A(0,0,0);
-    opargs[O_EACH] =           A(0,0,0);
-    opargs[O_CHOP] =           A(1,0,0);
-    opargs[O_FORK] =           A(1,0,0);
-    opargs[O_EXEC] =           A(1,0,0);
-    opargs[O_SYSTEM] =         A(1,0,0);
-    opargs[O_OCT] =            A(1,0,0);
-    opargs[O_HEX] =            A(1,0,0);
-    opargs[O_CHMOD] =          A(1,0,0);
-    opargs[O_CHOWN] =          A(1,0,0);
-    opargs[O_KILL] =           A(1,0,0);
-    opargs[O_RENAME] =         A(1,1,0);
-    opargs[O_UNLINK] =         A(1,0,0);
-    opargs[O_UMASK] =          A(1,0,0);
-    opargs[O_UNSHIFT] =                A(1,0,0);
-    opargs[O_LINK] =           A(1,1,0);
-    opargs[O_REPEAT] =         A(1,1,0);
-    opargs[O_EVAL] =           A(1,0,0);
-    opargs[O_FTEREAD] =                A(1,0,0);
-    opargs[O_FTEWRITE] =       A(1,0,0);
-    opargs[O_FTEEXEC] =                A(1,0,0);
-    opargs[O_FTEOWNED] =       A(1,0,0);
-    opargs[O_FTRREAD] =                A(1,0,0);
-    opargs[O_FTRWRITE] =       A(1,0,0);
-    opargs[O_FTREXEC] =                A(1,0,0);
-    opargs[O_FTROWNED] =       A(1,0,0);
-    opargs[O_FTIS] =           A(1,0,0);
-    opargs[O_FTZERO] =         A(1,0,0);
-    opargs[O_FTSIZE] =         A(1,0,0);
-    opargs[O_FTFILE] =         A(1,0,0);
-    opargs[O_FTDIR] =          A(1,0,0);
-    opargs[O_FTLINK] =         A(1,0,0);
-    opargs[O_SYMLINK] =                A(1,1,0);
-    opargs[O_FTPIPE] =         A(1,0,0);
-    opargs[O_FTSUID] =         A(1,0,0);
-    opargs[O_FTSGID] =         A(1,0,0);
-    opargs[O_FTSVTX] =         A(1,0,0);
-    opargs[O_FTCHR] =          A(1,0,0);
-    opargs[O_FTBLK] =          A(1,0,0);
-    opargs[O_FTSOCK] =         A(1,0,0);
-    opargs[O_FTTTY] =          A(1,0,0);
-    opargs[O_DOFILE] =         A(1,0,0);
-    opargs[O_FTTEXT] =         A(1,0,0);
-    opargs[O_FTBINARY] =       A(1,0,0);
-    opargs[O_UTIME] =          A(1,0,0);
-    opargs[O_WAIT] =           A(0,0,0);
-    opargs[O_SORT] =           A(1,0,0);
-    opargs[O_STUDY] =          A(1,0,0);
-    opargs[O_DELETE] =         A(1,0,0);
-}
diff --git a/arg.h b/arg.h
index efb3e36..ae52789 100644 (file)
--- a/arg.h
+++ b/arg.h
@@ -1,8 +1,13 @@
-/* $Header: arg.h,v 2.0 88/06/05 00:08:14 root Exp $
+/* $Header: arg.h,v 3.0 89/10/18 15:08:27 lwall Locked $
+ *
+ *    Copyright (c) 1989, Larry Wall
+ *
+ *    You may distribute under the terms of the GNU General Public License
+ *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       arg.h,v $
- * Revision 2.0  88/06/05  00:08:14  root
- * Baseline version 2.0.
+ * Revision 3.0  89/10/18  15:08:27  lwall
+ * 3.0 baseline
  * 
  */
 
 #define O_SORT 134
 #define O_DELETE 135
 #define O_STUDY 136
-#define MAXO 137
+#define O_ATAN2 137
+#define O_SIN 138
+#define O_COS 139
+#define O_RAND 140
+#define O_SRAND 141
+#define O_POW 142
+#define O_RETURN 143
+#define O_GETC 144
+#define O_MKDIR 145
+#define O_RMDIR 146
+#define O_GETPPID 147
+#define O_GETPGRP 148
+#define O_SETPGRP 149
+#define O_GETPRIORITY 150
+#define O_SETPRIORITY 151
+#define O_CHROOT 152
+#define O_IOCTL 153
+#define O_FCNTL 154
+#define O_FLOCK 155
+#define O_RINDEX 156
+#define O_PACK 157
+#define O_UNPACK 158
+#define O_READ 159
+#define O_WARN 160
+#define O_DBMOPEN 161
+#define O_DBMCLOSE 162
+#define O_ASLICE 163
+#define O_HSLICE 164
+#define O_LASLICE 165
+#define O_LHSLICE 166
+#define O_F_OR_R 167
+#define O_RANGE 168
+#define O_RCAT 169
+#define O_AASSIGN 170
+#define O_SASSIGN 171
+#define O_DUMP 172
+#define O_REVERSE 173
+#define O_ADDROF 174
+#define O_SOCKET 175
+#define O_BIND 176
+#define O_CONNECT 177
+#define O_LISTEN 178
+#define O_ACCEPT 179
+#define O_SEND 180
+#define O_RECV 181
+#define O_SSELECT 182
+#define O_SOCKETPAIR 183
+#define O_DBSUBR 184
+#define O_DEFINED 185
+#define O_UNDEF 186
+#define O_READLINK 187
+#define O_LSTAT 188
+#define O_AELEM 189
+#define O_HELEM 190
+#define O_LAELEM 191
+#define O_LHELEM 192
+#define O_LOCAL 193
+#define O_UNUSED 194
+#define O_FILENO 195
+#define O_GHBYNAME 196
+#define O_GHBYADDR 197
+#define O_GHOSTENT 198
+#define O_SHOSTENT 199
+#define O_EHOSTENT 200
+#define O_GSBYNAME 201
+#define O_GSBYPORT 202
+#define O_GSERVENT 203
+#define O_SSERVENT 204
+#define O_ESERVENT 205
+#define O_GPBYNAME 206
+#define O_GPBYNUMBER 207
+#define O_GPROTOENT 208
+#define O_SPROTOENT 209
+#define O_EPROTOENT 210
+#define O_GNBYNAME 211
+#define O_GNBYADDR 212
+#define O_GNETENT 213
+#define O_SNETENT 214
+#define O_ENETENT 215
+#define O_VEC 216
+#define O_GREP 217
+#define O_GPWNAM 218
+#define O_GPWUID 219
+#define O_GPWENT 220
+#define O_SPWENT 221
+#define O_EPWENT 222
+#define O_GGRNAM 223
+#define O_GGRGID 224
+#define O_GGRENT 225
+#define O_SGRENT 226
+#define O_EGRENT 227
+#define O_SHUTDOWN 228
+#define O_OPENDIR 229
+#define O_READDIR 230
+#define O_TELLDIR 231
+#define O_SEEKDIR 232
+#define O_REWINDDIR 233
+#define O_CLOSEDIR 234
+#define O_GETLOGIN 235
+#define O_SYSCALL 236
+#define O_GSOCKOPT 237
+#define O_SSOCKOPT 238
+#define O_GETSOCKNAME 239
+#define O_GETPEERNAME 240
+#define MAXO 241
 
 #ifndef DOINIT
 extern char *opname[];
@@ -286,7 +395,111 @@ char *opname[] = {
     "SORT",
     "DELETE",
     "STUDY",
-    "135"
+    "ATAN2",
+    "SIN",
+    "COS",
+    "RAND",
+    "SRAND",
+    "POW",
+    "RETURN",
+    "GETC",
+    "MKDIR",
+    "RMDIR",
+    "GETPPID",
+    "GETPGRP",
+    "SETPGRP",
+    "GETPRIORITY",
+    "SETPRIORITY",
+    "CHROOT",
+    "IOCTL",
+    "FCNTL",
+    "FLOCK",
+    "RINDEX",
+    "PACK",
+    "UNPACK",
+    "READ",
+    "WARN",
+    "DBMOPEN",
+    "DBMCLOSE",
+    "ASLICE",
+    "HSLICE",
+    "LASLICE",
+    "LHSLICE",
+    "FLIP_OR_RANGE",
+    "RANGE",
+    "RCAT",
+    "AASSIGN",
+    "SASSIGN",
+    "DUMP",
+    "REVERSE",
+    "ADDRESS_OF",
+    "SOCKET",
+    "BIND",
+    "CONNECT",
+    "LISTEN",
+    "ACCEPT",
+    "SEND",
+    "RECV",
+    "SSELECT",
+    "SOCKETPAIR",
+    "DBSUBR",
+    "DEFINED",
+    "UNDEF",
+    "READLINK",
+    "LSTAT",
+    "AELEM",
+    "HELEM",
+    "LAELEM",
+    "LHELEM",
+    "LOCAL",
+    "UNUSED",
+    "FILENO",
+    "GHBYNAME",
+    "GHBYADDR",
+    "GHOSTENT",
+    "SHOSTENT",
+    "EHOSTENT",
+    "GSBYNAME",
+    "GSBYPORT",
+    "GSERVENT",
+    "SSERVENT",
+    "ESERVENT",
+    "GPBYNAME",
+    "GPBYNUMBER",
+    "GPROTOENT",
+    "SPROTOENT",
+    "EPROTOENT",
+    "GNBYNAME",
+    "GNBYADDR",
+    "GNETENT",
+    "SNETENT",
+    "ENETENT",
+    "VEC",
+    "GREP",
+    "GPWNAM",
+    "GPWUID",
+    "GPWENT",
+    "SPWENT",
+    "EPWENT",
+    "GGRNAM",
+    "GGRGID",
+    "GGRENT",
+    "SGRENT",
+    "EGRENT",
+    "SHUTDOWN",
+    "OPENDIR",
+    "READDIR",
+    "TELLDIR",
+    "SEEKDIR",
+    "REWINDDIR",
+    "CLOSEDIR",
+    "GETLOGIN",
+    "SYSCALL",
+    "GSOCKOPT",
+    "SSOCKOPT",
+    "GETSOCKNAME",
+    "GETPEERNAME",
+    "241"
 };
 #endif
 
@@ -302,11 +515,18 @@ char *opname[] = {
 #define A_SPAT 9
 #define A_LEXPR 10
 #define A_ARYLEN 11
-#define A_NUMBER 12
+#define A_ARYSTAB 12
 #define A_LARYLEN 13
 #define A_GLOB 14
 #define A_WORD 15
 #define A_INDREAD 16
+#define A_LARYSTAB 17
+#define A_STAR 18
+#define A_LSTAR 19
+#define A_WANTARRAY 20
+
+#define A_MASK 31
+#define A_DONT 32              /* or this into type to suppress evaluation */
 
 #ifndef DOINIT
 extern char *argname[];
@@ -324,19 +544,46 @@ char *argname[] = {
     "SPAT",
     "LEXPR",
     "ARYLEN",
-    "NUMBER",
+    "ARYSTAB",
     "LARYLEN",
     "GLOB",
     "WORD",
     "INDREAD",
-    "17"
+    "LARYSTAB",
+    "STAR",
+    "LSTAR",
+    "WANTARRAY",
+    "21"
 };
 #endif
 
 #ifndef DOINIT
 extern bool hoistable[];
 #else
-bool hoistable[] = {0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0};
+bool hoistable[] =
+  {0,  /* A_NULL */
+   0,  /* EXPR */
+   1,  /* CMD */
+   1,  /* STAB */
+   0,  /* LVAL */
+   1,  /* SINGLE */
+   0,  /* DOUBLE */
+   0,  /* BACKTICK */
+   0,  /* READ */
+   0,  /* SPAT */
+   0,  /* LEXPR */
+   1,  /* ARYLEN */
+   1,  /* ARYSTAB */
+   0,  /* LARYLEN */
+   0,  /* GLOB */
+   1,  /* WORD */
+   0,  /* INDREAD */
+   0,  /* LARYSTAB */
+   1,  /* STAR */
+   1,  /* LSTAR */
+   1,  /* WANTARRAY */
+   0,  /* 21 */
+};
 #endif
 
 union argptr {
@@ -346,22 +593,25 @@ union argptr {
     SPAT       *arg_spat;
     CMD                *arg_cmd;
     STR                *arg_str;
-    double     arg_nval;
+    HASH       *arg_hash;
 };
 
 struct arg {
     union argptr arg_ptr;
     short      arg_len;
+#ifdef mips
+    short      pad;
+#endif
     unsigned char arg_type;
     unsigned char arg_flags;
 };
 
-#define AF_SPECIAL 1           /* op wants to evaluate this arg itself */
+#define AF_ARYOK 1             /* op can handle multiple values here */
 #define AF_POST 2              /* post *crement this item */
 #define AF_PRE 4               /* pre *crement this item */
 #define AF_UP 8                        /* increment rather than decrement */
 #define AF_COMMON 16           /* left and right have symbols in common */
-#define AF_NUMERIC 32          /* return as numeric rather than string */
+#define AF_UNUSED 32           /*  */
 #define AF_LISTISH 64          /* turn into list if important */
 #define AF_LOCAL 128           /* list of local variables */
 
@@ -371,13 +621,262 @@ struct arg {
  * use on the list of arguments following.  The arg_len in the 0th element
  * gives the maximum argument number, and the arg_str is used to store
  * the return value in a more-or-less static location.  Sorry it's not
- * re-entrant, but it sure makes it efficient.  The arg_type of the
+ * re-entrant (yet), but it sure makes it efficient.  The arg_type of the
  * 0th element is an operator (O_*) rather than an argument type (A_*).
  */
 
 #define Nullarg Null(ARG*)
 
-EXT char opargs[MAXO];
+#ifndef DOINIT
+EXT char opargs[MAXO+1];
+#else
+#define A(e1,e2,e3) (e1+(e2<<2)+(e3<<4))
+char opargs[MAXO+1] = {
+       A(0,0,0),       /* NULL */
+       A(1,0,0),       /* ITEM */
+       A(0,0,0),       /* ITEM2 */
+       A(0,0,0),       /* ITEM3 */
+       A(1,1,0),       /* CONCAT */
+       A(1,0,0),       /* MATCH */
+       A(1,0,0),       /* NMATCH */
+       A(1,0,0),       /* SUBST */
+       A(1,0,0),       /* NSUBST */
+       A(1,1,0),       /* ASSIGN */
+       A(1,1,0),       /* MULTIPLY */
+       A(1,1,0),       /* DIVIDE */
+       A(1,1,0),       /* MODULO */
+       A(1,1,0),       /* ADD */
+       A(1,1,0),       /* SUBTRACT */
+       A(1,1,0),       /* LEFT_SHIFT */
+       A(1,1,0),       /* RIGHT_SHIFT */
+       A(1,1,0),       /* LT */
+       A(1,1,0),       /* GT */
+       A(1,1,0),       /* LE */
+       A(1,1,0),       /* GE */
+       A(1,1,0),       /* EQ */
+       A(1,1,0),       /* NE */
+       A(1,1,0),       /* BIT_AND */
+       A(1,1,0),       /* XOR */
+       A(1,1,0),       /* BIT_OR */
+       A(1,0,0),       /* AND */
+       A(1,0,0),       /* OR */
+       A(1,0,0),       /* COND_EXPR */
+       A(1,1,0),       /* COMMA */
+       A(1,0,0),       /* NEGATE */
+       A(1,0,0),       /* NOT */
+       A(1,0,0),       /* COMPLEMENT */
+       A(1,0,0),       /* WRITE */
+       A(1,1,0),       /* OPEN */
+       A(1,0,0),       /* TRANS */
+       A(1,0,0),       /* NTRANS */
+       A(1,0,0),       /* CLOSE */
+       A(0,0,0),       /* ARRAY */
+       A(0,0,0),       /* HASH */
+       A(0,0,0),       /* LARRAY */
+       A(0,0,0),       /* LHASH */
+       A(0,3,0),       /* PUSH */
+       A(0,0,0),       /* POP */
+       A(0,0,0),       /* SHIFT */
+       A(1,0,1),       /* SPLIT */
+       A(1,0,0),       /* LENGTH */
+       A(3,0,0),       /* SPRINTF */
+       A(1,1,1),       /* SUBSTR */
+       A(1,3,0),       /* JOIN */
+       A(1,1,0),       /* SLT */
+       A(1,1,0),       /* SGT */
+       A(1,1,0),       /* SLE */
+       A(1,1,0),       /* SGE */
+       A(1,1,0),       /* SEQ */
+       A(1,1,0),       /* SNE */
+       A(0,3,0),       /* SUBR */
+       A(1,3,0),       /* PRINT */
+       A(1,0,0),       /* CHDIR */
+       A(0,3,0),       /* DIE */
+       A(1,0,0),       /* EXIT */
+       A(1,0,0),       /* RESET */
+       A(3,0,0),       /* LIST */
+       A(1,0,0),       /* SELECT */
+       A(1,0,0),       /* EOF */
+       A(1,0,0),       /* TELL */
+       A(1,1,1),       /* SEEK */
+       A(0,0,0),       /* LAST */
+       A(0,0,0),       /* NEXT */
+       A(0,0,0),       /* REDO */
+       A(0,0,0),       /* GOTO */
+       A(1,1,0),       /* INDEX */
+       A(0,0,0),       /* TIME */
+       A(0,0,0),       /* TIMES */
+       A(1,0,0),       /* LOCALTIME */
+       A(1,0,0),       /* GMTIME */
+       A(1,0,0),       /* STAT */
+       A(1,1,0),       /* CRYPT */
+       A(1,0,0),       /* EXP */
+       A(1,0,0),       /* LOG */
+       A(1,0,0),       /* SQRT */
+       A(1,0,0),       /* INT */
+       A(1,3,0),       /* PRINTF */
+       A(1,0,0),       /* ORD */
+       A(1,0,0),       /* SLEEP */
+       A(1,0,0),       /* FLIP */
+       A(0,1,0),       /* FLOP */
+       A(0,0,0),       /* KEYS */
+       A(0,0,0),       /* VALUES */
+       A(0,0,0),       /* EACH */
+       A(3,0,0),       /* CHOP */
+       A(0,0,0),       /* FORK */
+       A(1,3,0),       /* EXEC */
+       A(1,3,0),       /* SYSTEM */
+       A(1,0,0),       /* OCT */
+       A(1,0,0),       /* HEX */
+       A(0,3,0),       /* CHMOD */
+       A(0,3,0),       /* CHOWN */
+       A(0,3,0),       /* KILL */
+       A(1,1,0),       /* RENAME */
+       A(0,3,0),       /* UNLINK */
+       A(1,0,0),       /* UMASK */
+       A(0,3,0),       /* UNSHIFT */
+       A(1,1,0),       /* LINK */
+       A(1,1,0),       /* REPEAT */
+       A(1,0,0),       /* EVAL */
+       A(1,0,0),       /* FTEREAD */
+       A(1,0,0),       /* FTEWRITE */
+       A(1,0,0),       /* FTEEXEC */
+       A(1,0,0),       /* FTEOWNED */
+       A(1,0,0),       /* FTRREAD */
+       A(1,0,0),       /* FTRWRITE */
+       A(1,0,0),       /* FTREXEC */
+       A(1,0,0),       /* FTROWNED */
+       A(1,0,0),       /* FTIS */
+       A(1,0,0),       /* FTZERO */
+       A(1,0,0),       /* FTSIZE */
+       A(1,0,0),       /* FTFILE */
+       A(1,0,0),       /* FTDIR */
+       A(1,0,0),       /* FTLINK */
+       A(1,1,0),       /* SYMLINK */
+       A(1,0,0),       /* FTPIPE */
+       A(1,0,0),       /* FTSOCK */
+       A(1,0,0),       /* FTBLK */
+       A(1,0,0),       /* FTCHR */
+       A(1,0,0),       /* FTSUID */
+       A(1,0,0),       /* FTSGID */
+       A(1,0,0),       /* FTSVTX */
+       A(1,0,0),       /* FTTTY */
+       A(1,0,0),       /* DOFILE */
+       A(1,0,0),       /* FTTEXT */
+       A(1,0,0),       /* FTBINARY */
+       A(0,3,0),       /* UTIME */
+       A(0,0,0),       /* WAIT */
+       A(1,3,0),       /* SORT */
+       A(0,1,0),       /* DELETE */
+       A(1,0,0),       /* STUDY */
+       A(1,1,0),       /* ATAN2 */
+       A(1,0,0),       /* SIN */
+       A(1,0,0),       /* COS */
+       A(1,0,0),       /* RAND */
+       A(1,0,0),       /* SRAND */
+       A(1,1,0),       /* POW */
+       A(0,3,0),       /* RETURN */
+       A(1,0,0),       /* GETC */
+       A(1,1,0),       /* MKDIR */
+       A(1,0,0),       /* RMDIR */
+       A(0,0,0),       /* GETPPID */
+       A(1,0,0),       /* GETPGRP */
+       A(1,1,0),       /* SETPGRP */
+       A(1,1,0),       /* GETPRIORITY */
+       A(1,1,1),       /* SETPRIORITY */
+       A(1,0,0),       /* CHROOT */
+       A(1,1,1),       /* IOCTL */
+       A(1,1,1),       /* FCNTL */
+       A(1,1,0),       /* FLOCK */
+       A(1,1,0),       /* RINDEX */
+       A(1,3,0),       /* PACK */
+       A(1,1,0),       /* UNPACK */
+       A(1,1,1),       /* READ */
+       A(0,3,0),       /* WARN */
+       A(1,1,1),       /* DBMOPEN */
+       A(1,0,0),       /* DBMCLOSE */
+       A(0,3,0),       /* ASLICE */
+       A(0,3,0),       /* HSLICE */
+       A(0,3,0),       /* LASLICE */
+       A(0,3,0),       /* LHSLICE */
+       A(1,0,0),       /* F_OR_R */
+       A(1,1,0),       /* RANGE */
+       A(1,1,0),       /* RCAT */
+       A(3,3,0),       /* AASSIGN */
+       A(0,0,0),       /* SASSIGN */
+       A(0,0,0),       /* DUMP */
+       A(0,0,0),       /* REVERSE */
+       A(1,0,0),       /* ADDROF */
+       A(1,1,1),       /* SOCKET */
+       A(1,1,0),       /* BIND */
+       A(1,1,0),       /* CONNECT */
+       A(1,1,0),       /* LISTEN */
+       A(1,1,0),       /* ACCEPT */
+       A(1,1,2),       /* SEND */
+       A(1,1,1),       /* RECV */
+       A(1,1,1),       /* SSELECT */
+       A(1,1,1),       /* SOCKETPAIR */
+       A(0,3,0),       /* DBSUBR */
+       A(1,0,0),       /* DEFINED */
+       A(1,0,0),       /* UNDEF */
+       A(1,0,0),       /* READLINK */
+       A(1,0,0),       /* LSTAT */
+       A(0,1,0),       /* AELEM */
+       A(0,1,0),       /* HELEM */
+       A(0,1,0),       /* LAELEM */
+       A(0,1,0),       /* LHELEM */
+       A(1,0,0),       /* LOCAL */
+       A(0,0,0),       /* UNUSED */
+       A(1,0,0),       /* FILENO */
+       A(1,0,0),       /* GHBYNAME */
+       A(1,1,0),       /* GHBYADDR */
+       A(0,0,0),       /* GHOSTENT */
+       A(1,0,0),       /* SHOSTENT */
+       A(0,0,0),       /* EHOSTENT */
+       A(1,1,0),       /* GSBYNAME */
+       A(1,1,0),       /* GSBYPORT */
+       A(0,0,0),       /* GSERVENT */
+       A(1,0,0),       /* SSERVENT */
+       A(0,0,0),       /* ESERVENT */
+       A(1,0,0),       /* GPBYNAME */
+       A(1,0,0),       /* GPBYNUMBER */
+       A(0,0,0),       /* GPROTOENT */
+       A(1,0,0),       /* SPROTOENT */
+       A(0,0,0),       /* EPROTOENT */
+       A(1,0,0),       /* GNBYNAME */
+       A(1,1,0),       /* GNBYADDR */
+       A(0,0,0),       /* GNETENT */
+       A(1,0,0),       /* SNETENT */
+       A(0,0,0),       /* ENETENT */
+       A(1,1,1),       /* VEC */
+       A(0,3,0),       /* GREP */
+       A(1,0,0),       /* GPWNAM */
+       A(1,0,0),       /* GPWUID */
+       A(0,0,0),       /* GPWENT */
+       A(0,0,0),       /* SPWENT */
+       A(0,0,0),       /* EPWENT */
+       A(1,0,0),       /* GGRNAM */
+       A(1,0,0),       /* GGRGID */
+       A(0,0,0),       /* GGRENT */
+       A(0,0,0),       /* SGRENT */
+       A(0,0,0),       /* EGRENT */
+       A(1,1,0),       /* SHUTDOWN */
+       A(1,1,0),       /* OPENDIR */
+       A(1,0,0),       /* READDIR */
+       A(1,0,0),       /* TELLDIR */
+       A(1,1,0),       /* SEEKDIR */
+       A(1,0,0),       /* REWINDDIR */
+       A(1,0,0),       /* CLOSEDIR */
+       A(0,0,0),       /* GETLOGIN */
+       A(1,3,0),       /* SYSCALL */
+       A(1,1,1),       /* GSOCKOPT */
+       A(1,1,1),       /* SSOCKOPT */
+       A(1,0,0),       /* GETSOCKNAME */
+       A(1,0,0),       /* GETPEERNAME */
+       0
+};
+#undef A
+#endif
 
 int do_trans();
 int do_split();
@@ -390,3 +889,4 @@ int do_stat();
 STR *do_push();
 FILE *nextargv();
 STR *do_fttext();
+int do_slice();
diff --git a/array.c b/array.c
index f1446a7..6875d28 100644 (file)
--- a/array.c
+++ b/array.c
@@ -1,8 +1,13 @@
-/* $Header: array.c,v 2.0 88/06/05 00:08:17 root Exp $
+/* $Header: array.c,v 3.0 89/10/18 15:08:33 lwall Locked $
+ *
+ *    Copyright (c) 1989, Larry Wall
+ *
+ *    You may distribute under the terms of the GNU General Public License
+ *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       array.c,v $
- * Revision 2.0  88/06/05  00:08:17  root
- * Baseline version 2.0.
+ * Revision 3.0  89/10/18  15:08:33  lwall
+ * 3.0 baseline
  * 
  */
 
 #include "perl.h"
 
 STR *
-afetch(ar,key)
+afetch(ar,key,lval)
 register ARRAY *ar;
 int key;
+int lval;
 {
-    if (key < 0 || key > ar->ary_fill)
-       return Nullstr;
+    STR *str;
+
+    if (key < 0 || key > ar->ary_fill) {
+       if (lval && key >= 0) {
+           if (ar->ary_flags & ARF_REAL)
+               str = Str_new(5,0);
+           else
+               str = str_static(&str_undef);
+           (void)astore(ar,key,str);
+           return str;
+       }
+       else
+           return Nullstr;
+    }
+    if (lval && !ar->ary_array[key]) {
+       str = Str_new(6,0);
+       (void)astore(ar,key,str);
+       return str;
+    }
     return ar->ary_array[key];
 }
 
@@ -25,60 +48,84 @@ register ARRAY *ar;
 int key;
 STR *val;
 {
-    bool retval;
+    int retval;
 
     if (key < 0)
        return FALSE;
     if (key > ar->ary_max) {
-       int newmax = key + ar->ary_max / 5;
-
-       ar->ary_array = (STR**)saferealloc((char*)ar->ary_array,
-           (newmax+1) * sizeof(STR*));
-       bzero((char*)&ar->ary_array[ar->ary_max+1],
-           (newmax - ar->ary_max) * sizeof(STR*));
-       ar->ary_max = newmax;
+       int newmax;
+
+       if (ar->ary_alloc != ar->ary_array) {
+           retval = ar->ary_array - ar->ary_alloc;
+           Copy(ar->ary_array, ar->ary_alloc, ar->ary_max+1, STR*);
+           Zero(ar->ary_alloc+ar->ary_max+1, retval, STR*);
+           ar->ary_max += retval;
+           ar->ary_array -= retval;
+           if (key > ar->ary_max - 10) {
+               newmax = key + ar->ary_max;
+               goto resize;
+           }
+       }
+       else {
+           newmax = key + ar->ary_max / 5;
+         resize:
+           Renew(ar->ary_alloc,newmax+1, STR*);
+           Zero(&ar->ary_alloc[ar->ary_max+1], newmax - ar->ary_max, STR*);
+           ar->ary_array = ar->ary_alloc;
+           ar->ary_max = newmax;
+       }
     }
-    while (ar->ary_fill < key) {
-       if (++ar->ary_fill < key && ar->ary_array[ar->ary_fill] != Nullstr) {
-           str_free(ar->ary_array[ar->ary_fill]);
-           ar->ary_array[ar->ary_fill] = Nullstr;
+    if ((ar->ary_flags & ARF_REAL) && ar->ary_fill < key) {
+       while (++ar->ary_fill < key) {
+           if (ar->ary_array[ar->ary_fill] != Nullstr) {
+               str_free(ar->ary_array[ar->ary_fill]);
+               ar->ary_array[ar->ary_fill] = Nullstr;
+           }
        }
     }
     retval = (ar->ary_array[key] != Nullstr);
-    if (retval)
+    if (retval && (ar->ary_flags & ARF_REAL))
        str_free(ar->ary_array[key]);
     ar->ary_array[key] = val;
     return retval;
 }
 
-bool
-adelete(ar,key)
-register ARRAY *ar;
-int key;
-{
-    if (key < 0 || key > ar->ary_max)
-       return FALSE;
-    if (ar->ary_array[key]) {
-       str_free(ar->ary_array[key]);
-       ar->ary_array[key] = Nullstr;
-       return TRUE;
-    }
-    return FALSE;
-}
-
 ARRAY *
 anew(stab)
 STAB *stab;
 {
-    register ARRAY *ar = (ARRAY*)safemalloc(sizeof(ARRAY));
+    register ARRAY *ar;
 
-    ar->ary_array = (STR**) safemalloc(5 * sizeof(STR*));
-    ar->ary_magic = str_new(0);
-    ar->ary_magic->str_link.str_magic = stab;
+    New(1,ar,1,ARRAY);
+    Newz(2,ar->ary_alloc,5,STR*);
+    ar->ary_array = ar->ary_alloc;
+    ar->ary_magic = Str_new(7,0);
+    str_magic(ar->ary_magic, stab, '#', Nullch, 0);
     ar->ary_fill = -1;
     ar->ary_index = -1;
     ar->ary_max = 4;
-    bzero((char*)ar->ary_array, 5 * sizeof(STR*));
+    ar->ary_flags = ARF_REAL;
+    return ar;
+}
+
+ARRAY *
+afake(stab,size,strp)
+STAB *stab;
+int size;
+STR **strp;
+{
+    register ARRAY *ar;
+
+    New(3,ar,1,ARRAY);
+    New(4,ar->ary_alloc,size+1,STR*);
+    Copy(strp,ar->ary_alloc,size,STR*);
+    ar->ary_array = ar->ary_alloc;
+    ar->ary_magic = Str_new(8,0);
+    str_magic(ar->ary_magic, stab, '#', Nullch, 0);
+    ar->ary_fill = size - 1;
+    ar->ary_index = -1;
+    ar->ary_max = size - 1;
+    ar->ary_flags = 0;
     return ar;
 }
 
@@ -88,12 +135,16 @@ register ARRAY *ar;
 {
     register int key;
 
-    if (!ar)
+    if (!ar || !(ar->ary_flags & ARF_REAL))
        return;
+    if (key = ar->ary_array - ar->ary_alloc) {
+       ar->ary_max += key;
+       ar->ary_array -= key;
+    }
     for (key = 0; key <= ar->ary_max; key++)
        str_free(ar->ary_array[key]);
     ar->ary_fill = -1;
-    bzero((char*)ar->ary_array, (ar->ary_max+1) * sizeof(STR*));
+    Zero(ar->ary_array, ar->ary_max+1, STR*);
 }
 
 void
@@ -104,11 +155,17 @@ register ARRAY *ar;
 
     if (!ar)
        return;
-    for (key = 0; key <= ar->ary_max; key++)
-       str_free(ar->ary_array[key]);
+    if (key = ar->ary_array - ar->ary_alloc) {
+       ar->ary_max += key;
+       ar->ary_array -= key;
+    }
+    if (ar->ary_flags & ARF_REAL) {
+       for (key = 0; key <= ar->ary_max; key++)
+           str_free(ar->ary_array[key]);
+    }
     str_free(ar->ary_magic);
-    safefree((char*)ar->ary_array);
-    safefree((char*)ar);
+    Safefree(ar->ary_alloc);
+    Safefree(ar);
 }
 
 bool
@@ -141,13 +198,21 @@ register int num;
 
     if (num <= 0)
        return;
-    astore(ar,ar->ary_fill+num,(STR*)0);       /* maybe extend array */
-    dstr = ar->ary_array + ar->ary_fill;
-    sstr = dstr - num;
-    for (i = ar->ary_fill; i >= 0; i--) {
-       *dstr-- = *sstr--;
+    if (ar->ary_array - ar->ary_alloc >= num) {
+       ar->ary_max += num;
+       ar->ary_fill += num;
+       while (num--)
+           *--ar->ary_array = Nullstr;
+    }
+    else {
+       (void)astore(ar,ar->ary_fill+num,(STR*)0);      /* maybe extend array */
+       dstr = ar->ary_array + ar->ary_fill;
+       sstr = dstr - num;
+       for (i = ar->ary_fill; i >= 0; i--) {
+           *dstr-- = *sstr--;
+       }
+       Zero(ar->ary_array, num, STR*);
     }
-    bzero((char*)(ar->ary_array), num * sizeof(STR*));
 }
 
 STR *
@@ -158,10 +223,10 @@ register ARRAY *ar;
 
     if (ar->ary_fill < 0)
        return Nullstr;
-    retval = ar->ary_array[0];
-    bcopy((char*)(ar->ary_array+1),(char*)ar->ary_array,
-      ar->ary_fill * sizeof(STR*));
-    ar->ary_array[ar->ary_fill--] = Nullstr;
+    retval = *ar->ary_array;
+    *(ar->ary_array++) = Nullstr;
+    ar->ary_max--;
+    ar->ary_fill--;
     return retval;
 }
 
@@ -181,33 +246,5 @@ int fill;
     if (fill <= ar->ary_max)
        ar->ary_fill = fill;
     else
-       astore(ar,fill,Nullstr);
-}
-
-void
-ajoin(ar,delim,str)
-register ARRAY *ar;
-char *delim;
-register STR *str;
-{
-    register int i;
-    register int len;
-    register int dlen;
-
-    if (ar->ary_fill < 0) {
-       str_set(str,"");
-       STABSET(str);
-       return;
-    }
-    dlen = strlen(delim);
-    len = ar->ary_fill * dlen;         /* account for delimiters */
-    for (i = ar->ary_fill; i >= 0; i--)
-       len += str_len(ar->ary_array[i]);
-    str_grow(str,len);                 /* preallocate for efficiency */
-    str_sset(str,ar->ary_array[0]);
-    for (i = 1; i <= ar->ary_fill; i++) {
-       str_ncat(str,delim,dlen);
-       str_scat(str,ar->ary_array[i]);
-    }
-    STABSET(str);
+       (void)astore(ar,fill,Nullstr);
 }
diff --git a/array.h b/array.h
index d8dfe54..d489f64 100644 (file)
--- a/array.h
+++ b/array.h
@@ -1,22 +1,30 @@
-/* $Header: array.h,v 2.0 88/06/05 00:08:21 root Exp $
+/* $Header: array.h,v 3.0 89/10/18 15:08:41 lwall Locked $
+ *
+ *    Copyright (c) 1989, Larry Wall
+ *
+ *    You may distribute under the terms of the GNU General Public License
+ *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       array.h,v $
- * Revision 2.0  88/06/05  00:08:21  root
- * Baseline version 2.0.
+ * Revision 3.0  89/10/18  15:08:41  lwall
+ * 3.0 baseline
  * 
  */
 
 struct atbl {
     STR        **ary_array;
+    STR **ary_alloc;
     STR *ary_magic;
     int ary_max;
     int ary_fill;
     int ary_index;
+    char ary_flags;
 };
 
+#define ARF_REAL 1     /* free old entries */
+
 STR *afetch();
 bool astore();
-bool adelete();
 STR *apop();
 STR *ashift();
 void afree();
@@ -24,3 +32,4 @@ void aclear();
 bool apush();
 int alen();
 ARRAY *anew();
+ARRAY *afake();
diff --git a/client b/client
new file mode 100644 (file)
index 0000000..97ecbc2
--- /dev/null
+++ b/client
@@ -0,0 +1,34 @@
+#!./perl
+
+$pat = 'S n C4 x8';
+$inet = 2;
+$echo = 7;
+$smtp = 25;
+$nntp = 119;
+$test = 2345;
+
+$SIG{'INT'} = 'dokill';
+
+$this = pack($pat,$inet,0,   128,149,13,43);
+$that = pack($pat,$inet,$test,127,0,0,1);
+
+if (socket(S,2,1,6)) { print "socket ok\n"; } else { die $!; }
+if (bind(S,$this)) { print "bind ok\n"; } else { die $!; }
+if (connect(S,$that)) { print "connect ok\n"; } else { die $!; }
+
+select(S); $| = 1; select(stdout);
+
+if ($child = fork) {
+    while (<>) {
+       print S;
+    }
+    sleep 3;
+    do dokill();
+}
+else {
+    while (<S>) {
+       print;
+    }
+}
+
+sub dokill { kill 9,$child if $child; }
diff --git a/cmd.c b/cmd.c
index f5649b6..682bd08 100644 (file)
--- a/cmd.c
+++ b/cmd.c
@@ -1,44 +1,60 @@
-/* $Header: cmd.c,v 2.0 88/06/05 00:08:24 root Exp $
+/* $Header: cmd.c,v 3.0 89/10/18 15:09:02 lwall Locked $
+ *
+ *    Copyright (c) 1989, Larry Wall
+ *
+ *    You may distribute under the terms of the GNU General Public License
+ *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       cmd.c,v $
- * Revision 2.0  88/06/05  00:08:24  root
- * Baseline version 2.0.
+ * Revision 3.0  89/10/18  15:09:02  lwall
+ * 3.0 baseline
  * 
  */
 
 #include "EXTERN.h"
 #include "perl.h"
 
+#ifdef I_VARARGS
+#  include <varargs.h>
+#endif
+
 static STR str_chop;
 
+void grow_dlevel();
+
 /* This is the main command loop.  We try to spend as much time in this loop
  * as possible, so lots of optimizations do their activities in here.  This
  * means things get a little sloppy.
  */
 
-STR *
-cmd_exec(cmd)
+int
+cmd_exec(cmd,gimme,sp)
 #ifdef cray    /* nobody else has complained yet */
 CMD *cmd;
 #else
 register CMD *cmd;
 #endif
+int gimme;
+int sp;
 {
     SPAT *oldspat;
     int oldsave;
+    int aryoptsave;
 #ifdef DEBUGGING
     int olddlevel;
     int entdlevel;
 #endif
-    register STR *retstr;
+    register STR *retstr = &str_undef;
     register char *tmps;
     register int cmdflags;
     register int match;
     register char *go_to = goto_targ;
+    register int newsp = -2;
+    register STR **st = stack->ary_array;
     FILE *fp;
     ARRAY *ar;
 
-    retstr = &str_no;
+    lastsize = 0;
 #ifdef DEBUGGING
     entdlevel = dlevel;
 #endif
@@ -46,8 +62,17 @@ tail_recursion_entry:
 #ifdef DEBUGGING
     dlevel = entdlevel;
 #endif
-    if (cmd == Nullcmd)
-       return retstr;
+#ifdef TAINT
+    tainted = 0;       /* Each statement is presumed innocent */
+#endif
+    if (cmd == Nullcmd) {
+       if (gimme == G_ARRAY && newsp > -2)
+           return newsp;
+       else {
+           st[++sp] = retstr;
+           return sp;
+       }
+    }
     cmdflags = cmd->c_flags;   /* hopefully load register */
     if (go_to) {
        if (cmd->c_label && strEQ(go_to,cmd->c_label))
@@ -61,28 +86,50 @@ tail_recursion_entry:
                olddlevel = dlevel;
 #endif
                retstr = &str_yes;
+               newsp = -2;
                if (cmd->ucmd.ccmd.cc_true) {
 #ifdef DEBUGGING
                    if (debug) {
                        debname[dlevel] = 't';
-                       debdelim[dlevel++] = '_';
+                       debdelim[dlevel] = '_';
+                       if (++dlevel >= dlmax)
+                           grow_dlevel();
                    }
 #endif
-                   retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
+                   newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
+                   st = stack->ary_array;      /* possibly reallocated */
+                   retstr = st[newsp];
                }
-               if (!goto_targ) {
+               if (!goto_targ)
                    go_to = Nullch;
-               } else {
-                   retstr = &str_no;
-                   if (cmd->ucmd.ccmd.cc_alt) {
+               curspat = oldspat;
+               if (savestack->ary_fill > oldsave)
+                   restorelist(oldsave);
 #ifdef DEBUGGING
-                       if (debug) {
-                           debname[dlevel] = 'e';
-                           debdelim[dlevel++] = '_';
-                       }
+               dlevel = olddlevel;
 #endif
-                       retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
+               cmd = cmd->ucmd.ccmd.cc_alt;
+               goto tail_recursion_entry;
+           case C_ELSE:
+               oldspat = curspat;
+               oldsave = savestack->ary_fill;
+#ifdef DEBUGGING
+               olddlevel = dlevel;
+#endif
+               retstr = &str_undef;
+               newsp = -2;
+               if (cmd->ucmd.ccmd.cc_true) {
+#ifdef DEBUGGING
+                   if (debug) {
+                       debname[dlevel] = 'e';
+                       debdelim[dlevel] = '_';
+                       if (++dlevel >= dlmax)
+                           grow_dlevel();
                    }
+#endif
+                   newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
+                   st = stack->ary_array;      /* possibly reallocated */
+                   retstr = st[newsp];
                }
                if (!goto_targ)
                    go_to = Nullch;
@@ -97,19 +144,31 @@ tail_recursion_entry:
            case C_WHILE:
                if (!(cmdflags & CF_ONCE)) {
                    cmdflags |= CF_ONCE;
-                   loop_ptr++;
+                   if (++loop_ptr >= loop_max) {
+                       loop_max += 128;
+                       Renew(loop_stack, loop_max, struct loop);
+                   }
                    loop_stack[loop_ptr].loop_label = cmd->c_label;
+                   loop_stack[loop_ptr].loop_sp = sp;
 #ifdef DEBUGGING
                    if (debug & 4) {
                        deb("(Pushing label #%d %s)\n",
-                         loop_ptr,cmd->c_label);
+                         loop_ptr, cmd->c_label ? cmd->c_label : "");
                    }
 #endif
                }
                switch (setjmp(loop_stack[loop_ptr].loop_env)) {
                case O_LAST:    /* not done unless go_to found */
                    go_to = Nullch;
-                   retstr = &str_no;
+                   st = stack->ary_array;      /* possibly reallocated */
+                   if (lastretstr) {
+                       retstr = lastretstr;
+                       newsp = -2;
+                   }
+                   else {
+                       newsp = sp + lastsize;
+                       retstr = st[newsp];
+                   }
 #ifdef DEBUGGING
                    olddlevel = dlevel;
 #endif
@@ -133,10 +192,14 @@ tail_recursion_entry:
 #ifdef DEBUGGING
                    if (debug) {
                        debname[dlevel] = 't';
-                       debdelim[dlevel++] = '_';
+                       debdelim[dlevel] = '_';
+                       if (++dlevel >= dlmax)
+                           grow_dlevel();
                    }
 #endif
-                   cmd_exec(cmd->ucmd.ccmd.cc_true);
+                   newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
+                   st = stack->ary_array;      /* possibly reallocated */
+                   retstr = st[newsp];
                }
                if (!goto_targ) {
                    go_to = Nullch;
@@ -149,10 +212,14 @@ tail_recursion_entry:
 #ifdef DEBUGGING
                    if (debug) {
                        debname[dlevel] = 'a';
-                       debdelim[dlevel++] = '_';
+                       debdelim[dlevel] = '_';
+                       if (++dlevel >= dlmax)
+                           grow_dlevel();
                    }
 #endif
-                   cmd_exec(cmd->ucmd.ccmd.cc_alt);
+                   newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
+                   st = stack->ary_array;      /* possibly reallocated */
+                   retstr = st[newsp];
                }
                if (goto_targ)
                    break;
@@ -162,12 +229,13 @@ tail_recursion_entry:
            cmd = cmd->c_next;
            if (cmd && cmd->c_head == cmd)
                                        /* reached end of while loop */
-               return retstr;          /* targ isn't in this block */
+               return sp;              /* targ isn't in this block */
            if (cmdflags & CF_ONCE) {
 #ifdef DEBUGGING
                if (debug & 4) {
+                   tmps = loop_stack[loop_ptr].loop_label;
                    deb("(Popping label #%d %s)\n",loop_ptr,
-                       loop_stack[loop_ptr].loop_label);
+                       tmps ? tmps : "" );
                }
 #endif
                loop_ptr--;
@@ -191,11 +259,11 @@ until_loop:
                curspat);
        }
        debname[dlevel] = cmdname[cmd->c_type][0];
-       debdelim[dlevel++] = '!';
+       debdelim[dlevel] = '!';
+       if (++dlevel >= dlmax)
+           grow_dlevel();
     }
 #endif
-    while (tmps_max > tmps_base)               /* clean up after last eval */
-       str_free(tmps_list[tmps_max--]);
 
     /* Here is some common optimization */
 
@@ -204,12 +272,14 @@ until_loop:
 
        case CFT_FALSE:
            retstr = cmd->c_short;
+           newsp = -2;
            match = FALSE;
            if (cmdflags & CF_NESURE)
                goto maybe;
            break;
        case CFT_TRUE:
            retstr = cmd->c_short;
+           newsp = -2;
            match = TRUE;
            if (cmdflags & CF_EQSURE)
                goto flipmaybe;
@@ -217,6 +287,7 @@ until_loop:
 
        case CFT_REG:
            retstr = STAB_STR(cmd->c_stab);
+           newsp = -2;
            match = str_true(retstr);   /* => retstr = retstr, c2 should fix */
            if (cmdflags & (match ? CF_EQSURE : CF_NESURE))
                goto flipmaybe;
@@ -232,10 +303,23 @@ until_loop:
            /* FALL THROUGH */
        case CFT_STROP:         /* string op optimization */
            retstr = STAB_STR(cmd->c_stab);
+           newsp = -2;
+#ifndef I286
            if (*cmd->c_short->str_ptr == *str_get(retstr) &&
-                   strnEQ(cmd->c_short->str_ptr, str_get(retstr),
-                     cmd->c_slen) ) {
+                   bcmp(cmd->c_short->str_ptr, str_get(retstr),
+                     cmd->c_slen) == 0 ) {
                if (cmdflags & CF_EQSURE) {
+                   if (sawampersand && (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
+                       curspat = Nullspat;
+                       if (leftstab)
+                           str_nset(stab_val(leftstab),"",0);
+                       if (amperstab)
+                           str_sset(stab_val(amperstab),cmd->c_short);
+                       if (rightstab)
+                           str_nset(stab_val(rightstab),
+                             retstr->str_ptr + cmd->c_slen,
+                             retstr->str_cur - cmd->c_slen);
+                   }
                    match = !(cmdflags & CF_FIRSTNEG);
                    retstr = &str_yes;
                    goto flipmaybe;
@@ -246,23 +330,76 @@ until_loop:
                retstr = &str_no;
                goto flipmaybe;
            }
+#else
+           {
+               char *zap1, *zap2, zap1c, zap2c;
+               int  zaplen;
+
+               zap1 = cmd->c_short->str_ptr;
+               zap2 = str_get(retstr);
+               zap1c = *zap1;
+               zap2c = *zap2;
+               zaplen = cmd->c_slen;
+               if ((zap1c == zap2c) && (bcmp(zap1, zap2, zaplen) == 0)) {
+                   if (cmdflags & CF_EQSURE) {
+                       if (sawampersand &&
+                         (cmdflags & CF_OPTIMIZE) != CFT_STROP) {
+                           curspat = Nullspat;
+                           if (leftstab)
+                               str_nset(stab_val(leftstab),"",0);
+                           if (amperstab)
+                               str_sset(stab_val(amperstab),cmd->c_short);
+                           if (rightstab)
+                               str_nset(stab_val(rightstab),
+                                        retstr->str_ptr + cmd->c_slen,
+                                        retstr->str_cur - cmd->c_slen);
+                       }
+                       match = !(cmdflags & CF_FIRSTNEG);
+                       retstr = &str_yes;
+                       goto flipmaybe;
+                   }
+               }
+               else if (cmdflags & CF_NESURE) {
+                   match = cmdflags & CF_FIRSTNEG;
+                   retstr = &str_no;
+                   goto flipmaybe;
+               }
+           }
+#endif
            break;                      /* must evaluate */
 
        case CFT_SCAN:                  /* non-anchored search */
          scanner:
            retstr = STAB_STR(cmd->c_stab);
-           if (retstr->str_pok == 5)
+           newsp = -2;
+           if (retstr->str_pok & SP_STUDIED)
                if (screamfirst[cmd->c_short->str_rare] >= 0)
                    tmps = screaminstr(retstr, cmd->c_short);
                else
                    tmps = Nullch;
            else {
                tmps = str_get(retstr);         /* make sure it's pok */
-               tmps = fbminstr(tmps, tmps + retstr->str_cur, cmd->c_short);
+#ifndef lint
+               tmps = fbminstr((unsigned char*)tmps,
+                   (unsigned char*)tmps + retstr->str_cur, cmd->c_short);
+#endif
            }
            if (tmps) {
                if (cmdflags & CF_EQSURE) {
-                   ++*(long*)&cmd->c_short->str_nval;
+                   ++cmd->c_short->str_u.str_useful;
+                   if (sawampersand) {
+                       curspat = Nullspat;
+                       if (leftstab)
+                           str_nset(stab_val(leftstab),retstr->str_ptr,
+                             tmps - retstr->str_ptr);
+                       if (amperstab)
+                           str_sset(stab_val(amperstab),cmd->c_short);
+                       if (rightstab)
+                           str_nset(stab_val(rightstab),
+                             tmps + cmd->c_short->str_cur,
+                             retstr->str_cur - (tmps - retstr->str_ptr) -
+                               cmd->c_short->str_cur);
+                   }
                    match = !(cmdflags & CF_FIRSTNEG);
                    retstr = &str_yes;
                    goto flipmaybe;
@@ -272,13 +409,13 @@ until_loop:
            }
            else {
                if (cmdflags & CF_NESURE) {
-                   ++*(long*)&cmd->c_short->str_nval;
+                   ++cmd->c_short->str_u.str_useful;
                    match = cmdflags & CF_FIRSTNEG;
                    retstr = &str_no;
                    goto flipmaybe;
                }
            }
-           if (--*(long*)&cmd->c_short->str_nval < 0) {
+           if (--cmd->c_short->str_u.str_useful < 0) {
                str_free(cmd->c_short);
                cmd->c_short = Nullstr;
                cmdflags &= ~CF_OPTIMIZE;
@@ -289,24 +426,29 @@ until_loop:
 
        case CFT_NUMOP:         /* numeric op optimization */
            retstr = STAB_STR(cmd->c_stab);
+           newsp = -2;
            switch (cmd->c_slen) {
            case O_EQ:
-               match = (str_gnum(retstr) == cmd->c_short->str_nval);
+               if (dowarn) {
+                   if ((!retstr->str_nok && !looks_like_number(retstr)))
+                       warn("Possible use of == on string value");
+               }
+               match = (str_gnum(retstr) == cmd->c_short->str_u.str_nval);
                break;
            case O_NE:
-               match = (str_gnum(retstr) != cmd->c_short->str_nval);
+               match = (str_gnum(retstr) != cmd->c_short->str_u.str_nval);
                break;
            case O_LT:
-               match = (str_gnum(retstr) <  cmd->c_short->str_nval);
+               match = (str_gnum(retstr) <  cmd->c_short->str_u.str_nval);
                break;
            case O_LE:
-               match = (str_gnum(retstr) <= cmd->c_short->str_nval);
+               match = (str_gnum(retstr) <= cmd->c_short->str_u.str_nval);
                break;
            case O_GT:
-               match = (str_gnum(retstr) >  cmd->c_short->str_nval);
+               match = (str_gnum(retstr) >  cmd->c_short->str_u.str_nval);
                break;
            case O_GE:
-               match = (str_gnum(retstr) >= cmd->c_short->str_nval);
+               match = (str_gnum(retstr) >= cmd->c_short->str_u.str_nval);
                break;
            }
            if (match) {
@@ -323,86 +465,111 @@ until_loop:
 
        case CFT_INDGETS:               /* while (<$foo>) */
            last_in_stab = stabent(str_get(STAB_STR(cmd->c_stab)),TRUE);
-           if (!last_in_stab->stab_io)
-               last_in_stab->stab_io = stio_new();
+           if (!stab_io(last_in_stab))
+               stab_io(last_in_stab) = stio_new();
            goto dogets;
        case CFT_GETS:                  /* really a while (<file>) */
            last_in_stab = cmd->c_stab;
          dogets:
-           fp = last_in_stab->stab_io->fp;
-           retstr = defstab->stab_val;
-           if (fp && str_gets(retstr, fp)) {
-               if (*retstr->str_ptr == '0' && !retstr->str_ptr[1])
+           fp = stab_io(last_in_stab)->ifp;
+           retstr = stab_val(defstab);
+           newsp = -2;
+           if (fp && str_gets(retstr, fp, 0)) {
+               if (*retstr->str_ptr == '0' && retstr->str_cur == 1)
                    match = FALSE;
                else
                    match = TRUE;
-               last_in_stab->stab_io->lines++;
+               stab_io(last_in_stab)->lines++;
            }
-           else if (last_in_stab->stab_io->flags & IOF_ARGV)
+           else if (stab_io(last_in_stab)->flags & IOF_ARGV)
                goto doeval;    /* doesn't necessarily count as EOF yet */
            else {
-               retstr = &str_no;
+               retstr = &str_undef;
                match = FALSE;
            }
            goto flipmaybe;
        case CFT_EVAL:
            break;
        case CFT_UNFLIP:
-           retstr = eval(cmd->c_expr,Null(STR***),-1);
+           while (tmps_max > tmps_base)        /* clean up after last eval */
+               str_free(tmps_list[tmps_max--]);
+           newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
+           st = stack->ary_array;      /* possibly reallocated */
+           retstr = st[newsp];
            match = str_true(retstr);
            if (cmd->c_expr->arg_type == O_FLIP)        /* undid itself? */
                cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
            goto maybe;
        case CFT_CHOP:
-           retstr = cmd->c_stab->stab_val;
+           retstr = stab_val(cmd->c_stab);
+           newsp = -2;
            match = (retstr->str_cur != 0);
            tmps = str_get(retstr);
            tmps += retstr->str_cur - match;
-           str_set(&str_chop,tmps);
+           str_nset(&str_chop,tmps,match);
            *tmps = '\0';
            retstr->str_nok = 0;
            retstr->str_cur = tmps - retstr->str_ptr;
            retstr = &str_chop;
            goto flipmaybe;
        case CFT_ARRAY:
-           ar = cmd->c_expr[1].arg_ptr.arg_stab->stab_array;
+           ar = stab_array(cmd->c_expr[1].arg_ptr.arg_stab);
            match = ar->ary_index;      /* just to get register */
 
-           if (match < 0)              /* first time through here? */
-               cmd->c_short = cmd->c_stab->stab_val;
+           if (match < 0) {            /* first time through here? */
+               aryoptsave = savestack->ary_fill;
+               savesptr(&stab_val(cmd->c_stab));
+               saveint(&ar->ary_index);
+           }
 
-           if (match >= ar->ary_fill) {
-               ar->ary_index = -1;
-/*             cmd->c_stab->stab_val = cmd->c_short; - Can't be done in LAST */
+           if (match >= ar->ary_fill) {        /* we're in LAST, probably */
+               retstr = &str_undef;
+               ar->ary_index = -1;     /* this is actually redundant */
                match = FALSE;
            }
            else {
                match++;
-               retstr = cmd->c_stab->stab_val = ar->ary_array[match];
+               retstr = stab_val(cmd->c_stab) = ar->ary_array[match];
                ar->ary_index = match;
                match = TRUE;
            }
+           newsp = -2;
            goto maybe;
        }
 
     /* we have tried to make this normal case as abnormal as possible */
 
     doeval:
-       lastretstr = retstr;
-       retstr = eval(cmd->c_expr,Null(STR***),-1);
-       match = str_true(retstr);
+       if (gimme == G_ARRAY) {
+           lastretstr = Nullstr;
+           lastspbase = sp;
+           lastsize = newsp - sp;
+       }
+       else
+           lastretstr = retstr;
+       while (tmps_max > tmps_base)    /* clean up after last eval */
+           str_free(tmps_list[tmps_max--]);
+       newsp = eval(cmd->c_expr,gimme && (cmdflags & CF_TERM),sp);
+       st = stack->ary_array;  /* possibly reallocated */
+       retstr = st[newsp];
+       if (newsp > sp)
+           match = str_true(retstr);
+       else
+           match = FALSE;
        goto maybe;
 
     /* if flipflop was true, flop it */
 
     flipmaybe:
        if (match && cmdflags & CF_FLIP) {
+           while (tmps_max > tmps_base)        /* clean up after last eval */
+               str_free(tmps_list[tmps_max--]);
            if (cmd->c_expr->arg_type == O_FLOP) {      /* currently toggled? */
-               retstr = eval(cmd->c_expr,Null(STR***),-1);/*let eval undo it*/
+               newsp = eval(cmd->c_expr,G_SCALAR,sp);/*let eval undo it*/
                cmdflags = copyopt(cmd,cmd->c_expr[3].arg_ptr.arg_cmd);
            }
            else {
-               retstr = eval(cmd->c_expr,Null(STR***),-1);/* let eval do it */
+               newsp = eval(cmd->c_expr,G_SCALAR,sp);/* let eval do it */
                if (cmd->c_expr->arg_type == O_FLOP)    /* still toggled? */
                    cmdflags = copyopt(cmd,cmd->c_expr[4].arg_ptr.arg_cmd);
            }
@@ -418,9 +585,12 @@ until_loop:
     maybe:
        if (cmdflags & CF_INVERT)
            match = !match;
-       if (!match && cmd->c_type != C_IF)
+       if (!match)
            goto next_cmd;
     }
+#ifdef TAINT
+    tainted = 0;       /* modifier doesn't affect regular expression */
+#endif
 
     /* now to do the actual command, if any */
 
@@ -429,39 +599,87 @@ until_loop:
        fatal("panic: cmd_exec");
     case C_EXPR:                       /* evaluated for side effects */
        if (cmd->ucmd.acmd.ac_expr) {   /* more to do? */
-           lastretstr = retstr;
-           retstr = eval(cmd->ucmd.acmd.ac_expr,Null(STR***),-1);
+           if (gimme == G_ARRAY) {
+               lastretstr = Nullstr;
+               lastspbase = sp;
+               lastsize = newsp - sp;
+           }
+           else
+               lastretstr = retstr;
+           while (tmps_max > tmps_base)        /* clean up after last eval */
+               str_free(tmps_list[tmps_max--]);
+           newsp = eval(cmd->ucmd.acmd.ac_expr,gimme && (cmdflags&CF_TERM),sp);
+           st = stack->ary_array;      /* possibly reallocated */
+           retstr = st[newsp];
        }
        break;
+    case C_NSWITCH:
+       match = (int)str_gnum(STAB_STR(cmd->c_stab));
+       goto doswitch;
+    case C_CSWITCH:
+       match = *(str_get(STAB_STR(cmd->c_stab))) & 255;
+      doswitch:
+       match -= cmd->ucmd.scmd.sc_offset;
+       if (match < 0)
+           match = 0;
+       else if (match > cmd->ucmd.scmd.sc_max)
+           match = cmd->c_slen;
+       cmd = cmd->ucmd.scmd.sc_next[match];
+       goto tail_recursion_entry;
+    case C_NEXT:
+       cmd = cmd->ucmd.ccmd.cc_alt;
+       goto tail_recursion_entry;
+    case C_ELSIF:
+       fatal("panic: ELSIF");
     case C_IF:
        oldspat = curspat;
        oldsave = savestack->ary_fill;
 #ifdef DEBUGGING
        olddlevel = dlevel;
 #endif
-       if (match) {
-           retstr = &str_yes;
-           if (cmd->ucmd.ccmd.cc_true) {
+       retstr = &str_yes;
+       newsp = -2;
+       if (cmd->ucmd.ccmd.cc_true) {
 #ifdef DEBUGGING
-               if (debug) {
-                   debname[dlevel] = 't';
-                   debdelim[dlevel++] = '_';
-               }
-#endif
-               retstr = cmd_exec(cmd->ucmd.ccmd.cc_true);
+           if (debug) {
+               debname[dlevel] = 't';
+               debdelim[dlevel] = '_';
+               if (++dlevel >= dlmax)
+                   grow_dlevel();
            }
+#endif
+           newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
+           st = stack->ary_array;      /* possibly reallocated */
+           retstr = st[newsp];
        }
-       else {
-           retstr = &str_no;
-           if (cmd->ucmd.ccmd.cc_alt) {
+       curspat = oldspat;
+       if (savestack->ary_fill > oldsave)
+           restorelist(oldsave);
 #ifdef DEBUGGING
-               if (debug) {
-                   debname[dlevel] = 'e';
-                   debdelim[dlevel++] = '_';
-               }
+       dlevel = olddlevel;
 #endif
-               retstr = cmd_exec(cmd->ucmd.ccmd.cc_alt);
+       cmd = cmd->ucmd.ccmd.cc_alt;
+       goto tail_recursion_entry;
+    case C_ELSE:
+       oldspat = curspat;
+       oldsave = savestack->ary_fill;
+#ifdef DEBUGGING
+       olddlevel = dlevel;
+#endif
+       retstr = &str_undef;
+       newsp = -2;
+       if (cmd->ucmd.ccmd.cc_true) {
+#ifdef DEBUGGING
+           if (debug) {
+               debname[dlevel] = 'e';
+               debdelim[dlevel] = '_';
+               if (++dlevel >= dlmax)
+                   grow_dlevel();
            }
+#endif
+           newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
+           st = stack->ary_array;      /* possibly reallocated */
+           retstr = st[newsp];
        }
        curspat = oldspat;
        if (savestack->ary_fill > oldsave)
@@ -474,18 +692,31 @@ until_loop:
     case C_WHILE:
        if (!(cmdflags & CF_ONCE)) {    /* first time through here? */
            cmdflags |= CF_ONCE;
-           loop_ptr++;
+           if (++loop_ptr >= loop_max) {
+               loop_max += 128;
+               Renew(loop_stack, loop_max, struct loop);
+           }
            loop_stack[loop_ptr].loop_label = cmd->c_label;
+           loop_stack[loop_ptr].loop_sp = sp;
 #ifdef DEBUGGING
            if (debug & 4) {
                deb("(Pushing label #%d %s)\n",
-                 loop_ptr,cmd->c_label);
+                 loop_ptr, cmd->c_label ? cmd->c_label : "");
            }
 #endif
        }
        switch (setjmp(loop_stack[loop_ptr].loop_env)) {
        case O_LAST:
-           retstr = lastretstr;
+           /* retstr = lastretstr; */
+           st = stack->ary_array;      /* possibly reallocated */
+           if (lastretstr) {
+               retstr = lastretstr;
+               newsp = -2;
+           }
+           else {
+               newsp = sp + lastsize;
+               retstr = st[newsp];
+           }
            curspat = oldspat;
            if (savestack->ary_fill > oldsave)
                restorelist(oldsave);
@@ -508,10 +739,14 @@ until_loop:
 #ifdef DEBUGGING
            if (debug) {
                debname[dlevel] = 't';
-               debdelim[dlevel++] = '_';
+               debdelim[dlevel] = '_';
+               if (++dlevel >= dlmax)
+                   grow_dlevel();
            }
 #endif
-           cmd_exec(cmd->ucmd.ccmd.cc_true);
+           newsp = cmd_exec(cmd->ucmd.ccmd.cc_true,gimme,sp);
+           st = stack->ary_array;      /* possibly reallocated */
+           retstr = st[newsp];
        }
        /* actually, this spot is rarely reached anymore since the above
         * cmd_exec() returns through longjmp().  Hooray for structure.
@@ -524,10 +759,14 @@ until_loop:
 #ifdef DEBUGGING
            if (debug) {
                debname[dlevel] = 'a';
-               debdelim[dlevel++] = '_';
+               debdelim[dlevel] = '_';
+               if (++dlevel >= dlmax)
+                   grow_dlevel();
            }
 #endif
-           cmd_exec(cmd->ucmd.ccmd.cc_alt);
+           newsp = cmd_exec(cmd->ucmd.ccmd.cc_alt,gimme,sp);
+           st = stack->ary_array;      /* possibly reallocated */
+           retstr = st[newsp];
        }
       finish_while:
        curspat = oldspat;
@@ -550,20 +789,20 @@ until_loop:
     if (cmdflags & CF_ONCE) {
 #ifdef DEBUGGING
        if (debug & 4) {
-           deb("(Popping label #%d %s)\n",loop_ptr,
-               loop_stack[loop_ptr].loop_label);
+           tmps = loop_stack[loop_ptr].loop_label;
+           deb("(Popping label #%d %s)\n",loop_ptr, tmps ? tmps : "");
        }
 #endif
        loop_ptr--;
-       if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY) {
-           cmd->c_stab->stab_val = cmd->c_short;
-       }
+       if ((cmdflags & CF_OPTIMIZE) == CFT_ARRAY)
+           restorelist(aryoptsave);
     }
     cmd = cmd->c_next;
     goto tail_recursion_entry;
 }
 
 #ifdef DEBUGGING
+#  ifndef VARARGS
 /*VARARGS1*/
 deb(pat,a1,a2,a3,a4,a5,a6,a7,a8)
 char *pat;
@@ -575,6 +814,25 @@ char *pat;
        fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
     fprintf(stderr,pat,a1,a2,a3,a4,a5,a6,a7,a8);
 }
+#  else
+/*VARARGS1*/
+deb(va_alist)
+va_dcl
+{
+    va_list args;
+    char *pat;
+    register int i;
+
+    va_start(args);
+    fprintf(stderr,"%-4ld",(long)line);
+    for (i=0; i<dlevel; i++)
+       fprintf(stderr,"%c%c ",debname[i],debdelim[i]);
+
+    pat = va_arg(args, char *);
+    (void) vfprintf(stderr,pat,args);
+    va_end( args );
+}
+#  endif
 #endif
 
 copyopt(cmd,which)
@@ -589,6 +847,136 @@ register CMD *which;
     return cmd->c_flags;
 }
 
+ARRAY *
+saveary(stab)
+STAB *stab;
+{
+    register STR *str;
+
+    str = Str_new(10,0);
+    str->str_state = SS_SARY;
+    str->str_u.str_stab = stab;
+    if (str->str_ptr) {
+       Safefree(str->str_ptr);
+       str->str_len = 0;
+    }
+    str->str_ptr = (char*)stab_array(stab);
+    (void)apush(savestack,str); /* save array ptr */
+    stab_xarray(stab) = Null(ARRAY*);
+    return stab_xarray(aadd(stab));
+}
+
+HASH *
+savehash(stab)
+STAB *stab;
+{
+    register STR *str;
+
+    str = Str_new(11,0);
+    str->str_state = SS_SHASH;
+    str->str_u.str_stab = stab;
+    if (str->str_ptr) {
+       Safefree(str->str_ptr);
+       str->str_len = 0;
+    }
+    str->str_ptr = (char*)stab_hash(stab);
+    (void)apush(savestack,str); /* save hash ptr */
+    stab_xhash(stab) = Null(HASH*);
+    return stab_xhash(hadd(stab));
+}
+
+void
+saveitem(item)
+register STR *item;
+{
+    register STR *str;
+
+    (void)apush(savestack,item);               /* remember the pointer */
+    str = Str_new(12,0);
+    str_sset(str,item);
+    (void)apush(savestack,str);                        /* remember the value */
+}
+
+void
+saveint(intp)
+int *intp;
+{
+    register STR *str;
+
+    str = Str_new(13,0);
+    str->str_state = SS_SINT;
+    str->str_u.str_useful = (long)*intp;       /* remember value */
+    if (str->str_ptr) {
+       Safefree(str->str_ptr);
+       str->str_len = 0;
+    }
+    str->str_ptr = (char*)intp;                /* remember pointer */
+    (void)apush(savestack,str);
+}
+
+void
+savelong(longp)
+long *longp;
+{
+    register STR *str;
+
+    str = Str_new(14,0);
+    str->str_state = SS_SLONG;
+    str->str_u.str_useful = *longp;            /* remember value */
+    if (str->str_ptr) {
+       Safefree(str->str_ptr);
+       str->str_len = 0;
+    }
+    str->str_ptr = (char*)longp;               /* remember pointer */
+    (void)apush(savestack,str);
+}
+
+void
+savesptr(sptr)
+STR **sptr;
+{
+    register STR *str;
+
+    str = Str_new(15,0);
+    str->str_state = SS_SSTRP;
+    str->str_magic = *sptr;            /* remember value */
+    if (str->str_ptr) {
+       Safefree(str->str_ptr);
+       str->str_len = 0;
+    }
+    str->str_ptr = (char*)sptr;                /* remember pointer */
+    (void)apush(savestack,str);
+}
+
+void
+savenostab(stab)
+STAB *stab;
+{
+    register STR *str;
+
+    str = Str_new(16,0);
+    str->str_state = SS_SNSTAB;
+    str->str_magic = (STR*)stab;       /* remember which stab to free */
+    (void)apush(savestack,str);
+}
+
+void
+savehptr(hptr)
+HASH **hptr;
+{
+    register STR *str;
+
+    str = Str_new(17,0);
+    str->str_state = SS_SHPTR;
+    str->str_u.str_hash = *hptr;       /* remember value */
+    if (str->str_ptr) {
+       Safefree(str->str_ptr);
+       str->str_len = 0;
+    }
+    str->str_ptr = (char*)hptr;                /* remember pointer */
+    (void)apush(savestack,str);
+}
+
 void
 savelist(sarg,maxsarg)
 register STR **sarg;
@@ -598,10 +986,10 @@ int maxsarg;
     register int i;
 
     for (i = 1; i <= maxsarg; i++) {
-       apush(savestack,sarg[i]);               /* remember the pointer */
-       str = str_new(0);
+       (void)apush(savestack,sarg[i]);         /* remember the pointer */
+       str = Str_new(18,0);
        str_sset(str,sarg[i]);
-       apush(savestack,str);                   /* remember the value */
+       (void)apush(savestack,str);                     /* remember the value */
     }
 }
 
@@ -611,12 +999,70 @@ int base;
 {
     register STR *str;
     register STR *value;
+    register STAB *stab;
 
+    if (base < -1)
+       fatal("panic: corrupt saved stack index");
     while (savestack->ary_fill > base) {
        value = apop(savestack);
-       str = apop(savestack);
-       str_sset(str,value);
-       STABSET(str);
-       str_free(value);
+       switch (value->str_state) {
+       case SS_NORM:                           /* normal string */
+       case SS_INCR:
+           str = apop(savestack);
+           str_replace(str,value);
+           STABSET(str);
+           break;
+       case SS_SARY:                           /* array reference */
+           stab = value->str_u.str_stab;
+           afree(stab_xarray(stab));
+           stab_xarray(stab) = (ARRAY*)value->str_ptr;
+           value->str_ptr = Nullch;
+           str_free(value);
+           break;
+       case SS_SHASH:                          /* hash reference */
+           stab = value->str_u.str_stab;
+           (void)hfree(stab_xhash(stab));
+           stab_xhash(stab) = (HASH*)value->str_ptr;
+           value->str_ptr = Nullch;
+           str_free(value);
+           break;
+       case SS_SINT:                           /* int reference */
+           *((int*)value->str_ptr) = (int)value->str_u.str_useful;
+           value->str_ptr = Nullch;
+           str_free(value);
+           break;
+       case SS_SLONG:                          /* long reference */
+           *((long*)value->str_ptr) = value->str_u.str_useful;
+           value->str_ptr = Nullch;
+           str_free(value);
+           break;
+       case SS_SSTRP:                          /* STR* reference */
+           *((STR**)value->str_ptr) = value->str_magic;
+           value->str_magic = Nullstr;
+           value->str_ptr = Nullch;
+           str_free(value);
+           break;
+       case SS_SHPTR:                          /* HASH* reference */
+           *((HASH**)value->str_ptr) = value->str_u.str_hash;
+           value->str_ptr = Nullch;
+           str_free(value);
+           break;
+       case SS_SNSTAB:
+           stab = (STAB*)value->str_magic;
+           value->str_magic = Nullstr;
+           (void)stab_clear(stab);
+           str_free(value);
+           break;
+       default:
+           fatal("panic: restorelist inconsistency");
+       }
     }
 }
+
+void
+grow_dlevel()
+{
+    dlmax += 128;
+    Renew(debname, dlmax, char);
+    Renew(debdelim, dlmax, char);
+}
diff --git a/cmd.h b/cmd.h
index e320ee2..5e880a4 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -1,16 +1,26 @@
-/* $Header: cmd.h,v 2.0 88/06/05 00:08:28 root Exp $
+/* $Header: cmd.h,v 3.0 89/10/18 15:09:15 lwall Locked $
+ *
+ *    Copyright (c) 1989, Larry Wall
+ *
+ *    You may distribute under the terms of the GNU General Public License
+ *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       cmd.h,v $
- * Revision 2.0  88/06/05  00:08:28  root
- * Baseline version 2.0.
+ * Revision 3.0  89/10/18  15:09:15  lwall
+ * 3.0 baseline
  * 
  */
 
 #define C_NULL 0
 #define C_IF 1
-#define C_WHILE 2
-#define C_EXPR 3
+#define C_ELSE 2
+#define C_WHILE 3
 #define C_BLOCK 4
+#define C_EXPR 5
+#define C_NEXT 6
+#define C_ELSIF 7      /* temporary--turns into an IF + ELSE */
+#define C_CSWITCH 8    /* created by switch optimization in block_head() */
+#define C_NSWITCH 9    /* likewise */
 
 #ifdef DEBUGGING
 #ifndef DOINIT
@@ -19,21 +29,15 @@ extern char *cmdname[];
 char *cmdname[] = {
     "NULL",
     "IF",
+    "ELSE",
     "WHILE",
-    "EXPR",
     "BLOCK",
-    "5",
-    "6",
-    "7",
-    "8",
-    "9",
-    "10",
-    "11",
-    "12",
-    "13",
-    "14",
-    "15",
-    "16"
+    "EXPR",
+    "NEXT",
+    "ELSIF",
+    "CSWITCH",
+    "NSWITCH",
+    "10"
 };
 #endif
 #endif /* DEBUGGING */
@@ -48,6 +52,7 @@ char *cmdname[] = {
 #define CF_INVERT 04000        /* it's an "unless" or an "until" */
 #define CF_ONCE 010000 /* we've already pushed the label on the stack */
 #define CF_FLIP 020000 /* on a match do flipflop */
+#define CF_TERM 040000 /* value of this cmd might be returned */
 
 #define CFT_FALSE 0    /* c_expr is always false */
 #define CFT_TRUE 1     /* c_expr is always true */
@@ -62,6 +67,7 @@ char *cmdname[] = {
 #define CFT_ARRAY 10   /* this is a foreach loop */
 #define CFT_INDGETS 11 /* c_expr is <$variable> */
 #define CFT_NUMOP 12   /* c_expr is a numeric comparison */
+#define CFT_CCLASS 13  /* c_expr must start with one of these characters */
 
 #ifdef DEBUGGING
 #ifndef DOINIT
@@ -81,7 +87,8 @@ char *cmdopt[] = {
     "ARRAY",
     "INDGETS",
     "NUMOP",
-    "13"
+    "CCLASS",
+    "14"
 };
 #endif
 #endif /* DEBUGGING */
@@ -93,7 +100,13 @@ struct acmd {
 
 struct ccmd {
     CMD                *cc_true;       /* normal code to do on if and while */
-    CMD                *cc_alt;        /* else code or continue code */
+    CMD                *cc_alt;        /* else cmd ptr or continue code */
+};
+
+struct scmd {
+    CMD                **sc_next;      /* array of pointers to commands */
+    short      sc_offset;      /* first value - 1 */
+    short      sc_max;         /* last value + 1 */
 };
 
 struct cmd {
@@ -107,6 +120,7 @@ struct cmd {
     union ucmd {
        struct acmd acmd;       /* normal command */
        struct ccmd ccmd;       /* compound command */
+       struct scmd scmd;       /* switch command */
     } ucmd;
     short      c_slen;         /* len of c_short, if not null */
     short      c_flags;        /* optimization flags--see above */
@@ -120,11 +134,11 @@ struct cmd {
 EXT CMD *main_root INIT(Nullcmd);
 EXT CMD *eval_root INIT(Nullcmd);
 
-EXT struct compcmd {
+struct compcmd {
     CMD *comp_true;
     CMD *comp_alt;
 };
 
 void opt_arg();
 void evalstatic();
-STR *cmd_exec();
+int cmd_exec();
index bb9eb6b..a21a110 100644 (file)
--- a/config.H
+++ b/config.H
  *     This symbol, if defined, indicates that the program is running under
  *     VMS.  It is currently only set in conjunction with the EUNICE symbol.
  */
-#/*undef       EUNICE          /**/
-#/*undef       VMS             /**/
+/*#undef       EUNICE          /**/
+/*#undef       VMS             /**/
+
+/* BIN:
+ *     This symbol holds the name of the directory in which the user wants
+ *     to put publicly executable images for the package in question.  It
+ *     is most often a local directory such as /usr/local/bin.
+ */
+#define BIN "/usr/local/bin"             /**/
+
+/* BYTEORDER:
+ *     This symbol contains an encoding of the order of bytes in a long.
+ *     Usual values (in octal) are 01234, 04321, 02143, 03412...
+ */
+#define BYTEORDER 01234                /**/
+
+/* CPPSTDIN:
+ *     This symbol contains the first part of the string which will invoke
+ *     the C preprocessor on the standard input and produce to standard
+ *     output.  Typical value of "cc -E" or "/lib/cpp".
+ */
+/* CPPMINUS:
+ *     This symbol contains the second part of the string which will invoke
+ *     the C preprocessor on the standard input and produce to standard
+ *     output.  This symbol will have the value "-" if CPPSTDIN needs a minus
+ *     to specify standard input, otherwise the value is "".
+ */
+#define CPPSTDIN "/lib/cpp"
+#define CPPMINUS ""
+
+/* BCMP:
+ *     This symbol, if defined, indicates that the bcmp routine is available
+ *     to compare blocks of memory.  If undefined, use memcmp.  If that's
+ *     not available, roll your own.
+ */
+#define        BCMP            /**/
+
+/* BCOPY:
+ *     This symbol, if defined, indicates that the bcopy routine is available
+ *     to copy blocks of memory.  Otherwise you should probably use memcpy().
+ */
+#define        BCOPY           /**/
 
 /* CHARSPRINTF:
  *     This symbol is defined if this system declares "char *sprintf()" in
  */
 #define        CHARSPRINTF     /**/
 
+/* CRYPT:
+ *     This symbol, if defined, indicates that the crypt routine is available
+ *     to encrypt passwords and the like.
+ */
+#define        CRYPT           /**/
+
+/* DOSUID:
+ *     This symbol, if defined, indicates that the C program should
+ *     check the script that it is executing for setuid/setgid bits, and
+ *     attempt to emulate setuid/setgid on systems that have disabled
+ *     setuid #! scripts because the kernel can't do it securely.
+ *     It is up to the package designer to make sure that this emulation
+ *     is done securely.  Among other things, it should do an fstat on
+ *     the script it just opened to make sure it really is a setuid/setgid
+ *     script, it should make sure the arguments passed correspond exactly
+ *     to the argument on the #! line, and it should not trust any
+ *     subprocesses to which it must pass the filename rather than the
+ *     file descriptor of the script to be executed.
+ */
+#define DOSUID         /**/
+
+/* DUP2:
+ *     This symbol, if defined, indicates that the dup2 routine is available
+ *     to dup file descriptors.  Otherwise you should use dup().
+ */
+#define        DUP2            /**/
+
+/* FCHMOD:
+ *     This symbol, if defined, indicates that the fchmod routine is available
+ *     to change mode of opened files.  If unavailable, use chmod().
+ */
+#define        FCHMOD          /**/
+
+/* FCHOWN:
+ *     This symbol, if defined, indicates that the fchown routine is available
+ *     to change ownership of opened files.  If unavailable, use chown().
+ */
+#define        FCHOWN          /**/
+
+/* FCNTL:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include fcntl.h.
+ */
+#define        FCNTL           /**/
+
+/* FLOCK:
+ *     This symbol, if defined, indicates that the flock() routine is
+ *     available to do file locking.
+ */
+#define        FLOCK           /**/
+
+/* GETGROUPS:
+ *     This symbol, if defined, indicates that the getgroups() routine is
+ *     available to get the list of process groups.  If unavailable, multiple
+ *     groups are probably not supported.
+ */
+#define        GETGROUPS               /**/
+
+/* GETHOSTENT:
+ *     This symbol, if defined, indicates that the gethostent() routine is
+ *     available to lookup host names in some data base or other.
+ */
+#define        GETHOSTENT              /**/
+
+/* GETPGRP:
+ *     This symbol, if defined, indicates that the getpgrp() routine is
+ *     available to get the current process group.
+ */
+#define        GETPGRP         /**/
+
+/* GETPRIORITY:
+ *     This symbol, if defined, indicates that the getpriority() routine is
+ *     available to get a process's priority.
+ */
+#define        GETPRIORITY             /**/
+
+/* HTONS:
+ *     This symbol, if defined, indicates that the htons routine (and friends)
+ *     are available to do network order byte swapping.
+ */
+/* HTONL:
+ *     This symbol, if defined, indicates that the htonl routine (and friends)
+ *     are available to do network order byte swapping.
+ */
+/* NTOHS:
+ *     This symbol, if defined, indicates that the ntohs routine (and friends)
+ *     are available to do network order byte swapping.
+ */
+/* NTOHL:
+ *     This symbol, if defined, indicates that the ntohl routine (and friends)
+ *     are available to do network order byte swapping.
+ */
+#define        HTONS           /**/
+#define        HTONL           /**/
+#define        NTOHS           /**/
+#define        NTOHL           /**/
+
 /* index:
  *     This preprocessor symbol is defined, along with rindex, if the system
  *     uses the strchr and strrchr routines instead.
  *     This preprocessor symbol is defined, along with index, if the system
  *     uses the strchr and strrchr routines instead.
  */
-#/*undef       index strchr    /* cultural */
-#/*undef       rindex strrchr  /*  differences? */
+/*#undef       index strchr    /* cultural */
+/*#undef       rindex strrchr  /*  differences? */
+
+/* IOCTL:
+ *     This symbol, if defined, indicates that sys/ioctl.h exists and should
+ *     be included.
+ */
+#define        IOCTL           /**/
+
+/* KILLPG:
+ *     This symbol, if defined, indicates that the killpg routine is available
+ *     to kill process groups.  If unavailable, you probably should use kill
+ *     with a negative process number.
+ */
+#define        KILLPG          /**/
+
+/* MEMCMP:
+ *     This symbol, if defined, indicates that the memcmp routine is available
+ *     to compare blocks of memory.  If undefined, roll your own.
+ */
+#define        MEMCMP          /**/
+
+/* MEMCPY:
+ *     This symbol, if defined, indicates that the memcpy routine is available
+ *     to copy blocks of memory.  Otherwise you should probably use bcopy().
+ *     If neither is defined, roll your own.
+ */
+#define        MEMCPY          /**/
+
+/* MKDIR:
+ *     This symbol, if defined, indicates that the mkdir routine is available
+ *     to create directories.  Otherwise you should fork off a new process to
+ *     exec /bin/mkdir.
+ */
+#define        MKDIR           /**/
+
+/* NDBM:
+ *     This symbol, if defined, indicates that ndbm.h exists and should
+ *     be included.
+ */
+#define        NDBM            /**/
+
+/* ODBM:
+ *     This symbol, if defined, indicates that dbm.h exists and should
+ *     be included.
+ */
+#define        ODBM            /**/
+
+/* READDIR:
+ *     This symbol, if defined, indicates that the readdir routine is available
+ *     from the C library to create directories.
+ */
+#define        READDIR         /**/
+
+/* RENAME:
+ *     This symbol, if defined, indicates that the rename routine is available
+ *     to rename files.  Otherwise you should do the unlink(), link(), unlink()
+ *     trick.
+ */
+#define        RENAME          /**/
+
+/* RMDIR:
+ *     This symbol, if defined, indicates that the rmdir routine is available
+ *     to remove directories.  Otherwise you should fork off a new process to
+ *     exec /bin/rmdir.
+ */
+#define        RMDIR           /**/
+
+/* SETEGID:
+ *     This symbol, if defined, indicates that the setegid routine is available
+ *     to change the effective gid of the current program.
+ */
+#define        SETEGID         /**/
+
+/* SETEUID:
+ *     This symbol, if defined, indicates that the seteuid routine is available
+ *     to change the effective uid of the current program.
+ */
+#define        SETEUID         /**/
+
+/* SETPGRP:
+ *     This symbol, if defined, indicates that the setpgrp() routine is
+ *     available to set the current process group.
+ */
+#define        SETPGRP         /**/
+
+/* SETPRIORITY:
+ *     This symbol, if defined, indicates that the setpriority() routine is
+ *     available to set a process's priority.
+ */
+#define        SETPRIORITY             /**/
+
+/* SETREGID:
+ *     This symbol, if defined, indicates that the setregid routine is available
+ *     to change the real and effective gid of the current program.
+ */
+#define        SETREGID                /**/
+
+/* SETREUID:
+ *     This symbol, if defined, indicates that the setreuid routine is available
+ *     to change the real and effective uid of the current program.
+ */
+#define        SETREUID                /**/
+
+/* SETRGID:
+ *     This symbol, if defined, indicates that the setrgid routine is available
+ *     to change the real gid of the current program.
+ */
+#define        SETRGID         /**/
+
+/* SETRUID:
+ *     This symbol, if defined, indicates that the setruid routine is available
+ *     to change the real uid of the current program.
+ */
+#define        SETRUID         /**/
+
+/* SOCKET:
+ *     This symbol, if defined, indicates that the BSD socket interface is
+ *     supported.
+ */
+/* SOCKETPAIR:
+ *     This symbol, if defined, indicates that the BSD socketpair call is
+ *     supported.
+ */
+/* OLDSOCKET:
+ *     This symbol, if defined, indicates that the 4.1c BSD socket interface
+ *     is supported instead of the 4.2/4.3 BSD socket interface.
+ */
+#define        SOCKET          /**/
+
+#define        SOCKETPAIR      /**/
+
+/*#undef       OLDSOCKET       /**/
+
+/* STATBLOCKS:
+ *     This symbol is defined if this system has a stat structure declaring
+ *     st_blksize and st_blocks.
+ */
+#define        STATBLOCKS      /**/
+
+/* STDSTDIO:
+ *     This symbol is defined if this system has a FILE structure declaring
+ *     _ptr and _cnt in stdio.h.
+ */
+#define        STDSTDIO        /**/
 
 /* STRUCTCOPY:
  *     This symbol, if defined, indicates that this C compiler knows how
  */
 #define        STRUCTCOPY      /**/
 
+/* SYMLINK:
+ *     This symbol, if defined, indicates that the symlink routine is available
+ *     to create symbolic links.
+ */
+#define        SYMLINK         /**/
+
+/* SYSCALL:
+ *     This symbol, if defined, indicates that the syscall routine is available
+ *     to call arbitrary system calls.  If undefined, that's tough.
+ */
+#define        SYSCALL         /**/
+
+/* TMINSYS:
+ *     This symbol is defined if this system declares "struct tm" in
+ *     in <sys/time.h> rather than <time.h>.  We can't just say
+ *     -I/usr/include/sys because some systems have both time files, and
+ *     the -I trick gets the wrong one.
+ */
+/* I_SYSTIME:
+ *     This symbol is defined if this system has the file <sys/time.h>.
+ */
+/*#undef       TMINSYS         /**/
+#define        I_SYSTIME       /**/
+
+/* VARARGS:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include varargs.h.
+ */
+#define        VARARGS         /**/
+
 /* vfork:
  *     This symbol, if defined, remaps the vfork routine to fork if the
  *     vfork() routine isn't supported here.
  */
-#/*undef       vfork fork      /**/
+/*#undef       vfork fork      /**/
+
+/* VOIDSIG:
+ *     This symbol is defined if this system declares "void (*signal())()" in
+ *     signal.h.  The old way was to declare it as "int (*signal())()".  It
+ *     is up to the package author to declare things correctly based on the
+ *     symbol.
+ */
+/*#undef       VOIDSIG         /**/
+
+/* VPRINTF:
+ *     This symbol, if defined, indicates that the vprintf routine is available
+ *     to printf with a pointer to an argument list.  If unavailable, you
+ *     may need to write your own, probably in terms of _doprnt().
+ */
+/* CHARVSPRINTF:
+ *     This symbol is defined if this system has vsprintf() returning type
+ *     (char*).  The trend seems to be to declare it as "int vsprintf()".  It
+ *     is up to the package author to declare vsprintf correctly based on the
+ *     symbol.
+ */
+/*#undef       VPRINTF         /**/
+/*#undef       CHARVSPRINTF    /**/
+
+/* GIDTYPE:
+ *     This symbol has a value like gid_t, int, ushort, or whatever type is
+ *     used to declare group ids in the kernel.
+ */
+#define GIDTYPE gid_t          /**/
+
+/* I_DIRENT:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include dirent.h.
+ */
+/* DIRNAMLEN:
+ *     This symbol, if defined, indicates to the C program that the length
+ *     of directory entry names is provided by a d_namlen field.  Otherwise
+ *     you need to do strlen() on the d_name field.
+ */
+/*#undef       I_DIRENT                /**/
+#define        DIRNAMLEN               /**/
+
+/* I_FCNTL:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include fcntl.h.
+ */
+#define        I_FCNTL         /**/
+
+/* I_GRP:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include grp.h.
+ */
+#define        I_GRP           /**/
+
+/* I_PWD:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include pwd.h.
+ */
+/* PWQUOTA:
+ *     This symbol, if defined, indicates to the C program that struct passwd
+ *     contains pw_quota.
+ */
+/* PWAGE:
+ *     This symbol, if defined, indicates to the C program that struct passwd
+ *     contains pw_age.
+ */
+#define        I_PWD           /**/
+#define        PWQUOTA         /**/
+/*#undef       PWAGE           /**/
+
+/* I_SYSDIR:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include sys/dir.h.
+ */
+#define        I_SYSDIR                /**/
+
+/* I_SYSIOCTL:
+ *     This symbol, if defined, indicates that sys/ioctl.h exists and should
+ *     be included.
+ */
+#define        I_SYSIOCTL              /**/
+
+/* I_VARARGS:
+ *     This symbol, if defined, indicates to the C program that it should
+ *     include varargs.h.
+ */
+#define        I_VARARGS               /**/
+
+/* INTSIZE:
+ *     This symbol contains the size of an int, so that the C preprocessor
+ *     can make decisions based on it.
+ */
+#define INTSIZE 4              /**/
+
+/* RANDBITS:
+ *     This symbol contains the number of bits of random number the rand()
+ *     function produces.  Usual values are 15, 16, and 31.
+ */
+#define RANDBITS 31            /**/
+
+/* SIG_NAME:
+ *     This symbol contains an list of signal names in order.
+ */
+#define SIG_NAME "ZERO","HUP","INT","QUIT","ILL","TRAP","IOT","EMT","FPE","KILL","BUS","SEGV","SYS","PIPE","ALRM","TERM","URG","STOP","TSTP","CONT","CHLD","TTIN","TTOU","IO","XCPU","XFSZ","VTALRM","PROF","WINCH","USR1","USR2"              /**/
+
+/* STDCHAR:
+ *     This symbol is defined to be the type of char used in stdio.h.
+ *     It has the values "unsigned char" or "char".
+ */
+#define STDCHAR char   /**/
+
+/* UIDTYPE:
+ *     This symbol has a value like uid_t, int, ushort, or whatever type is
+ *     used to declare user ids in the kernel.
+ */
+#define UIDTYPE uid_t          /**/
 
 /* VOIDFLAGS:
  *     This symbol indicates how much support of the void type is given by this
  *     The package designer should define VOIDUSED to indicate the requirements
  *     of the package.  This can be done either by #defining VOIDUSED before
  *     including config.h, or by defining defvoidused in Myinit.U.  If the
+ *     latter approach is taken, only those flags will be tested.  If the
  *     level of void support necessary is not present, defines void to int.
  */
 #ifndef VOIDUSED
 #define M_VOID         /* Xenix strikes again */
 #endif
 
+/* PRIVLIB:
+ *     This symbol contains the name of the private library for this package.
+ *     The library is private in the sense that it needn't be in anyone's
+ *     execution path, but it should be accessible by the world.  The program
+ *     should be prepared to do ~ expansion.
+ */
+#define PRIVLIB "/usr/local/lib/perl"          /**/
+
index bb4b62b..5cf8ad1 100644 (file)
@@ -37,6 +37,19 @@ sed <<!GROK!THIS! >config.h -e 's!^#undef!/\*#undef!'
 #$d_eunice     EUNICE          /**/
 #$d_eunice     VMS             /**/
 
+/* BIN:
+ *     This symbol holds the name of the directory in which the user wants
+ *     to put publicly executable images for the package in question.  It
+ *     is most often a local directory such as /usr/local/bin.
+ */
+#define BIN "$bin"             /**/
+
+/* BYTEORDER:
+ *     This symbol contains an encoding of the order of bytes in a long.
+ *     Usual values (in octal) are 01234, 04321, 02143, 03412...
+ */
+#define BYTEORDER 0$byteorder          /**/
+
 /* CPPSTDIN:
&nb