[comp.sources.bugs] perl 3.0 patch #29

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (10/17/90)

System: perl version 3.0
Patch #: 29
Priority: HIGH
Subject: added SysV IPC
Subject: added waitpid
Subject: various portability fixes
Subject: added cmp and <=>
Subject: added caller
Subject: added scalar
Subject: added sysread and syswrite
Subject: added -M, -A and -C
Subject: index and substr now have optional 3rd args
Subject: you can now read into the middle string
Subject: non-existent array values no longer cause core dumps
Subject: scripts now run at almost full speed under the debugger
Subject: @ENV = () now works
Subject: defined @foo was behaving inconsistently
Subject: -5 % 5 was wrong
Subject: package behavior is now more consistent
Subject: tr/// now understands c, d and s options, and handles nulls right
Subject: *foo now prints as *package'foo
Subject: local() without initialization now creates undefined values
Subject: file - didn't auto-close cleanly
Subject: close; core dumped
Subject: more MSDOS and OS/2 updates, from Kai Uwe Rommel
Subject: added scalar reverse
Subject: sort undefined_subroutine @array is now a fatal error
Subject: ~ now works on vector string
Subject: eof; core dumped
Subject: oct and hex now produce unsigned result
Subject: unshift did not return the documented value
Subject: added @###.## fields to format
Subject: h2ph didn't translate includes right
Subject: %foo = () will now clear dbm files
Subject: dbm files couldn't be opened read only
Subject: the cache array for dbm files wasn't correctly created on fetches
Subject: the debugger now understands packages and evals
Subject: more variables are settable from debugger
Subject: some machines didn't like unsigned C preprocessor values
Subject: added DATA filehandle to read stuff after __END__
Subject: -w sometimes printed spurious warnings about ARGV and ENV
Subject: require "./foo" didn't work right
Subject: require error messages referred to wrong file
Subject: patterns with multiple short literal strings sometimes failed
Subject: /^pat/ occasionally matched in middle of string when $* = 0
Subject: /.{n,m}$/ could match with fewer than n characters remaining
Subject: /\d{9}/ could match more than 9 characters
Subject: taintperl now checks for world writable PATH components
Subject: the undefined value could get defined by devious means
Subject: undefined values compared inconsistently 
Subject: op.stat could fail if /bin/0 existed
Subject: the length of a search pattern was limited
Subject: 0x80000000 now makes unsigned value
Subject: Null could not be used as a delimiter
Subject: usub/mus had str_set where it needed str_nset
Subject: s2p modernized
Subject: removed #ifdef undef
Subject: a2p mistranslated certain weird field separators

