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

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (03/02/90)

System: perl version 3.0
Patch #: 11
Priority: HIGH
Subject: patch #9, continued

Description:
	See patch #9.


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 #12 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: 10
1c1
< #define PATCHLEVEL 10
---
> #define PATCHLEVEL 11

Index: evalargs.xc
Prereq: 3.0.1.3
*** evalargs.xc.old	Thu Mar  1 10:51:30 1990
--- evalargs.xc	Thu Mar  1 10:51:32 1990
***************
*** 2,10 ****
   * kit sizes from getting too big.
   */
  
! /* $Header: evalargs.xc,v 3.0.1.3 89/11/17 15:25:07 lwall Locked $
   *
   * $Log:	evalargs.xc,v $
   * Revision 3.0.1.3  89/11/17  15:25:07  lwall
   * patch5: constant numeric subscripts disappeared in ?:
   * 
--- 2,13 ----
   * kit sizes from getting too big.
   */
  
! /* $Header: evalargs.xc,v 3.0.1.4 90/02/28 17:38:37 lwall Locked $
   *
   * $Log:	evalargs.xc,v $
+  * Revision 3.0.1.4  90/02/28  17:38:37  lwall
+  * patch9: $#foo -= 2 didn't work
+  * 
   * Revision 3.0.1.3  89/11/17  15:25:07  lwall
   * patch5: constant numeric subscripts disappeared in ?:
   * 
***************
*** 176,182 ****
  	    ++sp;
  	    stab = argptr.arg_stab;
  	    str = stab_array(argptr.arg_stab)->ary_magic;
! 	    if (argflags & (AF_PRE|AF_POST))
  		str_numset(str,(double)(stab_array(stab)->ary_fill+arybase));
  #ifdef DEBUGGING
  	    tmps = "LARYLEN";
--- 179,185 ----
  	    ++sp;
  	    stab = argptr.arg_stab;
  	    str = stab_array(argptr.arg_stab)->ary_magic;
! 	    if (optype != O_SASSIGN || argflags & (AF_PRE|AF_POST))
  		str_numset(str,(double)(stab_array(stab)->ary_fill+arybase));
  #ifdef DEBUGGING
  	    tmps = "LARYLEN";
***************
*** 229,236 ****
  	    break;
  	case A_WANTARRAY:
  	    {
- 		extern int wantarray;
- 
  		if (wantarray == G_ARRAY)
  		    st[++sp] = &str_yes;
  		else
--- 232,237 ----
***************
*** 295,301 ****
  			str_cat(tmpstr,
  			  "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
  #endif
! 			(void)do_open(last_in_stab,tmpstr->str_ptr);
  			fp = stab_io(last_in_stab)->ifp;
  			str_free(tmpstr);
  		    }
--- 296,303 ----
  			str_cat(tmpstr,
  			  "|tr -s ' \t\f\r' '\\012\\012\\012\\012'|");
  #endif
! 			(void)do_open(last_in_stab,tmpstr->str_ptr,
! 			  tmpstr->str_cur);
  			fp = stab_io(last_in_stab)->ifp;
  			str_free(tmpstr);
  		    }

Index: form.c
Prereq: 3.0
*** form.c.old	Thu Mar  1 10:51:37 1990
--- form.c	Thu Mar  1 10:51:38 1990
***************
*** 1,4 ****
! /* $Header: form.c,v 3.0 89/10/18 15:17:26 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
--- 1,4 ----
! /* $Header: form.c,v 3.0.1.1 90/02/28 17:39:34 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
***************
*** 6,11 ****
--- 6,14 ----
   *    as specified in the README file that comes with the perl 3.0 kit.
   *
   * $Log:	form.c,v $
+  * Revision 3.0.1.1  90/02/28  17:39:34  lwall
+  * patch9: ... in format threw off subsequent field
+  * 
   * Revision 3.0  89/10/18  15:17:26  lwall
   * 3.0 baseline
   * 
***************
*** 157,162 ****
--- 160,166 ----
  		    *d++ = '.';
  		    *d++ = '.';
  		    *d++ = '.';
+ 		    size -= 3;
  		}
  		while (*chophere && index(chopset,*chophere))
  		    chophere++;

Index: lib/getopt.pl
Prereq: 3.0
*** lib/getopt.pl.old	Thu Mar  1 10:51:53 1990
--- lib/getopt.pl	Thu Mar  1 10:51:55 1990
***************
*** 1,4 ****
! ;# $Header: getopt.pl,v 3.0 89/10/18 15:19:26 lwall Locked $
  
  ;# Process single-character switches with switch clustering.  Pass one argument
  ;# which is a string containing all switches that take an argument.  For each
--- 1,4 ----
! ;# $Header: getopt.pl,v 3.0.1.1 90/02/28 17:41:59 lwall Locked $
  
  ;# Process single-character switches with switch clustering.  Pass one argument
  ;# which is a string containing all switches that take an argument.  For each
***************
*** 12,17 ****
--- 12,18 ----
  sub Getopt {
      local($argumentative) = @_;
      local($_,$first,$rest);
+     local($[) = 0;
  
      while (($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
  	($first,$rest) = ($1,$2);

Index: lib/getopts.pl
*** lib/getopts.pl.old	Thu Mar  1 10:52:00 1990
--- lib/getopts.pl	Thu Mar  1 10:52:01 1990
***************
*** 6,12 ****
  
  sub Getopts {
      local($argumentative) = @_;
!     local(@args,$_,$first,$rest);
  
      @args = split( / */, $argumentative );
      while(($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
--- 6,13 ----
  
  sub Getopts {
      local($argumentative) = @_;
!     local(@args,$_,$first,$rest,$errs);
!     local($[) = 0;
  
      @args = split( / */, $argumentative );
      while(($_ = $ARGV[0]) =~ /^-(.)(.*)/) {
***************
*** 31,37 ****
  	    }
  	}
  	else {
! 	    print stderr "Unknown option: $first\n";
  	    if($rest ne '') {
  		$ARGV[0] = "-$rest";
  	    }
--- 32,39 ----
  	    }
  	}
  	else {
! 	    print STDERR "Unknown option: $first\n";
! 	    ++$errs;
  	    if($rest ne '') {
  		$ARGV[0] = "-$rest";
  	    }
***************
*** 40,45 ****
--- 42,48 ----
  	    }
  	}
      }
+     $errs == 0;
  }
  
  1;

Index: eg/g/gsh
Prereq: 3.0
*** eg/g/gsh.old	Thu Mar  1 10:50:36 1990
--- eg/g/gsh	Thu Mar  1 10:50:37 1990
***************
*** 1,6 ****
! #!/bin/perl
  
! # $Header: gsh,v 3.0 89/10/18 15:14:36 lwall Locked $
  
  # Do rsh globally--see man page
  
--- 1,6 ----
! #! /usr/bin/perl
  
! # $Header: gsh,v 3.0.1.1 90/02/28 17:14:10 lwall Locked $
  
  # Do rsh globally--see man page
  
***************
*** 8,18 ****
  
  sub getswitches {
      while ($ARGV[0] =~ /^-/) {		# parse switches
! 	$ARGV[0] =~ /^-h/ && ($showhost++,$silent++,shift,next);
! 	$ARGV[0] =~ /^-s/ && ($silent++,shift,next);
! 	$ARGV[0] =~ /^-d/ && ($dodist++,shift,next);
! 	$ARGV[0] =~ /^-n/ && ($n=' -n',shift,next);
! 	$ARGV[0] =~ /^-l/ && ($l=' -l ' . $ARGV[1],shift,shift,next);
  	last;
      }
  }