Description:
	This set of patches pretty much brings you up to the functionality
	that version 4.0 will have.  The Perl Book documents version 4.0.

	Perhaps these should be called release notes...   :-)

    Enhancements:

	Many of the changes relate to making the debugger work better.
	It now runs your scripts at nearly full speed because it no longer
	calls a subroutine on every statement.  The debugger now doesn't
	get confused about packages, evals and other filenames.  More
	variables (though still not all) are available within the debugger.

	Related to this is the fact that every statement now knows which
	package and filename it was compiled in, so package semantics are
	now much more straightforward.  Every variable also knows which
	package it was compiled in.  So many places that used to print
	out just the variable name now prefix the variable name with the
	package name.  Notably, if you print *foo it now gives *package'foo.

	Along with these, there is now a "caller" function which returns
	the context of the current subroutine call.  See the man page for
	more details.

	Chip Salzenberg sent the patches for System V IPC (msg, sem and shm)
	so I dropped them in.

	There was no way to wait for a specific pid, which was silly, since
	Perl was already keeping track of the information.  So I added
	the waitpid() call, which uses Unix's wait4() or waitpid() if
	available, and otherwise emulates them (at least as far as letting
	you wait for a particular pid--it doesn't emulate non-blocking wait).

	For use in sorting routines, there are now two new operators,
	cmp and <=>.  These do string and numeric comparison, returning
	-1, 0 or 1 when the first argument is less than, equal to or
	greater than the second argument.

	Occasionally one finds that one wants to evaluate an operator in
	a scalar context, even though it's part of a LIST.  For this purpose,
	there is now a scalar() operator.  For instance, the approved
	fix for the novice error of using <> in assigning to a local is now:

		local($var) = scalar(<STDIN>);

	Perl's ordinary I/O is done using standard I/O routines.  Every
	now and then this gets in your way.  You may now access the system
	calls read() and write() via the Perl functions sysread() and
	syswrite().  They should not be intermixed with ordinary I/O calls
	unless you know what you're doing.

	Along with this, both the sysread() and read() functions allow you
	an optional 4th argument giving an offset into the string you're
	reading into, so for instance you can easily finish up partial reads.

	As a bit of syntactic sugar, you can now use the file tests -M, -A
	and -C to determine the age of a file in (possibly fractional) days
	as of the time the script started running.  This makes it much
	easier to write midnight cleanup scripts with precision.

	The index() and rindex() functions now have an optional 3rd argument
	which tells it where to start looking, so you can now iterate through
	a string using these functions.

	The substr() function's 3rd argument is now optional, and if omitted,
	the function returns everything to the end of the string.

	The tr/// translation function now understands c, d and s options, just
	like the tr program.  (Well, almost just like.  The d option only
	deletes characters that aren't in the replacement string.)  The
	c complementes the character class to match and the s option squishes
	out multiple occurrences of any replacement class characters.

	The reverse function, used in a scalar context, now reverses its
	scalar argument as a string.

	Dale Worley posted a patch to add @###.## type fields to formats.
	I said, "Neat!" and dropped it in, lock, stock and sinker.

	Kai Uwe Rommel sent a bunch of MSDOS and OS/2 updates, which I (mostly)
	incorporated.  I can't vouch for them, but they look okay.

	Any data stored after the __END__ marker can be accesses now via
	the DATA filehandle, which is automatically opened onto the script
	at that point.  (Well, actually, it's just kept open, since it
	was already open to read the script.)

	The taintperl program now checks for world writable PATH components,
	and complains if any are found (if PATH is used).

    Bug fixes:

	It used to be that you could get core dumps by such means as

	    @$foo=();
	    @foo[42];

	    (1,2,3)[42];

	    $#foo = 50;
	    foreach $elem (@foo) {
		$elem = 1;
	    }

	This is no longer so.  (For those who are up on Perl internals, the
	stack policy no longer allows Nullstr--all undefined values must
	be passed as &str_undef.)

	If you say something like

		local($foo,$bar);
	
	or

		local($initialized,$foo,$bar) = ('one value');

	$foo and $bar are now initialized to the undefined value, rather
	than the defined null string.

	Array assignment to special arrays is now better supported.  For
	instance, @ENV = () clears the environment, and %foo = () will
	now clear any dbm file bound to %foo.

	On the subject of dbm files, the highly visible bugs at patchlevel
	28 have been fixed.  You can now open dbm files readonly, and you
	don't have to do a dummy assignment to make the cache allocate itself.

	The modulus operator wasn't working right on negative values because
	of a misplaced cast.  For instance, -5 % 5 was returning
	the value 5, which is clearly wrong.

	Certain operations coredumped if you didn't supply a value:
	
		close;
		eof;

	Previously, if the subroutine supplied for a sort operation didn't
	exist, it failed quietly.  Now it produces a fatal error.

	The bitwise complement operator ~ didn't work on vec() strings longer
	than one byte because of failure to increment a loop variable.

	The oct and hex functions returned a negative result if the highest
	bit was set.  They now return an unsigned result, which seems a
	little less confusing.  Likewise, the token 0x80000000 also produces
	an unsigned value now.

	Some machines didn't like to see 0x87654321 in an #ifdef because
	they think of the symbols as signed.  The tests have been changed
	to just look at the lower 4 nybbles of the value, which is sufficient
	to determine endianness, at least as far as the #ifdefs are concerned.

	The unshift operator did not return the documented value, which
	was the number of elements in the new array.  Instead it returned
	the last unshifted argument, more or less by accident.

	-w sometimes printed spurious warnings about ARGV and ENV when
	referencing the arrays indirectly through shift or exec.  This
	was because the typo test was misplaced before the code that
	exempts special variables from the typo test.

	If you said 'require "./foo.pl"', it would look in someplace like
	/usr/local/lib/perl/./foo.pl instead of the current directory.  This
	works more like people expect now.  The require error messages also
	referred to wrong file, if they worked at all.

	The h2ph program didn't translate includes right--it should have
	changed .h to .ph.

	Patterns with multiple short literal strings sometimes failed.
	This was a problem with the code that looks for a maximal literal
	string to feed to the Boyer-Moore searching routine.  The code
	was gluing together literal strings that weren't continuous.

	The $* variable controls multi-line pattern matching.  When it's
	0, patterns are supposed to match as if the string contained a
	single line.  Unfortunately, /^pat/ occasionally matched in middle
	of string under certain conditions.

	Recently the regular expression routines were upgraded to do
	{n,m} more efficiently.  In doing this, however, I manufactured
	a couple of bugs: /.{n,m}$/ could match with fewer than n characters
	remaining on the line, and patterns like /\d{9}/ could match more
	than 9 characters.

	The undefined value has an actual physical location in Perl, and
	pointers to it are passed around.  By certain circuitous routes
	it was possible to clobber the undefined value so that it
	was no longer undefined--kind of like making /dev/null into
	a real file.  Hopefully this can't happen any more.

	op.stat could fail if /bin/0 existed, because of a while (<*>) {...
	This has been changed to a while (defined($_ = <*>)) {...

	The length of a search pattern was limited by the length of
	tokenbuf internally.  This restriction has been removed.

	The null character gave the tokener indigestion when used as
	a delimiter for m// or s///.

	There was a bunch of other cleanupish things that are too trivial
	to mention here.


Fix:	From rn, say "| patch -p -N -d DIR", where DIR is your perl source
	directory.  Outside of rn, say "cd DIR; patch -p -N <thisarticle".
	If you don't have the patch program, apply the following by hand,
	or get patch (version 2.0, latest patchlevel).

	After patching:
		*** DO NOTHING--INSTALL ALL PATCHES UP THROUGH #36 FIRST ***

	If patch indicates that patchlevel is the wrong version, you may need
	to apply one or more previous patches, or the patch may already
	have been applied.  See the patchlevel.h file to find out what has or
	has not been applied.  In any event, don't continue with the patch.

	If you are missing previous patches they can be obtained from me:

	Larry Wall
	lwall@jpl-devvax.jpl.nasa.gov

	If you send a mail message of the following form it will greatly speed
	processing:

	Subject: Command
	@SH mailpatch PATH perl 3.0 LIST
		   ^ note the c

	where PATH is a return path FROM ME TO YOU either in Internet notation,
	or in bang notation from some well-known host, and LIST is the number
	of one or more patches you need, separated by spaces, commas, and/or
	hyphens.  Saying 35- says everything from 35 to the end.


	You can also get the patches via anonymous FTP from
	jpl-devvax.jpl.nasa.gov (128.149.1.143).

Index: patchlevel.h
Prereq: 28
1c1
< #define PATCHLEVEL 28
---
> #define PATCHLEVEL 29

Index: Configure
Prereq: 3.0.1.9
*** Configure.old	Tue Oct 16 11:44:13 1990
--- Configure	Tue Oct 16 11:44:29 1990
***************
*** 8,14 ****
  # 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 3.0.1.9 90/08/13 21:48:46 lwall Locked $
  #
  # Yes, you may rip this off to use in other distribution packages.
  # (Note: this Configure script was generated automatically.  Rather than
--- 8,14 ----
  # 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 3.0.1.10 90/10/15 14:37:52 lwall Locked $
  #
  # Yes, you may rip this off to use in other distribution packages.
  # (Note: this Configure script was generated automatically.  Rather than
***************
*** 15,21 ****
  # working with this copy of Configure, you may wish to get metaconfig.)
  
  : sanity checks
! PATH=".:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc:/usr/new:/usr/new/bin:/usr/nbin:$PATH"
  export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh $0; kill $$)
  
  if test ! -t 0; then
--- 15,21 ----
  # working with this copy of Configure, you may wish to get metaconfig.)
  
  : sanity checks
! PATH="$PATH:.:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc:/usr/new:/usr/new/bin:/usr/nbin"
  export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh $0; kill $$)
  
  if test ! -t 0; then
***************
*** 154,159 ****
--- 154,160 ----
  d_strerror=''
  d_symlink=''
  d_syscall=''
+ d_sysvipc=''
  d_truncate=''
  d_varargs=''
  d_vfork=''
***************
*** 162,167 ****
--- 163,169 ----
  d_vprintf=''
  d_charvspr=''
  d_wait4=''
+ d_waitpid=''
  gidtype=''
  i_dirent=''
  d_dirnamlen=''
***************
*** 169,174 ****
--- 171,177 ----
  i_grp=''
  i_niin=''
  i_pwd=''
+ d_pwcomment=''
  d_pwquota=''
  d_pwage=''
  d_pwchange=''
***************
*** 232,238 ****
  undef='undef'
  : change the next line if compiling for Xenix/286 on Xenix/386
  xlibpth='/usr/lib/386 /lib/386'
! libpth='/usr/lib /usr/local/lib /usr/lib/large /lib '$xlibpth' /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
--- 235,241 ----
  undef='undef'
  : change the next line if compiling for Xenix/286 on Xenix/386
  xlibpth='/usr/lib/386 /lib/386'
! libpth='/usr/ccs/lib /usr/lib /usr/local/lib /usr/lib/large /lib '$xlibpth' /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
***************
*** 259,269 ****
  attrlist="$attrlist nsc32000 sinix xenix venix posix ansi M_XENIX"
  attrlist="$attrlist $mc68k __STDC__ UTS M_I8086 M_I186 M_I286 M_I386"
  attrlist="$attrlist i186 __m88k__ m88k DGUX __DGUX__"
! 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
  libswanted="net_s net nsl_s nsl socket nm ndir ndbm dbm sun m bsd BSD x c_s"
  inclwanted='/usr/netinclude /usr/include/sun /usr/include/bsd /usr/include/lan'
  : some greps do not return status, grrr.
  echo "grimblepritz" >grimble
  if grep blurfldyick grimble >/dev/null 2>&1 ; then
--- 262,273 ----
  attrlist="$attrlist nsc32000 sinix xenix venix posix ansi M_XENIX"
  attrlist="$attrlist $mc68k __STDC__ UTS M_I8086 M_I186 M_I286 M_I386"
  attrlist="$attrlist i186 __m88k__ m88k DGUX __DGUX__"
! pth="/usr/ccs/bin /bin /usr/bin /usr/ucb /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
  libswanted="net_s net nsl_s nsl socket nm ndir ndbm dbm sun m bsd BSD x c_s"
  inclwanted='/usr/netinclude /usr/include/sun /usr/include/bsd /usr/include/lan'
+ 
  : some greps do not return status, grrr.
  echo "grimblepritz" >grimble
  if grep blurfldyick grimble >/dev/null 2>&1 ; then
***************
*** 1126,1132 ****
      *) thatlib="${thislib}_s";;
      *) thatlib=NONE;;
      esac
!     xxx=`loc lib$thislib.a X /usr/lib /usr/local/lib /lib`
      if test -f $xxx; then
  	echo "Found -l$thislib."
  	case "$dflt" in
--- 1130,1136 ----
      *) thatlib="${thislib}_s";;
      *) thatlib=NONE;;
      esac
!     xxx=`loc lib$thislib.a X /usr/ccs/lib /usr/lib /usr/local/lib /lib`
      if test -f $xxx; then
  	echo "Found -l$thislib."
  	case "$dflt" in
***************
*** 1274,1298 ****
      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...'
--- 1278,1302 ----
      cppstdin="$cc -E"
      cppminus='';
  else
!     echo 'Nope...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 '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 "'$cpp' -" will work...'
! 	    $cpp - <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="$cpp"
  		cppminus='-';
  	    else
  		echo 'Nope...maybe "'"$cc"' -P" will work...'
***************
*** 1357,1363 ****
  '') libc=unknown;;
  esac
  case "$libpth" in
! '') libpth='/lib /usr/lib /usr/local/lib';;
  esac
  case "$libs" in
  *-lc_s*) libc=`loc libc_s.a $libc $libpth`
--- 1361,1367 ----
  '') libc=unknown;;
  esac
  case "$libpth" in
! '') libpth='/usr/ccs/lib /lib /usr/lib /usr/local/lib';;
  esac
  case "$libs" in
  *-lc_s*) libc=`loc libc_s.a $libc $libpth`
***************
*** 1388,1394 ****
      done
      ;;
  esac
! set /usr/lib/libc.so.[0-9]*
  eval set \$$#
  if test -f "$1"; then
      echo "Your shared C library is in $1."
--- 1392,1400 ----
      done
      ;;
  esac