--- 8,19 ----
  
  sub getswitches {
      while ($ARGV[0] =~ /^-/) {		# parse switches
! 	$ARGV[0] =~ /^-h/ && ($showhost++,$silent++,shift(@ARGV),next);
! 	$ARGV[0] =~ /^-s/ && ($silent++,shift(@ARGV),next);
! 	$ARGV[0] =~ /^-d/ && ($dodist++,shift(@ARGV),next);
! 	$ARGV[0] =~ /^-n/ && ($n=' -n',shift(@ARGV),next);
! 	$ARGV[0] =~ /^-l/ && ($l=' -l ' . $ARGV[1],shift(@ARGV),shift(@ARGV),
! 				next);
  	last;
      }
  }

Index: t/io.pipe
Prereq: 3.0
*** t/io.pipe.old	Thu Mar  1 10:54:52 1990
--- t/io.pipe	Thu Mar  1 10:54:53 1990
***************
*** 1,9 ****
  #!./perl
  
! # $Header: io.pipe,v 3.0 89/10/18 15:26:30 lwall Locked $
  
  $| = 1;
! print "1..4\n";
  
  open(PIPE, "|-") || (exec 'tr', '[A-Z]', '[a-z]');
  print PIPE "OK 1\n";
--- 1,9 ----
  #!./perl
  
! # $Header: io.pipe,v 3.0.1.1 90/02/28 18:32:41 lwall Locked $
  
  $| = 1;
! print "1..8\n";
  
  open(PIPE, "|-") || (exec 'tr', '[A-Z]', '[a-z]');
  print PIPE "OK 1\n";
***************
*** 12,21 ****
  
  if (open(PIPE, "-|")) {
      while(<PIPE>) {
  	print;
      }
  }
  else {
!     print STDOUT "ok 3\n";
!     exec 'echo', 'ok 4';
  }
--- 12,56 ----
  
  if (open(PIPE, "-|")) {
      while(<PIPE>) {
+ 	s/^not //;
  	print;
      }
  }
  else {
!     print STDOUT "not ok 3\n";
!     exec 'echo', 'not ok 4';
  }
+ 
+ pipe(READER,WRITER) || die "Can't open pipe";
+ 
+ if ($pid = fork) {
+     close WRITER;
+     while(<READER>) {
+ 	s/^not //;
+ 	y/A-Z/a-z/;
+ 	print;
+     }
+ }
+ else {
+     die "Couldn't fork" unless defined $pid;
+     close READER;
+     print WRITER "not ok 5\n";
+     open(STDOUT,">&WRITER") || die "Can't dup WRITER to STDOUT";
+     close WRITER;
+     exec 'echo', 'not ok 6';
+ }
+ 
+ 
+ pipe(READER,WRITER) || die "Can't open pipe";
+ close READER;
+ 
+ $SIG{'PIPE'} = 'broken_pipe';
+ 
+ sub broken_pipe {
+     print "ok 7\n";
+ }
+ 
+ print WRITER "not ok 7\n";
+ close WRITER;
+ 
+ print "ok 8\n";

Index: lib/look.pl
*** lib/look.pl.old	Thu Mar  1 10:52:05 1990
--- lib/look.pl	Thu Mar  1 10:52:06 1990
***************
*** 11,23 ****
      $blksize = 8192 unless $blksize;
      $key =~ s/[^\w\s]//g if $dict;
      $key =~ y/A-Z/a-z/ if $fold;
!     $max = $size + $blksize - 1;
!     $max -= $size % $blksize;
!     while ($max - $min > $blksize) {
! 	$mid = ($max + $min) / 2;
! 	die "look: internal error"  if $mid % $blksize;
! 	seek(FH,$mid,0);
! 	$_ = <FH>;		# probably a partial line
  	$_ = <FH>;
  	chop;
  	s/[^\w\s]//g if $dict;
--- 11,21 ----
      $blksize = 8192 unless $blksize;
      $key =~ s/[^\w\s]//g if $dict;
      $key =~ y/A-Z/a-z/ if $fold;
!     $max = int($size / $blksize);
!     while ($max - $min > 1) {
! 	$mid = int(($max + $min) / 2);
! 	seek(FH,$mid * $blksize,0);
! 	$_ = <FH> if $mid;		# probably a partial line
  	$_ = <FH>;
  	chop;
  	s/[^\w\s]//g if $dict;
***************
*** 29,35 ****
--- 27,35 ----
  	    $max = $mid;
  	}
      }
+     $min *= $blksize;
      seek(FH,$min,0);