! set /usr/ccs/lib/libc.so
! test -f $1 || set /usr/lib/libc.so
! test -f $1 || set /usr/lib/libc.so.[0-9]*
  eval set \$$#
  if test -f "$1"; then
      echo "Your shared C library is in $1."
***************
*** 1440,1446 ****
  set `echo $libc $libnames | tr ' ' '\012' | sort | uniq`
  $echo $n "Extracting names from $* for later perusal...$c"
  nm $* 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
--- 1446,1452 ----
  set `echo $libc $libnames | tr ' ' '\012' | sort | uniq`
  $echo $n "Extracting names from $* for later perusal...$c"
  nm $* 2>/dev/null >libc.tmp
! $sed -n -e 's/^.* [ATD]  *_[_.]*//p' -e 's/^.* [ATD] //p' <libc.tmp >libc.list
  if $contains '^printf$' libc.list >/dev/null 2>&1; then
      echo "done"
  else
***************
*** 1453,1459 ****
         $sed -n -e 's/^_//' \
  	      -e 's/^\([a-zA-Z_0-9]*\).*xtern.*text.*/\1/p' <libc.tmp >libc.list
      $contains '^printf$' libc.list >/dev/null 2>&1 || \
! 	$sed -n -e 's/^.*|FUNC |GLOB .*|//p' <libc.tmp >libc.list
      if $contains '^printf$' libc.list >/dev/null 2>&1; then
  	echo "done"
      else
--- 1459,1466 ----
         $sed -n -e 's/^_//' \
  	      -e 's/^\([a-zA-Z_0-9]*\).*xtern.*text.*/\1/p' <libc.tmp >libc.list
      $contains '^printf$' libc.list >/dev/null 2>&1 || \
! 	$sed -n -e 's/^.*|FUNC |GLOB .*|//p' -e 's/^.*|FUNC |WEAK .*|//p' \
! 	   <libc.tmp >libc.list
      if $contains '^printf$' libc.list >/dev/null 2>&1; then
  	echo "done"
      else
***************
*** 1860,1866 ****
  if $test -r /usr/include/pwd.h ; then
      i_pwd="$define"
      echo "pwd.h found."
!     $cppstdin $cppflags </usr/include/pwd.h >$$.h
      if $contains 'pw_quota' $$.h >/dev/null 2>&1; then
  	d_pwquota="$define"
      else
--- 1867,1878 ----
  if $test -r /usr/include/pwd.h ; then
      i_pwd="$define"
      echo "pwd.h found."
!     $cppstdin $cppflags $cppminus </usr/include/pwd.h >$$.h
!     if $contains 'pw_comment' $$.h >/dev/null 2>&1; then
! 	d_pwcomment="$define"
!     else
! 	d_pwcomment="$undef"
!     fi
      if $contains 'pw_quota' $$.h >/dev/null 2>&1; then
  	d_pwquota="$define"
      else
***************
*** 1889,1894 ****
--- 1901,1907 ----
      rm -f $$.h
  else
      i_pwd="$undef"
+     d_pwcomment="$undef"
      d_pwquota="$undef"
      d_pwage="$undef"
      d_pwchange="$undef"
***************
*** 2083,2088 ****
--- 2096,2105 ----
  esac
  $rm -f try.c try
  
+ : see if there is System V IPC
+ set msgget d_sysvipc
+ eval $inlibc
+ 
  : see if truncate exists
  set truncate d_truncate
  eval $inlibc
***************
*** 2103,2109 ****
  
  : see if signal is declared as pointer to function returning int or void
  echo " "
! $cppstdin $cppflags < /usr/include/signal.h >$$.tmp
  if $contains 'void.*signal' $$.tmp >/dev/null 2>&1 ; then
      echo "You have void (*signal())() instead of int."
      d_voidsig="$define"
--- 2120,2126 ----
  
  : see if signal is declared as pointer to function returning int or void
  echo " "
! $cppstdin $cppflags $cppminus < /usr/include/signal.h >$$.tmp
  if $contains 'void.*signal' $$.tmp >/dev/null 2>&1 ; then
      echo "You have void (*signal())() instead of int."
      d_voidsig="$define"
***************
*** 2139,2144 ****
--- 2156,2165 ----
  set wait4 d_wait4
  eval $inlibc
  
+ : see if there is a waitpid
+ set waitpid d_waitpid
+ eval $inlibc
+ 
  : check for void type
  echo " "
  $cat <<EOM
***************
*** 2494,2500 ****
  Log='$Log'
  Header='$Header'
  
- 
  : determine which malloc to compile in
  echo " "
  case "$usemymalloc" in
--- 2515,2520 ----
***************
*** 2709,2714 ****
--- 2729,2735 ----
  d_strerror='$d_strerror'
  d_symlink='$d_symlink'
  d_syscall='$d_syscall'
+ d_sysvipc='$d_sysvipc'
  d_truncate='$d_truncate'
  d_varargs='$d_varargs'
  d_vfork='$d_vfork'
***************
*** 2717,2722 ****
--- 2738,2744 ----
  d_vprintf='$d_vprintf'
  d_charvspr='$d_charvspr'
  d_wait4='$d_wait4'
+ d_waitpid='$d_waitpid'
  gidtype='$gidtype'
  i_dirent='$i_dirent'
  d_dirnamlen='$d_dirnamlen'
***************
*** 2724,2729 ****
--- 2746,2752 ----
  i_grp='$i_grp'
  i_niin='$i_niin'
  i_pwd='$i_pwd'
+ d_pwcomment='$d_pwcomment'
  d_pwquota='$d_pwquota'
  d_pwage='$d_pwage'
  d_pwchange='$d_pwchange'

Index: Makefile.SH
Prereq: 3.0.1.8
*** Makefile.SH.old	Tue Oct 16 11:44:49 1990
--- Makefile.SH	Tue Oct 16 11:44:55 1990
***************
*** 25,33 ****
  
  echo "Extracting Makefile (with variable substitutions)"
  cat >Makefile <<!GROK!THIS!
! # $Header: Makefile.SH,v 3.0.1.8 90/08/13 21:50:49 lwall Locked $
  #
  # $Log:	Makefile.SH,v $
  # Revision 3.0.1.8  90/08/13  21:50:49  lwall
  # patch28: not all yaccs are the same
  # 
--- 25,36 ----
  
  echo "Extracting Makefile (with variable substitutions)"
  cat >Makefile <<!GROK!THIS!
! # $Header: Makefile.SH,v 3.0.1.9 90/10/15 14:41:34 lwall Locked $
  #
  # $Log:	Makefile.SH,v $
+ # Revision 3.0.1.9  90/10/15  14:41:34  lwall
+ # patch29: various portability fixes
+ # 
  # Revision 3.0.1.8  90/08/13  21:50:49  lwall
  # patch28: not all yaccs are the same
  # 
***************
*** 69,74 ****
--- 72,78 ----
  manext = $manext
  CFLAGS = $ccflags $optimize
  LDFLAGS = $ldflags
+ CLDFLAGS = $ldflags
  SMALL = $small
  LARGE = $large $split
  mallocsrc = $mallocsrc
***************
*** 75,81 ****
  mallocobj = $mallocobj
  SLN = $sln
  
! libs = $libs -lm
  
  public = perl taintperl $suidperl
  
--- 79,85 ----
  mallocobj = $mallocobj
  SLN = $sln
  
! libs = $libs
  
  public = perl taintperl $suidperl
  
***************
*** 101,107 ****
  
  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)
  
--- 105,111 ----
  
  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 usersub.c
  
  c = $(c1) $(c2) $(c3)
  
***************
*** 135,144 ****
  # used for all scripts that aren't set-id or running under something set-id.
  
  perl: perl.o $(obj) usersub.o
! 	$(CC) $(LARGE) $(LDFLAGS) $(obj) perl.o usersub.o $(libs) -o perl
  
  uperl.o: perl.o $(obj)
! 	ld $(LARGE) $(LDFLAGS) -r $(obj) perl.o $(libs) -o uperl.o
  
  saber: perl.c
  	# load $(c) perl.c
--- 139,148 ----
  # used for all scripts that aren't set-id or running under something set-id.
  
  perl: perl.o $(obj) usersub.o
! 	$(CC) $(LARGE) $(CLDFLAGS) $(obj) perl.o usersub.o $(libs) -o perl
  
  uperl.o: perl.o $(obj)
! 	-ld $(LARGE) $(LDFLAGS) -r $(obj) perl.o $(libs) -o uperl.o
  
  saber: perl.c
  	# load $(c) perl.c
***************
*** 149,155 ****
  # has been invoked correctly.
  
  suidperl: tperl.o sperly.o $(tobj) usersub.o
! 	$(CC) $(LARGE) $(LDFLAGS) sperly.o $(tobj) tperl.o usersub.o $(libs) \
  	    -o suidperl
  
  # This version interprets scripts that are already set-id either via a wrapper
--- 153,159 ----
  # has been invoked correctly.
  
  suidperl: tperl.o sperly.o $(tobj) usersub.o
! 	$(CC) $(LARGE) $(CLDFLAGS) sperly.o $(tobj) tperl.o usersub.o $(libs) \
  	    -o suidperl
  
  # This version interprets scripts that are already set-id either via a wrapper
***************
*** 158,164 ****
  # and normal perl is the presence of the "taint" checks.
  
  taintperl: tperl.o tperly.o $(tobj) usersub.o
! 	$(CC) $(LARGE) $(LDFLAGS) tperly.o $(tobj) tperl.o usersub.o $(libs) \
  	    -o taintperl
  
  # Replicating all this junk is yucky, but I don't see a portable way to fix it.
--- 162,168 ----
  # and normal perl is the presence of the "taint" checks.
  
  taintperl: tperl.o tperly.o $(tobj) usersub.o
! 	$(CC) $(LARGE) $(CLDFLAGS) tperly.o $(tobj) tperl.o usersub.o $(libs) \
  	    -o taintperl
  
  # Replicating all this junk is yucky, but I don't see a portable way to fix it.
***************
*** 349,357 ****
  	rm -f *.o all perl taintperl suidperl perl.man
  	cd x2p; $(MAKE) clean
  
! realclean:
  	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
  
--- 353,361 ----
  	rm -f *.o all perl taintperl suidperl perl.man
  	cd x2p; $(MAKE) clean
  
! realclean: clean
  	cd x2p; $(MAKE) realclean
! 	rm -f *.orig */*.orig *~ */*~ core $(addedbyconf) h2ph h2ph.man
  	rm -f perl.c perly.h t/perl Makefile config.h makedepend makedir
  	rm -f x2p/Makefile
  

Index: x2p/Makefile.SH
Prereq: 3.0.1.5
*** x2p/Makefile.SH.old	Tue Oct 16 12:06:09 1990
--- x2p/Makefile.SH	Tue Oct 16 12:06:10 1990
***************
*** 18,26 ****
  esac
  echo "Extracting x2p/Makefile (with variable substitutions)"
  cat >Makefile <<!GROK!THIS!
! # $Header: Makefile.SH,v 3.0.1.5 90/08/13 22:41:05 lwall Locked $
  #
  # $Log:	Makefile.SH,v $
  # Revision 3.0.1.5  90/08/13  22:41:05  lwall
  # patch28: shift/reduce count was off for a2p's Makefile
  # 
--- 18,29 ----
  esac
  echo "Extracting x2p/Makefile (with variable substitutions)"
  cat >Makefile <<!GROK!THIS!