+     <FH> if $min;
      while (<FH>) {
  	chop;
  	s/[^\w\s]//g if $dict;

Index: t/op.mkdir
Prereq: 3.0.1.1
*** t/op.mkdir.old	Thu Mar  1 10:54:56 1990
--- t/op.mkdir	Thu Mar  1 10:54:57 1990
***************
*** 1,6 ****
  #!./perl
  
! # $Header: op.mkdir,v 3.0.1.1 89/11/11 05:00:47 lwall Locked $
  
  print "1..7\n";
  
--- 1,6 ----
  #!./perl
  
! # $Header: op.mkdir,v 3.0.1.2 90/02/28 18:35:31 lwall Locked $
  
  print "1..7\n";
  
***************
*** 12,15 ****
  print (-d 'blurfl' ? "ok 4\n" : "not ok 4\n");
  print (rmdir('blurfl') ? "ok 5\n" : "not ok 5\n");
  print (rmdir('blurfl') ? "not ok 6\n" : "ok 6\n");
! print ($! =~ /such/ ? "ok 7\n" : "not ok 7\n");
--- 12,15 ----
  print (-d 'blurfl' ? "ok 4\n" : "not ok 4\n");
  print (rmdir('blurfl') ? "ok 5\n" : "not ok 5\n");
  print (rmdir('blurfl') ? "not ok 6\n" : "ok 6\n");
! print ($! =~ /such|exist/ ? "ok 7\n" : "not ok 7\n");

Index: t/op.stat
Prereq: 3.0.1.2
*** t/op.stat.old	Thu Mar  1 10:55:01 1990
--- t/op.stat	Thu Mar  1 10:55:02 1990
***************
*** 1,6 ****
  #!./perl
  
! # $Header: op.stat,v 3.0.1.2 89/11/17 15:39:27 lwall Locked $
  
  print "1..56\n";
  
--- 1,6 ----
  #!./perl
  
! # $Header: op.stat,v 3.0.1.3 90/02/28 18:36:51 lwall Locked $
  
  print "1..56\n";
  
***************
*** 88,98 ****
  
  $cnt = $uid = 0;
  
! while (</usr/bin/*>) {
      $cnt++;
      $uid++ if -u;
      last if $uid && $uid < $cnt;
  }
  
  # I suppose this is going to fail somewhere...
  if ($uid > 0 && $uid < $cnt) {print "ok 35\n";} else {print "not ok 35\n";}
--- 88,102 ----
  
  $cnt = $uid = 0;
  
! chop($cwd = `pwd`);
! die "Can't run op.stat test 35 without pwd working" unless $cwd;
! chdir '/usr/bin' || die "Can't cd to /usr/bin";
! while (<*>) {
      $cnt++;
      $uid++ if -u;
      last if $uid && $uid < $cnt;
  }
+ chdir $cwd || die "Can't cd back to $cwd";
  
  # I suppose this is going to fail somewhere...
  if ($uid > 0 && $uid < $cnt) {print "ok 35\n";} else {print "not ok 35\n";}

Index: t/op.subst
Prereq: 3.0
*** t/op.subst.old	Thu Mar  1 10:55:07 1990
--- t/op.subst	Thu Mar  1 10:55:09 1990
***************
*** 1,6 ****
  #!./perl
  
! # $Header: op.subst,v 3.0 89/10/18 15:31:43 lwall Locked $
  
  print "1..42\n";
  
--- 1,6 ----
  #!./perl
  
! # $Header: op.subst,v 3.0.1.1 90/02/28 18:37:30 lwall Locked $
  
  print "1..42\n";
  
***************
*** 42,48 ****
  $_ = '\\' x 4;
  if (length($_) == 4) {print "ok 9\n";} else {print "not ok 9\n";}
  s/\\/\\\\/g;
! if ($_ eq '\\' x 8) {print "ok 10\n";} else {print "not ok 10\n";}
  
  $_ = '\/' x 4;
  if (length($_) == 8) {print "ok 11\n";} else {print "not ok 11\n";}
--- 42,48 ----
  $_ = '\\' x 4;
  if (length($_) == 4) {print "ok 9\n";} else {print "not ok 9\n";}
  s/\\/\\\\/g;
! if ($_ eq '\\' x 8) {print "ok 10\n";} else {print "not ok 10 $_\n";}
  
  $_ = '\/' x 4;
  if (length($_) == 8) {print "ok 11\n";} else {print "not ok 11\n";}

Index: perl.h
Prereq: 3.0.1.4
*** perl.h.old	Thu Mar  1 10:52:21 1990
--- perl.h	Thu Mar  1 10:52:24 1990
***************
*** 1,4 ****
! /* $Header: perl.h,v 3.0.1.4 89/12/21 20:07:35 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
--- 1,4 ----
! /* $Header: perl.h,v 3.0.1.5 90/02/28 17:52:28 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
***************
*** 6,11 ****
--- 6,19 ----
   *    as specified in the README file that comes with the perl 3.0 kit.
   *
   * $Log:	perl.h,v $
+  * Revision 3.0.1.5  90/02/28  17:52:28  lwall
+  * patch9: Configure now determines whether volatile is supported
+  * patch9: volatilized some more variables for super-optimizing compilers
+  * patch9: unused VREG symbol deleted
+  * patch9: perl can now start up other interpreters scripts  
+  * patch9: you may now undef $/ to have no input record separator
+  * patch9: nested evals clobbered their longjmp environment
+  * 
   * Revision 3.0.1.4  89/12/21  20:07:35  lwall
   * patch7: arranged for certain registers to be restored after longjmp()
   * patch7: Configure now compiles a test program to figure out time.h fiasco
***************
*** 35,51 ****
   * 
   */
  
! #ifdef __STDC__
  #define VOLATILE volatile
- #define VREG
  #else
  #define VOLATILE
- #define VREG register
  #endif
  
- #define VOIDUSED 1
- #include "config.h"
- 
  #ifdef IAMSUID
  #   ifndef TAINT
  #	define TAINT
--- 43,57 ----
   * 
   */
  
! #define VOIDUSED 1
! #include "config.h"
! 
! #if defined(HASVOLATILE) || defined(__STDC__)
  #define VOLATILE volatile
  #else
  #define VOLATILE
  #endif
  
  #ifdef IAMSUID
  #   ifndef TAINT
  #	define TAINT
***************
*** 420,425 ****
--- 426,432 ----
  void do_join();
  void do_sprintf();
  void do_accept();
+ void do_pipe();
  void do_vecset();
  void savelist();
  void saveitem();
***************
*** 428,436 ****
--- 435,446 ----
  void savesptr();
  void savehptr();
  void restorelist();
+ void repeatcpy();
  HASH *savehash();
  ARRAY *saveary();
  
+ EXT char **origargv;
+ EXT int origargc;
  EXT line_t line INIT(0);
  EXT line_t subline INIT(0);
  EXT STR *subname INIT(Nullstr);
***************
*** 476,482 ****
  
  EXT char *filename;
  EXT char *origfilename;
! EXT FILE *rsfp;
  EXT char buf[1024];
  EXT char *bufptr;
  EXT char *oldbufptr;
--- 486,492 ----
  
  EXT char *filename;
  EXT char *origfilename;
! EXT FILE * VOLATILE rsfp;
  EXT char buf[1024];
  EXT char *bufptr;
  EXT char *oldbufptr;
***************
*** 485,491 ****
  
  EXT STR *linestr INIT(Nullstr);
  
! EXT char record_separator INIT('\n');
  EXT int rslen INIT(1);
  EXT char *ofs INIT(Nullch);
  EXT int ofslen INIT(0);
--- 495,501 ----
  
  EXT STR *linestr INIT(Nullstr);
  
! EXT int record_separator INIT('\n');
  EXT int rslen INIT(1);
  EXT char *ofs INIT(Nullch);
  EXT int ofslen INIT(0);
***************
*** 506,511 ****
--- 516,522 ----
  EXT bool sawstudy INIT(FALSE);		/* do fbminstr on all strings */
  EXT bool sawi INIT(FALSE);		/* study must assume case insensitive */
  EXT bool sawvec INIT(FALSE);
+ EXT bool localizing INIT(FALSE);	/* are we processing a local() list? */
  
  #ifdef CSH
  char *cshname INIT(CSH);
***************
*** 522,528 ****
  
  EXT char tokenbuf[256];
  EXT int expectterm INIT(TRUE);		/* how to interpret ambiguous tokens */
! EXT int in_eval INIT(FALSE);		/* trap fatal errors? */
  EXT int multiline INIT(0);		/* $*--do strings hold >1 line? */
  EXT int forkprocess;			/* so do_open |- can return proc# */
  EXT int do_undump INIT(0);		/* -u or dump seen? */
--- 533,539 ----
  
  EXT char tokenbuf[256];
  EXT int expectterm INIT(TRUE);		/* how to interpret ambiguous tokens */
! EXT VOLATILE int in_eval INIT(FALSE);	/* trap fatal errors? */
  EXT int multiline INIT(0);		/* $*--do strings hold >1 line? */
  EXT int forkprocess;			/* so do_open |- can return proc# */
  EXT int do_undump INIT(0);		/* -u or dump seen? */
***************
*** 554,560 ****
  EXT int unsafe;
  
  #ifdef DEBUGGING
! EXT int debug INIT(0);
  EXT int dlevel INIT(0);
  EXT int dlmax INIT(128);
  EXT char *debname;
--- 565,571 ----
  EXT int unsafe;
  
  #ifdef DEBUGGING
! EXT VOLATILE int debug INIT(0);
  EXT int dlevel INIT(0);
  EXT int dlmax INIT(128);
  EXT char *debname;
***************
*** 581,593 ****
  EXT int loop_max INIT(128);
  
  EXT jmp_buf top_env;
- EXT jmp_buf eval_env;
  
! EXT char *goto_targ INIT(Nullch);	/* cmd_exec gets strange when set */
  
  EXT ARRAY *stack;		/* THE STACK */
  
! EXT ARRAY *savestack;		/* to save non-local values on */
  
  EXT ARRAY *tosave;		/* strings to save on recursive subroutine */
  
--- 592,603 ----
  EXT int loop_max INIT(128);
  
  EXT jmp_buf top_env;
  
! EXT char * VOLATILE goto_targ INIT(Nullch); /* cmd_exec gets strange when set */
  
  EXT ARRAY *stack;		/* THE STACK */
  
! EXT ARRAY * VOLATILE savestack;		/* to save non-local values on */
  
  EXT ARRAY *tosave;		/* strings to save on recursive subroutine */
  
***************
*** 594,599 ****
--- 604,613 ----
  EXT ARRAY *lineary;		/* lines of script for debugger */
  
  EXT ARRAY *pidstatary;		/* keep pids and statuses by fd for mypopen */
+ 
+ EXT int *di;			/* for tmp use in debuggers */
+ EXT char *dc;
+ EXT short *ds;
  
  double atof();
  long time();

Index: perl.man.1
Prereq: 3.0.1.2
*** perl.man.1.old	Thu Mar  1 10:52:35 1990
--- perl.man.1	Thu Mar  1 10:52:38 1990
***************
*** 1,7 ****
  .rn '' }`
! ''' $Header: perl.man.1,v 3.0.1.2 89/11/17 15:30:03 lwall Locked $
  ''' 
  ''' $Log:	perl.man.1,v $
  ''' Revision 3.0.1.2  89/11/17  15:30:03  lwall
  ''' patch5: fixed some manual typos and indent problems
  ''' 
--- 1,11 ----
  .rn '' }`
! ''' $Header: perl.man.1,v 3.0.1.3 90/02/28 17:54:32 lwall Locked $
  ''' 
  ''' $Log:	perl.man.1,v $
+ ''' Revision 3.0.1.3  90/02/28  17:54:32  lwall
+ ''' patch9: @array in scalar context now returns length of array
+ ''' patch9: in manual, example of open and ?: was backwards
+ ''' 
  ''' Revision 3.0.1.2  89/11/17  15:30:03  lwall
  ''' patch5: fixed some manual typos and indent problems
  ''' 
***************
*** 481,489 ****
--- 485,504 ----
  
  .fi
  .PP
+ If you evaluate an array in a scalar context, it returns the length of
+ the array.
+ The following is always true:
+ .nf
+ 
+ 	@whatever == $#whatever \- $[ + 1;
+ 
+ .fi
+ .PP
  Multi-dimensional arrays are not directly supported, but see the discussion
  of the $; variable later for a means of emulating multiple subscripts with
  an associative array.
+ You could also write a subroutine to turn multiple subscripts into a single
+ subscript.
  .PP
  Every data type has its own namespace.
  You can, without fear of conflict, use the same name for a scalar variable,
***************
*** 684,690 ****
  from that file (newline included, so it's never false until EOF, at
  which time an undefined value is returned).
  Ordinarily you must assign that value to a variable,
! but there is one situation where in which an automatic assignment happens.
  If (and only if) the input symbol is the only thing inside the conditional of a
  .I while
  loop, the value is
--- 699,705 ----
  from that file (newline included, so it's never false until EOF, at
  which time an undefined value is returned).
  Ordinarily you must assign that value to a variable,
! but there is one situation where an automatic assignment happens.
  If (and only if) the input symbol is the only thing inside the conditional of a
  .I while
  loop, the value is
***************
*** 896,902 ****
  	if (!open(foo)) { die "Can't open $foo: $!"; }
  	die "Can't open $foo: $!" unless open(foo);
  	open(foo) || die "Can't open $foo: $!";	# foo or bust!
! 	open(foo) ? die "Can't open $foo: $!" : \'hi mom\';
  				# a bit exotic, that last one
  
  .fi
--- 911,917 ----
  	if (!open(foo)) { die "Can't open $foo: $!"; }
  	die "Can't open $foo: $!" unless open(foo);
  	open(foo) || die "Can't open $foo: $!";	# foo or bust!
! 	open(foo) ? \'hi mom\' : die "Can't open $foo: $!";
  				# a bit exotic, that last one
  
  .fi

Index: perl.man.2
Prereq: 3.0.1.2
*** perl.man.2.old	Thu Mar  1 10:52:49 1990
--- perl.man.2	Thu Mar  1 10:52:52 1990
***************
*** 1,7 ****
  ''' Beginning of part 2
! ''' $Header: perl.man.2,v 3.0.1.2 89/11/17 15:30:16 lwall Locked $
  '''
  ''' $Log:	perl.man.2,v $
  ''' Revision 3.0.1.2  89/11/17  15:30:16  lwall
  ''' patch5: fixed some manual typos and indent problems
  ''' 
--- 1,11 ----
  ''' Beginning of part 2
! ''' $Header: perl.man.2,v 3.0.1.3 90/02/28 17:55:58 lwall Locked $
  '''
  ''' $Log:	perl.man.2,v $
+ ''' Revision 3.0.1.3  90/02/28  17:55:58  lwall
+ ''' patch9: grep now returns number of items matched in scalar context
+ ''' patch9: documented in-place modification capabilites of grep
+ ''' 
  ''' Revision 3.0.1.2  89/11/17  15:30:16  lwall
  ''' patch5: fixed some manual typos and indent problems
  ''' 
***************
*** 777,787 ****
--- 781,796 ----
  Evaluates EXPR for each element of LIST (locally setting $_ to each element)
  and returns the array value consisting of those elements for which the
  expression evaluated to true.
+ In a scalar context, returns the number of times the expression was true.
  .nf
  
  	@foo = grep(!/^#/, @bar);    # weed out comments
  
  .fi
+ Note that, since $_ is a reference into the array value, it can be
+ used to modify the elements of the array.
+ While this is useful and supported, it can cause bizarre results if
+ the LIST contains literal values.
  .Ip "hex(EXPR)" 8 4
  .Ip "hex EXPR" 8
  Returns the decimal value of EXPR interpreted as an hex string.

Index: perl.man.3
Prereq: 3.0.1.3
*** perl.man.3.old	Thu Mar  1 10:53:05 1990
--- perl.man.3	Thu Mar  1 10:53:09 1990
***************
*** 1,7 ****
  ''' Beginning of part 3
! ''' $Header: perl.man.3,v 3.0.1.3 89/12/21 20:10:12 lwall Locked $
  '''
  ''' $Log:	perl.man.3,v $
  ''' Revision 3.0.1.3  89/12/21  20:10:12  lwall
  ''' patch7: documented that s`pat`repl` does command substitution on replacement
  ''' patch7: documented that $timeleft from select() is likely not implemented
--- 1,13 ----
  ''' Beginning of part 3
! ''' $Header: perl.man.3,v 3.0.1.4 90/02/28 18:00:09 lwall Locked $
  '''
  ''' $Log:	perl.man.3,v $
+ ''' Revision 3.0.1.4  90/02/28  18:00:09  lwall
+ ''' patch9: added pipe function
+ ''' patch9: documented how to handle arbitrary weird characters in filenames
+ ''' patch9: documented the unflushed buffers problem on piped opens
+ ''' patch9: documented how to force top of page
+ ''' 
  ''' Revision 3.0.1.3  89/12/21  20:10:12  lwall
  ''' patch7: documented that s`pat`repl` does command substitution on replacement
  ''' patch7: documented that $timeleft from select() is likely not implemented
***************
*** 202,207 ****
--- 208,229 ----
  .fi
  Explicitly closing any piped filehandle causes the parent process to wait for the
  child to finish, and returns the status value in $?.
+ Note: on any operation which may do a fork,
+ unflushed buffers remain unflushed in both
+ processes, which means you may need to set $| to
+ avoid duplicate output.
+ .Sp
+ The filename that is passed to open will have leading and trailing
+ whitespace deleted.
+ In order to open a file with arbitrary weird characters in it, it's necessary
+ to protect any leading and trailing whitespace thusly:
+ .nf
+ 
+ .ne 2
+         $file =~ s#^(\es)#./$1#;
+         open(FOO, "< $file\e0");
+ 
+ .fi
  .Ip "opendir(DIRHANDLE,EXPR)" 8 3
  Opens a directory named EXPR for processing by readdir(), telldir(), seekdir(),
  rewinddir() and closedir().
***************
*** 270,275 ****
--- 292,305 ----
  
  .fi
  The same template may generally also be used in the unpack function.
+ .Ip "pipe(READHANDLE,WRITEHANDLE)" 8 3
+ Opens a pair of connected pipes like the corresponding system call.
+ Note that if you set up a loop of piped processes, deadlock can occur
+ unless you are very careful.
+ In addition, note that perl's pipes use stdio buffering, so you may need
+ to set $| to flush your WRITEHANDLE after each command, depending on
+ the application.
+ [Requires version 3.0 patchlevel 9.]
  .Ip "pop(ARRAY)" 8
  .Ip "pop ARRAY" 8 6
  Pops and returns the last value of the array, shortening the array by 1.
***************
*** 693,699 ****
  .Ip "split" 8
  Splits a string into an array of strings, and returns it.
  (If not in an array context, returns the number of fields found and splits
! into the @_ array.)
  If EXPR is omitted, splits the $_ string.
  If PATTERN is also omitted, splits on whitespace (/[\ \et\en]+/).
  Anything matching PATTERN is taken to be a delimiter separating the fields.
--- 723,731 ----
  .Ip "split" 8
  Splits a string into an array of strings, and returns it.
  (If not in an array context, returns the number of fields found and splits
! into the @_ array.
! (In an array context, you can force the split into @_
! by using ?? as the pattern delimiters, but it still returns the array value.))
  If EXPR is omitted, splits the $_ string.
  If PATTERN is also omitted, splits on whitespace (/[\ \et\en]+/).
  Anything matching PATTERN is taken to be a delimiter separating the fields.
***************
*** 1119,1129 ****
  .Sp
  Top of form processing is handled automatically:
  if there is insufficient room on the current page for the formatted 
! record, the page is advanced, a special top-of-page format is used
  to format the new page header, and then the record is written.
  By default the top-of-page format is \*(L"top\*(R", but it
  may be set to the
  format of your choice by assigning the name to the $^ variable.
  .Sp
  If FILEHANDLE is unspecified, output goes to the current default output channel,
  which starts out as
--- 1151,1164 ----
  .Sp
  Top of form processing is handled automatically:
  if there is insufficient room on the current page for the formatted 
! record, the page is advanced by writing a form feed,
! a special top-of-page format is used
  to format the new page header, and then the record is written.
  By default the top-of-page format is \*(L"top\*(R", but it
  may be set to the
  format of your choice by assigning the name to the $^ variable.
+ The number of lines remaining on the current page is in variable $-, which
+ can be set to 0 to force a new page.
  .Sp
  If FILEHANDLE is unspecified, output goes to the current default output channel,
  which starts out as

Index: perl.man.4
Prereq: 3.0.1.4
*** perl.man.4.old	Thu Mar  1 10:53:22 1990
--- perl.man.4	Thu Mar  1 10:53:28 1990
***************
*** 1,7 ****
  ''' Beginning of part 4
! ''' $Header: perl.man.4,v 3.0.1.4 89/12/21 20:12:39 lwall Locked $
  '''
  ''' $Log:	perl.man.4,v $
  ''' Revision 3.0.1.4  89/12/21  20:12:39  lwall
  ''' patch7: documented that package'filehandle works as well as $package'variable
  ''' patch7: documented which identifiers are always in package main
--- 1,10 ----
  ''' Beginning of part 4
! ''' $Header: perl.man.4,v 3.0.1.5 90/02/28 18:01:52 lwall Locked $
  '''
  ''' $Log:	perl.man.4,v $
+ ''' Revision 3.0.1.5  90/02/28  18:01:52  lwall
+ ''' patch9: $0 is now always the command name
+ ''' 
  ''' Revision 3.0.1.4  89/12/21  20:12:39  lwall
  ''' patch7: documented that package'filehandle works as well as $package'variable
  ''' patch7: documented which identifiers are always in package main
***************
*** 263,269 ****
  not be relied upon.)
  $+ returns whatever the last bracket match matched.
  $& returns the entire matched string.
! ($0 normally returns the same thing, but don't depend on it.)
  $\` returns everything before the matched string.
  $\' returns everything after the matched string.
  Examples:
--- 266,272 ----
  not be relied upon.)
  $+ returns whatever the last bracket match matched.
  $& returns the entire matched string.
! ($0 used to return the same thing, but not any more.)
  $\` returns everything before the matched string.
  $\' returns everything after the matched string.
  Examples:
***************
*** 746,753 ****
  Contains the name of the file containing the
  .I perl
  script being executed.
- The value should be copied elsewhere before any pattern matching happens, which
- clobbers $0.
  (Mnemonic: same as sh and ksh.)
  .Ip $<digit> 8
  Contains the subpattern from the corresponding set of parentheses in the last
--- 749,754 ----
***************
*** 1168,1177 ****
  For instance, you could make aliases like these:
  .nf
  
!     $DBalias{'len'} = 's/^len(.*)/p length(\e$1)/';
!     $DBalias{'stop'} = 's/^stop (at|in)/b/';
!     $DBalias{'.'} =
!       's/^./p "\e$DBsub(\e$DBline):\et\e$DBline[\e$DBline]"/';
  
  .fi
  .Sh "Setuid Scripts"
--- 1169,1178 ----
  For instance, you could make aliases like these:
  .nf
  
!     $DB'alias{'len'} = 's/^len(.*)/p length($1)/';
!     $DB'alias{'stop'} = 's/^stop (at|in)/b/';
!     $DB'alias{'.'} =
!       's/^\e./p "\e$DB\e'sub(\e$DB\e'line):\et",\e$DB\e'line[\e$DB\e'line]/';
  
  .fi
  .Sh "Setuid Scripts"
***************
*** 1360,1367 ****
  .Ip * 4 2
  The current input line is normally in $_, not $0.
  It generally does not have the newline stripped.
! ($0 is initially the name of the program executed, then the last matched
! string.)
  .Ip * 4 2
  $<digit> does not refer to fields\*(--it refers to substrings matched by the last
  match pattern.
--- 1361,1367 ----
  .Ip * 4 2
  The current input line is normally in $_, not $0.
  It generally does not have the newline stripped.
! ($0 is the name of the program executed.)
  .Ip * 4 2
  $<digit> does not refer to fields\*(--it refers to substrings matched by the last
  match pattern.
***************
*** 1409,1415 ****
  	  OFS	\h'|2.5i'$,
  	  ORS	\h'|2.5i'$\e
  	  RLENGTH	\h'|2.5i'length($&)
! 	  RS	\h'|2.5i'$\/
  	  RSTART	\h'|2.5i'length($\`)
  	  SUBSEP	\h'|2.5i'$;
  
--- 1409,1415 ----
  	  OFS	\h'|2.5i'$,
  	  ORS	\h'|2.5i'$\e
  	  RLENGTH	\h'|2.5i'length($&)
! 	  RS	\h'|2.5i'$/
  	  RSTART	\h'|2.5i'length($\`)
  	  SUBSEP	\h'|2.5i'$;
  

Index: perl.y
Prereq: 3.0.1.3
*** perl.y.old	Thu Mar  1 10:53:40 1990
--- perl.y	Thu Mar  1 10:53:42 1990
***************
*** 1,4 ****
! /* $Header: perl.y,v 3.0.1.3 89/12/21 20:13:41 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
--- 1,4 ----
! /* $Header: perl.y,v 3.0.1.4 90/02/28 18:03:23 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
***************
*** 6,11 ****
--- 6,14 ----
   *    as specified in the README file that comes with the perl 3.0 kit.
   *
   * $Log:	perl.y,v $
+  * Revision 3.0.1.4  90/02/28  18:03:23  lwall
+  * patch9: line numbers were bogus during certain portions of foreach evaluation
+  * 
   * Revision 3.0.1.3  89/12/21  20:13:41  lwall
   * patch7: send() didn't allow a TO argument
   * 
***************
*** 229,234 ****
--- 232,239 ----
  					  stab2arg(A_STAB,scrstab),
  					  Nullarg,Nullarg ),
  					$7)))));
+ 				$$->c_line = $2;
+ 				$$->c_head->c_line = $2;
  			    }
  			    else {
  				$$ = wopt(over($3,add_label($1,
***************
*** 254,259 ****
--- 259,266 ----
  					  stab2arg(A_STAB,scrstab),
  					  Nullarg,Nullarg ),
  					$6)))));
+ 				$$->c_line = $2;
+ 				$$->c_head->c_line = $2;
  			    }
  			    else {	/* lisp, anyone? */
  				$$ = wopt(over(defstab,add_label($1,

Index: perly.c
Prereq: 3.0.1.3
*** perly.c.old	Thu Mar  1 10:53:50 1990
--- perly.c	Thu Mar  1 10:53:53 1990
***************
*** 1,4 ****
! char rcsid[] = "$Header: perly.c,v 3.0.1.3 89/12/21 20:15:41 lwall Locked $\nPatch level: ###\n";
  /*
   *    Copyright (c) 1989, Larry Wall
   *
--- 1,4 ----
! char rcsid[] = "$Header: perly.c,v 3.0.1.4 90/02/28 18:06:41 lwall Locked $\nPatch level: ###\n";
  /*
   *    Copyright (c) 1989, Larry Wall
   *
***************
*** 6,11 ****
--- 6,16 ----
   *    as specified in the README file that comes with the perl 3.0 kit.
   *
   * $Log:	perly.c,v $
+  * Revision 3.0.1.4  90/02/28  18:06:41  lwall
+  * patch9: perl can now start up other interpreters scripts
+  * patch9: nested evals clobbered their longjmp environment
+  * patch9: eval could mistakenly return undef in array context
+  * 
   * Revision 3.0.1.3  89/12/21  20:15:41  lwall
   * patch7: ANSI strerror() is now supported
   * patch7: errno may now be a macro with an lvalue
***************
*** 48,54 ****
      register char *s;
      char *index(), *strcpy(), *getenv();
      bool dosearch = FALSE;
-     char **origargv = argv;
  #ifdef DOSUID
      char *validarg = "";
  #endif
--- 53,58 ----
***************
*** 61,66 ****
--- 65,72 ----
  #endif
  #endif
  
+     origargv = argv;
+     origargc = argc;
      uid = (int)getuid();
      euid = (int)geteuid();
      gid = (int)getgid();
***************
*** 67,73 ****
      egid = (int)getegid();
      if (do_undump) {
  	do_undump = 0;
! 	loop_ptr = 0;		/* start label stack again */
  	goto just_doit;
      }
      (void)sprintf(index(rcsid,'#'), "%d\n", PATCHLEVEL);
--- 73,79 ----
      egid = (int)getegid();
      if (do_undump) {
  	do_undump = 0;
! 	loop_ptr = -1;		/* start label stack again */
  	goto just_doit;
      }
      (void)sprintf(index(rcsid,'#'), "%d\n", PATCHLEVEL);
***************
*** 670,676 ****
  	str_numset(STAB_STR(tmpstab),(double)getpid());
  
      if (setjmp(top_env))	/* sets goto_targ on longjump */
! 	loop_ptr = 0;		/* start label stack again */
  
  #ifdef DEBUGGING
      if (debug & 1024)
--- 676,682 ----
  	str_numset(STAB_STR(tmpstab),(double)getpid());
  
      if (setjmp(top_env))	/* sets goto_targ on longjump */
! 	loop_ptr = -1;		/* start label stack again */
  
  #ifdef DEBUGGING
      if (debug & 1024)
***************
*** 719,732 ****
      CMD *myroot;
      ARRAY *ar;
      int i;
!     char *oldfile = filename;
!     line_t oldline = line;
!     int oldtmps_base = tmps_base;
!     int oldsave = savestack->ary_fill;
!     SPAT *oldspat = curspat;
      static char *last_eval = Nullch;
      static CMD *last_root = Nullcmd;
      VOLATILE int sp = arglast[0];
  
      tmps_base = tmps_max;
      if (curstash != stash) {
--- 725,739 ----
      CMD *myroot;
      ARRAY *ar;
      int i;
!     char * VOLATILE oldfile = filename;
!     VOLATILE line_t oldline = line;
!     VOLATILE int oldtmps_base = tmps_base;
!     VOLATILE int oldsave = savestack->ary_fill;
!     SPAT * VOLATILE oldspat = curspat;
      static char *last_eval = Nullch;
      static CMD *last_root = Nullcmd;
      VOLATILE int sp = arglast[0];
+     char *tmps;
  
      tmps_base = tmps_max;
      if (curstash != stash) {
***************
*** 772,778 ****
      in_eval++;
      oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
      bufend = bufptr + linestr->str_cur;
!     if (setjmp(eval_env)) {
  	retval = 1;
  	last_root = Nullcmd;
      }
--- 779,796 ----
      in_eval++;
      oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
      bufend = bufptr + linestr->str_cur;
!     if (++loop_ptr >= loop_max) {
! 	loop_max += 128;
! 	Renew(loop_stack, loop_max, struct loop);
!     }
!     loop_stack[loop_ptr].loop_label = "_EVAL_";
!     loop_stack[loop_ptr].loop_sp = sp;
! #ifdef DEBUGGING
!     if (debug & 4) {
! 	deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
!     }
! #endif
!     if (setjmp(loop_stack[loop_ptr].loop_env)) {
  	retval = 1;
  	last_root = Nullcmd;
      }
***************
*** 800,806 ****
      }
      myroot = eval_root;		/* in case cmd_exec does another eval! */
      if (retval || error_count) {
! 	str = &str_undef;
  	last_root = Nullcmd;	/* can't free on error, for some reason */
  	if (rsfp) {
  	    fclose(rsfp);
--- 818,827 ----
      }
      myroot = eval_root;		/* in case cmd_exec does another eval! */
      if (retval || error_count) {
! 	st = stack->ary_array;
! 	sp = arglast[0];
! 	if (gimme != G_ARRAY)
! 	    st[++sp] = &str_undef;
  	last_root = Nullcmd;	/* can't free on error, for some reason */
  	if (rsfp) {
  	    fclose(rsfp);
***************
*** 817,822 ****
--- 838,851 ----
  	    cmd_free(myroot);
      }
      in_eval--;
+ #ifdef DEBUGGING
+ 	if (debug & 4) {
+ 	    tmps = loop_stack[loop_ptr].loop_label;
+ 	    deb("(Popping label #%d %s)\n",loop_ptr,
+ 		tmps ? tmps : "" );
+ 	}
+ #endif
+     loop_ptr--;
      filename = oldfile;
      line = oldline;
      tmps_base = oldtmps_base;

Index: regcomp.c
Prereq: 3.0.1.1
*** regcomp.c.old	Thu Mar  1 10:54:00 1990
--- regcomp.c	Thu Mar  1 10:54:02 1990
***************
*** 7,15 ****
   * blame Henry for some of the lack of readability.
   */
  
! /* $Header: regcomp.c,v 3.0.1.1 89/11/11 04:51:04 lwall Locked $
   *
   * $Log:	regcomp.c,v $
   * Revision 3.0.1.1  89/11/11  04:51:04  lwall
   * patch2: /[\000]/ didn't work
   * 
--- 7,18 ----
   * blame Henry for some of the lack of readability.
   */
  
! /* $Header: regcomp.c,v 3.0.1.2 90/02/28 18:08:35 lwall Locked $
   *
   * $Log:	regcomp.c,v $
+  * Revision 3.0.1.2  90/02/28  18:08:35  lwall
+  * patch9: /[\200-\377]/ didn't work on machines with signed chars
+  * 
   * Revision 3.0.1.1  89/11/11  04:51:04  lwall
   * patch2: /[\000]/ didn't work
   * 
***************
*** 770,775 ****
--- 773,779 ----
  {
  	if (regcode == &regdummy)
  	    return;
+ 	c &= 255;
  	if (def)
  		bits[c >> 3] &= ~(1 << (c & 7));
  	else

Index: regexec.c
Prereq: 3.0.1.2
*** regexec.c.old	Thu Mar  1 10:54:11 1990
--- regexec.c	Thu Mar  1 10:54:13 1990
***************
*** 7,15 ****
   * blame Henry for some of the lack of readability.
   */
  
! /* $Header: regexec.c,v 3.0.1.2 89/12/21 20:16:27 lwall Locked $
   *
   * $Log:	regexec.c,v $
   * Revision 3.0.1.2  89/12/21  20:16:27  lwall
   * patch7: certain patterns didn't match correctly at end of string
   * 
--- 7,20 ----
   * blame Henry for some of the lack of readability.
   */
  
! /* $Header: regexec.c,v 3.0.1.3 90/02/28 18:14:39 lwall Locked $
   *
   * $Log:	regexec.c,v $
+  * Revision 3.0.1.3  90/02/28  18:14:39  lwall
+  * patch9: /[\200-\377]/ didn't work on machines with signed chars
+  * patch9: \d, \w, and \s could misfire on characters with high bit set
+  * patch9: /\bfoo/i didn't work
+  * 
   * Revision 3.0.1.2  89/12/21  20:16:27  lwall
   * patch7: certain patterns didn't match correctly at end of string
   * 
***************
*** 64,69 ****
--- 69,79 ----
  int regnarrate = 0;
  #endif
  
+ #define isALNUM(c) (isascii(c) && (isalpha(c) || isdigit(c) || c == '_'))
+ #define isSPACE(c) (isascii(c) && isspace(c))
+ #define isDIGIT(c) (isascii(c) && isdigit(c))
+ #define isUPPER(c) (isascii(c) && isupper(c))
+ 
  /*
   * regexec and friends
   */
***************
*** 73,78 ****
--- 83,89 ----
   */
  static char *regprecomp;
  static char *reginput;		/* String-input pointer. */
+ static char regprev;		/* char before regbol, \n if none */
  static char *regbol;		/* Beginning of input, for ^ check. */
  static char *regeol;		/* End of input, for $ check. */
  static char **regstartp;	/* Pointer to startp array. */
***************
*** 112,118 ****
  	register int tmp;
  	int minlen = 0;		/* must match at least this many chars */
  	int dontbother = 0;	/* how many characters not to try at end */
- 	int beginning = (string == strbeg);	/* is ^ valid at stringarg? */
  
  	/* Be paranoid... */
  	if (prog == NULL || string == NULL) {
--- 123,128 ----
***************
*** 120,125 ****
--- 130,139 ----
  		return(0);
  	}
  
+ 	if (string == strbeg)	/* is ^ valid at stringarg? */
+ 	    regprev = '\n';
+ 	else
+ 	    regprev = stringarg[-1];
  	regprecomp = prog->precomp;
  	/* Check validity of program. */
  	if (UCHARAT(prog->program) != MAGIC) {
***************
*** 134,140 ****
  		string = c;
  		strend = string + i;
  		for (s = string; s < strend; s++)
! 			if (isupper(*s))
  				*s = tolower(*s);
  	}
  
--- 148,154 ----
  		string = c;
  		strend = string + i;
  		for (s = string; s < strend; s++)
! 			if (isUPPER(*s))
  				*s = tolower(*s);
  	}
  
***************
*** 141,147 ****
  	/* If there is a "must appear" string, look for it. */
  	s = string;
  	if (prog->regmust != Nullstr) {
! 		if (beginning && screamer) {
  			if (screamfirst[prog->regmust->str_rare] >= 0)
  				s = screaminstr(screamer,prog->regmust);
  			else
--- 155,161 ----
  	/* If there is a "must appear" string, look for it. */
  	s = string;
  	if (prog->regmust != Nullstr) {
! 		if (stringarg == strbeg && screamer) {
  			if (screamfirst[prog->regmust->str_rare] >= 0)
  				s = screaminstr(screamer,prog->regmust);
  			else
***************
*** 174,183 ****
  	}
  
  	/* Mark beginning of line for ^ . */
! 	if (beginning)
! 		regbol = string;
! 	else
! 		regbol = NULL;
  
  	/* Mark end of line for $ (and such) */
  	regeol = strend;
--- 188,194 ----
  	}
  
  	/* Mark beginning of line for ^ . */
! 	regbol = string;
  
  	/* Mark end of line for $ (and such) */
  	regeol = strend;
***************
*** 243,249 ****
  		case ANYOF: case ANYBUT:
  		    c = OPERAND(c);
  		    while (s < strend) {
! 			    i = *s;
  			    if (!(c[i >> 3] & (1 << (i&7))))
  				    if (regtry(prog, s))
  					    goto got_it;
--- 254,260 ----
  		case ANYOF: case ANYBUT:
  		    c = OPERAND(c);
  		    while (s < strend) {
! 			    i = UCHARAT(s);
  			    if (!(c[i >> 3] & (1 << (i&7))))
  				    if (regtry(prog, s))
  					    goto got_it;
***************
*** 255,267 ****
  			dontbother++,strend--;
  		    if (s != string) {
  			i = s[-1];
! 			tmp = (isalpha(i) || isdigit(i) || i == '_');
  		    }
  		    else
! 			tmp = 0;	/* assume not alphanumeric */
  		    while (s < strend) {
  			    i = *s;
! 			    if (tmp != (isalpha(i) || isdigit(i) || i == '_')) {
  				    tmp = !tmp;
  				    if (regtry(prog, s))
  					    goto got_it;
--- 266,278 ----
  			dontbother++,strend--;
  		    if (s != string) {
  			i = s[-1];
! 			tmp = isALNUM(i);
  		    }
  		    else
! 			tmp = isALNUM(regprev);	/* assume not alphanumeric */
  		    while (s < strend) {
  			    i = *s;
! 			    if (tmp != isALNUM(i)) {
  				    tmp = !tmp;
  				    if (regtry(prog, s))
  					    goto got_it;
***************
*** 276,288 ****
  			dontbother++,strend--;
  		    if (s != string) {
  			i = s[-1];
! 			tmp = (isalpha(i) || isdigit(i) || i == '_');
  		    }
  		    else
! 			tmp = 0;	/* assume not alphanumeric */
  		    while (s < strend) {
  			    i = *s;
! 			    if (tmp != (isalpha(i) || isdigit(i) || i == '_'))
  				    tmp = !tmp;
  			    else if (regtry(prog, s))
  				    goto got_it;
--- 287,299 ----
  			dontbother++,strend--;
  		    if (s != string) {
  			i = s[-1];
! 			tmp = isALNUM(i);
  		    }
  		    else
! 			tmp = isALNUM(regprev);	/* assume not alphanumeric */
  		    while (s < strend) {
  			    i = *s;
! 			    if (tmp != isALNUM(i))
  				    tmp = !tmp;
  			    else if (regtry(prog, s))
  				    goto got_it;
***************
*** 294,300 ****
  		case ALNUM:
  		    while (s < strend) {
  			    i = *s;
! 			    if (isalpha(i) || isdigit(i) || i == '_')
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
--- 305,311 ----
  		case ALNUM:
  		    while (s < strend) {
  			    i = *s;
! 			    if (isALNUM(i))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
***************
*** 303,309 ****
  		case NALNUM:
  		    while (s < strend) {
  			    i = *s;
! 			    if (!isalpha(i) && !isdigit(i) && i != '_')
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
--- 314,320 ----
  		case NALNUM:
  		    while (s < strend) {
  			    i = *s;
! 			    if (!isALNUM(i))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
***************
*** 311,317 ****
  		    break;
  		case SPACE:
  		    while (s < strend) {
! 			    if (isspace(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
--- 322,328 ----
  		    break;
  		case SPACE:
  		    while (s < strend) {
! 			    if (isSPACE(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
***************
*** 319,325 ****
  		    break;
  		case NSPACE:
  		    while (s < strend) {
! 			    if (!isspace(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
--- 330,336 ----
  		    break;
  		case NSPACE:
  		    while (s < strend) {
! 			    if (!isSPACE(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
***************
*** 327,333 ****
  		    break;
  		case DIGIT:
  		    while (s < strend) {
! 			    if (isdigit(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
--- 338,344 ----
  		    break;
  		case DIGIT:
  		    while (s < strend) {
! 			    if (isDIGIT(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
***************
*** 335,341 ****
  		    break;
  		case NDIGIT:
  		    while (s < strend) {
! 			    if (!isdigit(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
--- 346,352 ----
  		    break;
  		case NDIGIT:
  		    while (s < strend) {
! 			    if (!isDIGIT(*s))
  				    if (regtry(prog, s))
  					    goto got_it;
  			    s++;
***************
*** 471,477 ****
  
  		switch (OP(scan)) {
  		case BOL:
! 			if (locinput == regbol ||
  			    ((nextchar || locinput < regeol) &&
  			      locinput[-1] == '\n') )
  			{
--- 482,488 ----
  
  		switch (OP(scan)) {
  		case BOL:
! 			if (locinput == regbol ? regprev == '\n' :
  			    ((nextchar || locinput < regeol) &&
  			      locinput[-1] == '\n') )
  			{
***************
*** 517,524 ****
  		case ALNUM:
  			if (!nextchar)
  				return(0);
! 			if (!isalpha(nextchar) && !isdigit(nextchar) &&
! 			  nextchar != '_')
  				return(0);
  			nextchar = *++locinput;
  			break;
--- 528,534 ----
  		case ALNUM:
  			if (!nextchar)
  				return(0);
! 			if (!isALNUM(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
***************
*** 525,532 ****
  		case NALNUM:
  			if (!nextchar && locinput >= regeol)
  				return(0);
! 			if (isalpha(nextchar) || isdigit(nextchar) ||
! 			  nextchar == '_')
  				return(0);
  			nextchar = *++locinput;
  			break;
--- 535,541 ----
  		case NALNUM:
  			if (!nextchar && locinput >= regeol)
  				return(0);
! 			if (isALNUM(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
***************
*** 533,545 ****
  		case NBOUND:
  		case BOUND:
  			if (locinput == regbol)	/* was last char in word? */
! 				ln = 0;
  			else 
! 				ln = (isalpha(locinput[-1]) ||
! 				     isdigit(locinput[-1]) ||
! 				     locinput[-1] == '_' );
! 			n = (isalpha(nextchar) || isdigit(nextchar) ||
! 			    nextchar == '_' );	/* is next char in word? */
  			if ((ln == n) == (OP(scan) == BOUND))
  				return(0);
  			break;
--- 542,551 ----
  		case NBOUND:
  		case BOUND:
  			if (locinput == regbol)	/* was last char in word? */
! 				ln = isALNUM(regprev);
  			else 
! 				ln = isALNUM(locinput[-1]);
! 			n = isALNUM(nextchar); /* is next char in word? */
  			if ((ln == n) == (OP(scan) == BOUND))
  				return(0);
  			break;
***************
*** 546,552 ****
  		case SPACE:
  			if (!nextchar && locinput >= regeol)
  				return(0);
! 			if (!isspace(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
--- 552,558 ----
  		case SPACE:
  			if (!nextchar && locinput >= regeol)
  				return(0);
! 			if (!isSPACE(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
***************
*** 553,564 ****
  		case NSPACE:
  			if (!nextchar)
  				return(0);
! 			if (isspace(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
  		case DIGIT:
! 			if (!isdigit(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
--- 559,570 ----
  		case NSPACE:
  			if (!nextchar)
  				return(0);
! 			if (isSPACE(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
  		case DIGIT:
! 			if (!isDIGIT(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
***************
*** 565,571 ****
  		case NDIGIT:
  			if (!nextchar && locinput >= regeol)
  				return(0);
! 			if (isdigit(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
--- 571,577 ----
  		case NDIGIT:
  			if (!nextchar && locinput >= regeol)
  				return(0);
! 			if (isDIGIT(nextchar))
  				return(0);
  			nextchar = *++locinput;
  			break;
***************
*** 762,789 ****
  		}
  		break;
  	case ALNUM:
! 		while (isalpha(*scan) || isdigit(*scan) || *scan == '_')
  			scan++;
  		break;
  	case NALNUM:
! 		while (scan < loceol && (!isalpha(*scan) && !isdigit(*scan) &&
! 		  *scan != '_'))
  			scan++;
  		break;
  	case SPACE:
! 		while (scan < loceol && isspace(*scan))
  			scan++;
  		break;
  	case NSPACE:
! 		while (scan < loceol && !isspace(*scan))
  			scan++;
  		break;
  	case DIGIT:
! 		while (isdigit(*scan))
  			scan++;
  		break;
  	case NDIGIT:
! 		while (scan < loceol && !isdigit(*scan))
  			scan++;
  		break;
  	default:		/* Oh dear.  Called inappropriately. */
--- 768,794 ----
  		}
  		break;
  	case ALNUM:
! 		while (isALNUM(*scan))
  			scan++;
  		break;
  	case NALNUM:
! 		while (scan < loceol && !isALNUM(*scan))
  			scan++;
  		break;
  	case SPACE:
! 		while (scan < loceol && isSPACE(*scan))
  			scan++;
  		break;
  	case NSPACE:
! 		while (scan < loceol && !isSPACE(*scan))
  			scan++;
  		break;
  	case DIGIT:
! 		while (isDIGIT(*scan))
  			scan++;
  		break;
  	case NDIGIT:
! 		while (scan < loceol && !isDIGIT(*scan))
  			scan++;
  		break;
  	default:		/* Oh dear.  Called inappropriately. */

*** End of Patch 11 ***