! # $Header: Makefile.SH,v 3.0.1.6 90/10/16 11:28:18 lwall Locked $
  #
  # $Log:	Makefile.SH,v $
+ # Revision 3.0.1.6  90/10/16  11:28:18  lwall
+ # patch29: various portability fixes
+ # 
  # Revision 3.0.1.5  90/08/13  22:41:05  lwall
  # patch28: shift/reduce count was off for a2p's Makefile
  # 
***************
*** 63,69 ****
  mallocsrc = $mallocsrc
  mallocobj = $mallocobj
  
! libs = $libs -lm
  !GROK!THIS!
  
  cat >>Makefile <<'!NO!SUBS!'
--- 66,72 ----
  mallocsrc = $mallocsrc
  mallocobj = $mallocobj
  
! libs = $libs
  !GROK!THIS!
  
  cat >>Makefile <<'!NO!SUBS!'
***************
*** 105,111 ****
  	$(YACC) a2p.y
  	mv y.tab.c a2p.c
  
! a2p.o: a2p.c a2py.c a2p.h EXTERN.h util.h INTERN.h handy.h ../config.h
  	$(CC) -c $(CFLAGS) $(LARGE) a2p.c
  
  install: a2p s2p
--- 108,114 ----
  	$(YACC) a2p.y
  	mv y.tab.c a2p.c
  
! a2p.o: a2p.c a2py.c a2p.h EXTERN.h util.h INTERN.h handy.h ../config.h str.h hash.h
  	$(CC) -c $(CFLAGS) $(LARGE) a2p.c
  
  install: a2p s2p
***************
*** 137,144 ****
  clean:
  	rm -f *.o
  
! realclean:
! 	rm -f a2p *.orig */*.orig *.o core $(addedbyconf)
  
  # The following lint has practically everything turned on.  Unfortunately,
  # you have to wade through a lot of mumbo jumbo that can't be suppressed.
--- 140,147 ----
  clean:
  	rm -f *.o
  
! realclean: clean
! 	rm -f a2p *.orig */*.orig core $(addedbyconf) a2p.c s2p all
  
  # The following lint has practically everything turned on.  Unfortunately,
  # you have to wade through a lot of mumbo jumbo that can't be suppressed.

Index: README
*** README.old	Tue Oct 16 11:45:08 1990
--- README	Tue Oct 16 11:45:10 1990
***************
*** 91,97 ****
      Some compilers will not compile or optimize the larger files without
      some extra switches to use larger jump offsets or allocate larger
      internal tables.  It's okay to insert rules for specific files into
!     Makefile.SH, since a default rule only take effect in the
      absence of a specific rule.
  
      The 3b2 needs to turn off -O.
--- 91,97 ----
      Some compilers will not compile or optimize the larger files without
      some extra switches to use larger jump offsets or allocate larger
      internal tables.  It's okay to insert rules for specific files into
!     Makefile.SH, since a default rule only takes effect in the
      absence of a specific rule.
  
      The 3b2 needs to turn off -O.

Index: eg/sysvipc/README
*** eg/sysvipc/README.old	Tue Oct 16 11:51:22 1990
--- eg/sysvipc/README	Tue Oct 16 11:51:26 1990
***************
*** 0 ****
--- 1,9 ----
+ FYEnjoyment, here are the test scripts I used while implementing SysV
+ IPC in Perl.  Each of them must be run with the parameter "s" for
+ "send" or "r" for "receive"; in each case, the receiver is the server
+ and the sender is the client.
+ 
+ -- 
+ Chip Salzenberg at ComDev/TCT     <chip@tct.uucp>, <uunet!ateng!tct!chip>
+ 
+ 

Index: os2/README.OS2
*** os2/README.OS2.old	Tue Oct 16 11:53:58 1990
--- os2/README.OS2	Tue Oct 16 11:54:01 1990
***************
*** 1,9 ****
- 
  		   Notes on the OS/2 Perl port
  
  			Raymond Chen
! 			 (rjc@math.princeton.edu)
  
  -1.  Background.
  
  This port was based on the MS-DOS port by Diomidis Spinellis.
--- 1,11 ----
  		   Notes on the OS/2 Perl port
  
  			Raymond Chen
! 		 (rjc@math.princeton.edu)
  
+                         Kai Uwe Rommel
+           (rommel@lan.informatik.tu-muenchen.dbp.de)
+ 
  -1.  Background.
  
  This port was based on the MS-DOS port by Diomidis Spinellis.
***************
*** 16,43 ****
  
  1.  Compiling.
  
! Perl has been compiled under MS-DOS using the Microsoft C compiler 
! version 6.0.  Before compiling install dir.h as <sys/dir.h>.  You will 
! need a Unix-like make program and something like yacc (e.g. bison).  I 
! just ran yacc on my UNIX box and downloaded the resulting y.tab.[ch] 
  files.  Compilation takes 45 minutes on a 16MHz 386 machine running
! no jobs other than the compiler, so you will probably need something to 
  do in the meantime.  Like, say, lunch.  (Compilation time does not
! include formatting the manual.)  If you compile with optimization 
  turned off, it takes about half as long.
  
  The executable is 270k (perlsym.exe is 473k; if you compile
! without optimization, the sizes are 329K/531K), and the top level 
! directory needs 800K for sources, 550K for object code, and 800K for the 
  executables, assuming you want to build both perl.exe and perlsym.exe
  with full optimization.
  
! The makefile will compile glob for you which you will need to place 
! somewhere in your path so that perl globbing will work correctly.  All 
! the tests were run, although some modifications were necessary because 
! OS/2 isn't UNIX. The tests that failed failed because of limitations of 
! the operating system and aren't the fault of the compiler.  a2p and s2p 
! were not tested.  
  
  In the eg directory you will find the syscalls.pl header file,
  and a sample program that demonstrates some of the improvements
--- 18,45 ----
  
  1.  Compiling.
  
! Perl has been compiled under MS-DOS using the Microsoft C compiler
! version 6.0.  Before compiling install dir.h as <sys/dir.h>.  You will
! need a Unix-like make program and something like yacc (e.g. bison).  I
! just ran yacc on my UNIX box and downloaded the resulting y.tab.[ch]
  files.  Compilation takes 45 minutes on a 16MHz 386 machine running
! no jobs other than the compiler, so you will probably need something to
  do in the meantime.  Like, say, lunch.  (Compilation time does not
! include formatting the manual.)  If you compile with optimization
  turned off, it takes about half as long.
  
  The executable is 270k (perlsym.exe is 473k; if you compile
! without optimization, the sizes are 329K/531K), and the top level
! directory needs 800K for sources, 550K for object code, and 800K for the
  executables, assuming you want to build both perl.exe and perlsym.exe
  with full optimization.
  
! The makefile will compile glob for you which you will need to place
! somewhere in your path so that perl globbing will work correctly.  All
! the tests were run, although some modifications were necessary because
! OS/2 isn't UNIX. The tests that failed failed because of limitations of
! the operating system and aren't the fault of the compiler.  a2p and s2p
! were not tested.
  
  In the eg directory you will find the syscalls.pl header file,
  and a sample program that demonstrates some of the improvements
***************
*** 46,65 ****
  
  2.  Using OS/2 Perl
  
! The OS/2 version of perl has much of the functionality of the Unix 
! version.  Here are some things that don't work:  sockets, password 
! functions, [gs]et[eug]id, dbm functions, fork.  
  
  One thing that doesn't work is "split" with no arguments.  Somehow,
  yylval.arg is empty ...  [[ Wait, sorry, I fixed that. --rjc ]]
  
  Care has been taken to implement the rest, although the implementation
! might not be the best possible.  Here are short notes on the tricky 
! bits:  
  
  2.1.  In-place editing.
  
! Files currently can be edited in-place provided you are creating a 
  backup.  Considerable effort is made to ensure that a reasonable
  name for the backup is selected, while still remaining within
  the 8.3 contraints of the FAT filesystem.  (HPFS users have nothing
--- 48,67 ----
  
  2.  Using OS/2 Perl
  
! The OS/2 version of perl has much of the functionality of the Unix
! version.  Here are some things that don't work:  sockets, password
! functions, [gs]et[eug]id, dbm functions, fork.
  
  One thing that doesn't work is "split" with no arguments.  Somehow,
  yylval.arg is empty ...  [[ Wait, sorry, I fixed that. --rjc ]]
  
  Care has been taken to implement the rest, although the implementation
! might not be the best possible.  Here are short notes on the tricky
! bits:
  
  2.1.  In-place editing.
  
! Files currently can be edited in-place provided you are creating a
  backup.  Considerable effort is made to ensure that a reasonable
  name for the backup is selected, while still remaining within
  the 8.3 contraints of the FAT filesystem.  (HPFS users have nothing
***************
*** 76,89 ****
            swallow it.  FAT will rarely accept it.)
  
  Style 1:  If the suffix begins with a '.', change the file extension
! 	  to whatever you supplied.  If the name matches the original 
  	  name, use the fallback method.
  
! Style 2:  If the suffix is a single character, not a '.', try to add the 
            suffix to the following places, using the first one that works.
!               [1] Append to extension.  
!               [2] Append to filename, 
!               [3] Replace end of extension, 
                [4] Replace end of filename.
            If the name matches the original name, use the fallback method.
  
--- 78,91 ----
            swallow it.  FAT will rarely accept it.)
  
  Style 1:  If the suffix begins with a '.', change the file extension
! 	  to whatever you supplied.  If the name matches the original
  	  name, use the fallback method.
  
! Style 2:  If the suffix is a single character, not a '.', try to add the
            suffix to the following places, using the first one that works.
!               [1] Append to extension.
!               [2] Append to filename,
!               [3] Replace end of extension,
                [4] Replace end of filename.
            If the name matches the original name, use the fallback method.
  
***************
*** 116,122 ****
                 longname.fil => longname.fi~
                 longname.fi~ => longnam~.fi~
                 longnam~.fi~ => longnam~.$$$
!                
  2.2.  Directory access.
  
  Are implemented, but in order to support telldir() and seekdir(),
--- 118,124 ----
                 longname.fil => longname.fi~
                 longname.fi~ => longnam~.fi~
                 longnam~.fi~ => longnam~.$$$
! 
  2.2.  Directory access.
  
  Are implemented, but in order to support telldir() and seekdir(),
***************
*** 125,131 ****
  
  2.3.  Pipes and redirection.
  
! Pipes and redirection are supported.  Although OS/2 does not 
  terminate programs which try to write to closed pipes, perl will
  kill them for you if you do it like this:
  
--- 127,133 ----
  
  2.3.  Pipes and redirection.
  
! Pipes and redirection are supported.  Although OS/2 does not
  terminate programs which try to write to closed pipes, perl will
  kill them for you if you do it like this:
  
***************
*** 174,197 ****
  
  The arguments you pass are handed off to OS/2 without interpretation,
  and the return value is returned straight to you.  However, you don't
! have to supply arguments for the ones whose descriptions are "must be 
  zero"; perl will supply the mandatory zeros for you.
  
  2.5.  Binary file access
  
! Files are opened in text mode by default.  This means that CR LF pairs 
! are translated to LF. If binary access is needed the `binarymode' 
! function should be used.  There is currently no way to reverse the 
! effect of the binary function.  If that is needed close and reopen the 
! file.  
  
  2.6.  Priority
  
! The getpriority and setpriority functions are implemented, but since 
! OS/2 priorities are different from UNIX priorities, the arguments aren't 
! the same.  Basically, the arguments you pass are handed directly to 
! OS/2. The only exception is the last argument to setpriority.  To make 
! it easier to make delta priorities, if the priority class is 0xff, it 
  is changed to 0.  That way, you can write
  
  	setpriority(0,0,-2)
--- 176,199 ----
  
  The arguments you pass are handed off to OS/2 without interpretation,
  and the return value is returned straight to you.  However, you don't
! have to supply arguments for the ones whose descriptions are "must be
  zero"; perl will supply the mandatory zeros for you.
  
  2.5.  Binary file access
  
! Files are opened in text mode by default.  This means that CR LF pairs
! are translated to LF. If binary access is needed the `binarymode'
! function should be used.  There is currently no way to reverse the
! effect of the binary function.  If that is needed close and reopen the
! file.
  
  2.6.  Priority
  
! The getpriority and setpriority functions are implemented, but since
! OS/2 priorities are different from UNIX priorities, the arguments aren't
! the same.  Basically, the arguments you pass are handed directly to
! OS/2. The only exception is the last argument to setpriority.  To make
! it easier to make delta priorities, if the priority class is 0xff, it
  is changed to 0.  That way, you can write
  
  	setpriority(0,0,-2)
***************
*** 204,211 ****
  
  2.7.  Interpreter startup.
  
! The effect of the Unix #!/bin/perl interpreter startup can be obtained 
! under OS/2 by giving the script a .cmd extension and beginning the script 
  with the line
  
  	extproc C:\binp\perl.exe -S
--- 206,213 ----
  
  2.7.  Interpreter startup.
  
! The effect of the Unix #!/bin/perl interpreter startup can be obtained
! under OS/2 by giving the script a .cmd extension and beginning the script
  with the line
  
  	extproc C:\binp\perl.exe -S
***************
*** 264,270 ****
  as do_spawn does (which means, of course, that we probably
  should yank out code to be dished off into a subroutine).
  
! In do_spawn(), use DosExecPgm instead of spawnl in order to get more 
  precise reasons why the child terminated (RESULTCODES).
  
  
--- 266,272 ----
  as do_spawn does (which means, of course, that we probably
  should yank out code to be dished off into a subroutine).
  
! In do_spawn(), use DosExecPgm instead of spawnl in order to get more
  precise reasons why the child terminated (RESULTCODES).
  
  
***************
*** 273,275 ****
--- 275,356 ----
  				Raymond Chen <rjc@math.princeton.edu>
  				1817 Oxford St. Apt 6
  				Berkeley, CA 94709-1828 USA
+ 
+ -----------------------
+ I picked up the OS/2 port with patches 19-28. When compiling, I found
+ out that os2.c and director.c were missing. I had to rewrite them because
+ even the original author of the port (Raymond Chen) did no longer have them.
+ 
+ I had directory routines laying around, this was no big deal.
+ I rewrote os2.c, but did not implement the syscall() as described above.
+ I had not the time and did not really need it. Feel free ...
+ 
+ Changes to above described port:
+ 
+ - the small program GLOB is now named PERLGLOB for better ordering in
+   my /bin directory
+ 
+ - added help page (well, a graphical user interface would be overkill
+   but a simple help page should be in every program :-)
+ 
+ - several cosmetic changes in standard distribution files because of
+   naming conventions etc., #ifdef'd OS2
+ 
+ - syscall() not supported as noted above
+ 
+ - chdir now recognizes also drive letters and changes also the drive
+ 
+ - new mypopen(), mypclose() functions and simulation routines for DOS mode,
+   they are selected automatically in real mode
+ - the new pclose() does not kill the child, my experience is that this is
+   not needed.
+ 
+ - setpriority is now:   setpriority(class, pid, val)
+   see description of DosSetPrty() for class and val meanings
+ - getpriority is now:   getpriority(dummy, pid)
+   see description of DosGetPrty()
+ 
+ - kill is now:          kill(pid, sig)
+   where sig can be 0 (kill process)
+                    1-3 (send process flags A-C, see DosFlagProcess())
+   if pid is less than zero, the signal is sent to the whole
+   process tree originating at -pid.
+ 
+ The following files are now new with patch >=29:
+ 
+ readme.os2        this file
+ 
+ dir.h             sys/dir.h
+ director.c        directory routines
+ os2.c             kernel of OS/2 port (see below)
+ popen.c           new popen.c
+ mktemp.c          enhanced mktemp(), uses TMP env. variable, used by popen.c
+ 
+ perl.cs           Compiler Shell script for perl itself
+ perl.def          linker definition file for perl
+ perl.bad          names of protect-only API calls for BIND
+ perlglob.cs       Compiler Shell script for perl globbing program
+ perlglob.def      linker definition file for perlglob
+ a2p.cs            Compiler Shell script for a2p (see below)
+ a2p.def           linker definition file for a2p
+ makefile          Makefile, not tested
+ 
+ perlsh.cmd        the converted perlsh
+ selfrun.cmd       sample selfrunning perl script for OS/2
+ selfrun.bat       sample selfrunning perl script for DOS mode
+ 
+ Note: I don't use make but my own utility, the Compiler Shell CS.
+ It was posted in comp.binaries.os2 or you can ask me for the newest
+ version. The .CS files are the "makefiles" for it.
+ 
+ Note: MS C 6.00 is required. C 5.1 is not capable of compiling perl,
+ especially not with -DDEBUGGING
+ 
+ 
+                                 August 1990
+ 
+                                 Kai Uwe Rommel
+                                 rommel@lan.informatik.tu-muenchen.dbp.de
+                                 Breslauer Str. 25
+                                 D-8756 Kahl/Main
+                                 West (yes, still!) Germany

*** End of Patch 29 ***