perl 3.0 patch #23

Larry Wall lwall at jpl-devvax.JPL.NASA.GOV
Sat Aug 11 07:28:37 AEST 1990


System: perl version 3.0
Patch #: 23
Priority: 
Subject: patch #19, continued

Description:
	See patch #19.

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 #27 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 at 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: 22
1c1
< #define PATCHLEVEL 22
---
> #define PATCHLEVEL 23

Index: h2pl/mksizes
*** h2pl/mksizes.old	Thu Aug  9 05:59:47 1990
--- h2pl/mksizes	Thu Aug  9 05:59:48 1990
***************
*** 0 ****
--- 1,42 ----
+ #!/usr/local/bin/perl
+ 
+ ($iam = $0) =~ s%.*/%%;
+ $tmp = "$iam.$$";
+ open (CODE,">$tmp.c") || die "$iam: cannot create $tmp.c: $!\n";
+ 
+ $mask = q/printf ("$sizeof{'%s'} = %d;\n"/; 
+ 
+ # write C program
+ select(CODE);
+ 
+ print <<EO_C_PROGRAM;
+ #include <sys/param.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if_arp.h>
+ #include <net/if.h>
+ #include <net/route.h>
+ #include <sys/ioctl.h>
+ 
+ main() {
+ EO_C_PROGRAM
+ 
+ while ( <> ) {
+     chop;
+     printf "\t%s, \n\t\t\"%s\", sizeof(%s));\n", $mask, $_,$_;
+ }
+ 
+ print "\n}\n";
+ 
+ close CODE;
+ 
+ # compile C program
+ 
+ select(STDOUT);
+ 
+ system "cc $tmp.c -o $tmp";
+ die "couldn't compile $tmp.c" if $?;
+ system "./$tmp"; 	   
+ die "couldn't run $tmp" if $?;
+ 
+ unlink "$tmp.c", $tmp;

Index: h2pl/mkvars
*** h2pl/mkvars.old	Thu Aug  9 05:59:51 1990
--- h2pl/mkvars	Thu Aug  9 05:59:53 1990
***************
*** 0 ****
--- 1,31 ----
+ #!/usr/bin/perl
+ 
+ require 'sizeof.ph';
+ 
+ $LIB = '/usr/local/lib/perl';
+ 
+ foreach $include (@ARGV) {
+     printf STDERR "including %s\n", $include;
+     do $include;
+     warn "sourcing $include: $@\n" if ($@);
+     if (!open (INCLUDE,"$LIB/$include")) {
+ 	warn "can't open $LIB/$include: $!\n"; 
+ 	next; 
+     } 
+     while (<INCLUDE>) {
+ 	chop;
+ 	if (/^\s*eval\s+'sub\s+(\w+)\s.*[^{]$/ || /^\s*sub\s+(\w+)\s.*[^{]$/) {
+ 	    $var = $1;
+ 	    $val = eval "&$var;";
+ 	    if ($@) {
+ 		warn "$@: $_";
+ 		print <<EOT
+ warn "\$$var isn't correctly set" if defined \$_main{'$var'};
+ EOT
+ 		next;
+ 	    } 
+ 	    ( $nval = sprintf ("%x",$val ) ) =~ tr/a-z/A-Z/;
+ 	    printf "\$%s = 0x%s;\n", $var, $nval;
+ 	} 
+     }
+ } 

Index: usub/mus
*** usub/mus.old	Thu Aug  9 06:01:56 1990
--- usub/mus	Thu Aug  9 06:01:58 1990
***************
*** 0 ****
--- 1,129 ----
+ #!/usr/bin/perl
+ 
+ while (<>) {
+     if (s/^CASE\s+//) {
+ 	@fields = split;
+ 	$funcname = pop(@fields);
+ 	$rettype = "@fields";
+ 	@modes = ();
+ 	@types = ();
+ 	@names = ();
+ 	@outies = ();
+ 	@callnames = ();
+ 	$pre = "\n";
+ 	$post = '';
+ 
+ 	while (<>) {
+ 	    last unless /^[IO]+\s/;
+ 	    @fields = split(' ');
+ 	    push(@modes, shift(@fields));
+ 	    push(@names, pop(@fields));
+ 	    push(@types, "@fields");
+ 	}
+ 	while (s/^<\s//) {
+ 	    $pre .= "\t    $_";
+ 	    $_ = <>;
+ 	}
+ 	while (s/^>\s//) {
+ 	    $post .= "\t    $_";
+ 	    $_ = <>;
+ 	}
+ 	$items = @names;
+ 	$namelist = '$' . join(', $', @names);
+ 	$namelist = '' if $namelist eq '$';
+ 	print <<EOF;
+     case US_$funcname:
+ 	if (items != $items)
+ 	    fatal("Usage: &$funcname($namelist)");
+ 	else {
+ EOF
+ 	if ($rettype eq 'void') {
+ 	    print <<EOF;
+ 	    int retval = 1;
+ EOF
+ 	}
+ 	else {
+ 	    print <<EOF;
+ 	    $rettype retval;
+ EOF
+ 	}
+ 	foreach $i (1.. at names) {
+ 	    $mode = $modes[$i-1];
+ 	    $type = $types[$i-1];
+ 	    $name = $names[$i-1];
+ 	    if ($type =~ /^[A-Z]+\*$/) {
+ 		$cast = "*($type*)";
+ 	    }
+ 	    else {
+ 		$cast = "($type)";
+ 	    }
+ 	    $what = ($type =~ /^(struct\s+\w+|char|[A-Z]+)\s*\*$/ ? "get" : "gnum");
+ 	    $type .= "\t" if length($type) < 4;
+ 	    $cast .= "\t" if length($cast) < 8;
+ 	    $x = "\t" x (length($name) < 6);
+ 	    if ($mode =~ /O/) {
+ 		if ($what eq 'gnum') {
+ 		    push(@outies, "\t    str_numset(st[$i], (double) $name);\n");
+ 		}
+ 		else {
+ 		    push(@outies, "\t    str_set(st[$i], (char*) $name);\n");
+ 		}
+ 		push(@callnames, "&$name");
+ 	    }
+ 	    else {
+ 		push(@callnames, $name);
+ 	    }
+ 	    if ($mode =~ /I/) {
+ 	    print <<EOF;
+ 	    $type	$name =$x	$cast	str_$what(st[$i]);
+ EOF
+ 	    }
+ 	    else {
+ 		print <<EOF;
+ 	    $type	$name;
+ EOF
+ 	    }
+ 	}
+ 	$callnames = join(', ', @callnames);
+ 	$outies = join("\n", at outies);
+ 	if ($rettype eq 'void') {
+ 	    print <<EOF;
+ $pre	    (void)$funcname($callnames);
+ EOF
+ 	}
+ 	else {
+ 	    print <<EOF;
+ $pre	    retval = $funcname($callnames);
+ EOF
+ 	}
+ 	if ($rettype =~ /^(struct\s+\w+|char)\s*\*$/) {
+ 	    print <<EOF;
+ 	    str_set(st[0], (char*) retval);
+ EOF
+ 	}
+ 	elsif ($rettype =~ /^[A-Z]+\s*\*$/) {
+ 	    print <<EOF;
+ 	    str_set(st[0], (char*) &retval, sizeof retval);
+ EOF
+ 	}
+ 	else {
+ 	    print <<EOF;
+ 	    str_numset(st[0], (double) retval);
+ EOF
+ 	}
+ 	print $outies if $outies;
+ 	print $post if $post;
+ 	if (/^END/) {
+ 	    print "\t}\n\treturn sp;\n";
+ 	}
+ 	else {
+ 	    redo;
+ 	}
+     }
+     elsif (/^END/) {
+ 	print "\t}\n\treturn sp;\n";
+     }
+     else {
+ 	print;
+     }
+ }

Index: lib/nsyslog.pl
*** lib/nsyslog.pl.old	Thu Aug  9 06:00:41 1990
--- lib/nsyslog.pl	Thu Aug  9 06:00:43 1990
***************
*** 0 ****
--- 1,209 ----
+ #
+ # syslog.pl
+ #
+ # $Log:	nsyslog.pl,v $
+ # Revision 3.0.1.1  90/08/09  03:57:17  lwall
+ # patch19: Initial revision
+ # 
+ # Revision 1.2  90/06/11  18:45:30  18:45:30  root ()
+ # - Changed 'warn' to 'mail|warning' in test call (to give example of
+ #   facility specification, and because 'warn' didn't work on HP-UX).
+ # - Fixed typo in &openlog ("ncons" should be "cons").
+ # - Added (package-global) $maskpri, and &setlogmask.
+ # - In &syslog:
+ #   - put argument test ahead of &connect (why waste cycles?),
+ #   - allowed facility to be specified in &syslog's first arg (temporarily
+ #     overrides any $facility set in &openlog), just as in syslog(3C),
+ #   - do a return 0 when bit for $numpri not set in log mask (see syslog(3C)),
+ #   - changed $whoami code to use getlogin, getpwuid($<) and 'syslog'
+ #     (in that order) when $ident is null,
+ #   - made PID logging consistent with syslog(3C) and subject to $lo_pid only,
+ #   - fixed typo in "print CONS" statement ($<facility should be <$facility).
+ #   - changed \n to \r in print CONS (\r is useful, $message already has a \n).
+ # - Changed &xlate to return -1 for an unknown name, instead of croaking.
+ # 
+ #
+ # tom christiansen <tchrist at convex.com>
+ # modified to use sockets by Larry Wall <lwall at jpl-devvax.jpl.nasa.gov>
+ # NOTE: openlog now takes three arguments, just like openlog(3)
+ #
+ # call syslog() with a string priority and a list of printf() args
+ # like syslog(3)
+ #
+ #  usage: require 'syslog.pl';
+ #
+ #  then (put these all in a script to test function)
+ #		
+ #
+ #	do openlog($program,'cons,pid','user');
+ #	do syslog('info','this is another test');
+ #	do syslog('mail|warning','this is a better test: %d', time);
+ #	do closelog();
+ #	
+ #	do syslog('debug','this is the last test');
+ #	do openlog("$program $$",'ndelay','user');
+ #	do syslog('notice','fooprogram: this is really done');
+ #
+ #	$! = 55;
+ #	do syslog('info','problem was %m'); # %m == $! in syslog(3)
+ 
+ package syslog;
+ 
+ $host = 'localhost' unless $host;	# set $syslog'host to change
+ 
+ require '/usr/local/lib/perl/syslog.ph';
+ 
+ $maskpri = &LOG_UPTO(&LOG_DEBUG);
+ 
+ sub main'openlog {
+     ($ident, $logopt, $facility) = @_;  # package vars
+     $lo_pid = $logopt =~ /\bpid\b/;
+     $lo_ndelay = $logopt =~ /\bndelay\b/;
+     $lo_cons = $logopt =~ /\bcons\b/;
+     $lo_nowait = $logopt =~ /\bnowait\b/;
+     &connect if $lo_ndelay;
+ } 
+ 
+ sub main'closelog {
+     $facility = $ident = '';
+     &disconnect;
+ } 
+ 
+ sub main'setlogmask {
+     local($oldmask) = $maskpri;
+     $maskpri = shift;
+     $oldmask;
+ }
+  
+ sub main'syslog {
+     local($priority) = shift;
+     local($mask) = shift;
+     local($message, $whoami);
+     local(@words, $num, $numpri, $numfac, $sum);
+     local($facility) = $facility;	# may need to change temporarily.
+ 
+     die "syslog: expected both priority and mask" unless $mask && $priority;
+ 
+     @words = split(/\W+/, $priority, 2);# Allow "level" or "level|facility".
+     undef $numpri;
+     undef $numfac;
+     foreach (@words) {
+ 	$num = &xlate($_);		# Translate word to number.
+ 	if (/^kern$/ || $num < 0) {
+ 	    die "syslog: invalid level/facility: $_\n";
+ 	}
+ 	elsif ($num <= &LOG_PRIMASK) {
+ 	    die "syslog: too many levels given: $_\n" if defined($numpri);
+ 	    $numpri = $num;
+ 	    return 0 unless &LOG_MASK($numpri) & $maskpri;
+ 	}
+ 	else {
+ 	    die "syslog: too many facilities given: $_\n" if defined($numfac);
+ 	    $facility = $_;
+ 	    $numfac = $num;
+ 	}
+     }
+ 
+     die "syslog: level must be given\n" unless defined($numpri);
+ 
+     if (!defined($numfac)) {	# Facility not specified in this call.
+ 	$facility = 'user' unless $facility;
+ 	$numfac = &xlate($facility);
+     }
+ 
+     &connect unless $connected;
+ 
+     $whoami = $ident;
+ 
+     if (!$ident && $mask =~ /^(\S.*):\s?(.*)/) {
+ 	$whoami = $1;
+ 	$mask = $2;
+     } 
+ 
+     unless ($whoami) {
+ 	($whoami = getlogin) ||
+ 	    ($whoami = getpwuid($<)) ||
+ 		($whoami = 'syslog');
+     }
+ 
+     $whoami .= "[$$]" if $lo_pid;
+ 
+     $mask =~ s/%m/$!/g;
+     $mask .= "\n" unless $mask =~ /\n$/;
+     $message = sprintf ($mask, @_);
+ 
+     $sum = $numpri + $numfac;
+     unless (send(SYSLOG,"<$sum>$whoami: $message",0)) {
+ 	if ($lo_cons) {
+ 	    if ($pid = fork) {
+ 		unless ($lo_nowait) {
+ 		    do {$died = wait;} until $died == $pid || $died < 0;
+ 		}
+ 	    }
+ 	    else {
+ 		open(CONS,">/dev/console");
+ 		print CONS "<$facility.$priority>$whoami: $message\r";
+ 		exit if defined $pid;		# if fork failed, we're parent
+ 		close CONS;
+ 	    }
+ 	}
+     }
+ }
+ 
+ sub xlate {
+     local($name) = @_;
+     $name =~ y/a-z/A-Z/;
+     $name = "LOG_$name" unless $name =~ /^LOG_/;
+     $name = "syslog'$name";
+     eval &$name || -1;
+ }
+ 
+ sub connect {
+     $pat = 'S n C4 x8';
+ 
+     $af_unix = 1;
+     $af_inet = 2;
+ 
+     $stream = 1;
+     $datagram = 2;
+ 
+     ($name,$aliases,$proto) = getprotobyname('udp');
+     $udp = $proto;
+ 
+     ($name,$aliase,$port,$proto) = getservbyname('syslog','udp');
+     $syslog = $port;
+ 
+     if (chop($myname = `hostname`)) {
+ 	($name,$aliases,$addrtype,$length, at addrs) = gethostbyname($myname);
+ 	die "Can't lookup $myname\n" unless $name;
+ 	@bytes = unpack("C4",$addrs[0]);
+     }
+     else {
+ 	@bytes = (0,0,0,0);
+     }
+     $this = pack($pat, $af_inet, 0, @bytes);
+ 
+     if ($host =~ /^\d+\./) {
+ 	@bytes = split(/\./,$host);
+     }
+     else {
+ 	($name,$aliases,$addrtype,$length, at addrs) = gethostbyname($host);
+ 	die "Can't lookup $host\n" unless $name;
+ 	@bytes = unpack("C4",$addrs[0]);
+     }
+     $that = pack($pat,$af_inet,$syslog, at bytes);
+ 
+     socket(SYSLOG,$af_inet,$datagram,$udp) || die "socket: $!\n";
+     bind(SYSLOG,$this) || die "bind: $!\n";
+     connect(SYSLOG,$that) || die "connect: $!\n";
+ 
+     local($old) = select(SYSLOG); $| = 1; select($old);
+     $connected = 1;
+ }
+ 
+ sub disconnect {
+     close SYSLOG;
+     $connected = 0;
+ }
+ 
+ 1;

Index: t/op.pack
Prereq: 3.0
*** t/op.pack.old	Thu Aug  9 06:06:03 1990
--- t/op.pack	Thu Aug  9 06:06:03 1990
***************
*** 1,11 ****
  #!./perl
  
! # $Header: op.pack,v 3.0 89/10/18 15:30:39 lwall Locked $
  
  print "1..3\n";
  
! $format = "c2x5CCxsila6";
! @ary = (1,-100,127,128,32767,12345,123456,"abcdef");
  $foo = pack($format, at ary);
  @ary2 = unpack($format,$foo);
  
--- 1,13 ----
  #!./perl
  
! # $Header: op.pack,v 3.0.1.1 90/08/09 05:27:04 lwall Locked $
  
  print "1..3\n";
  
! $format = "c2x5CCxsdila6";
! # Need the expression in here to force ary[5] to be numeric.  This avoids
! # test2 failing because ary2 goes str->numeric->str and ary doesn't.
! @ary = (1,-100,127,128,32767,987.654321098 / 100.0,12345,123456,"abcdef");
  $foo = pack($format, at ary);
  @ary2 = unpack($format,$foo);
  

Index: os2/eg/os2.pl
*** os2/eg/os2.pl.old	Thu Aug  9 06:02:28 1990
--- os2/eg/os2.pl	Thu Aug  9 06:02:30 1990
***************
*** 0 ****
--- 1,70 ----
+ extproc C:\binp\misc\perl.exe -S
+ 
+ # os2.pl:  Demonstrates the OS/2 system calls and shows off some of the
+ # features in common with the UNIX version.
+ 
+ do "syscalls.pl" || die "Cannot load syscalls.pl ($!)";
+ 
+ # OS/2 version number.
+ 
+ 	$version = "  "; syscall($OS2_GetVersion,$version); 
+ 	($minor, $major) = unpack("CC", $version);
+ 	print "You are using OS/2 version ", int($major/10), 
+ 			".", int($minor/10), "\n\n";
+  
+ # Process ID.
+ 	print "This process ID is $$ and its parent's ID is ", 
+ 		getppid(), "\n\n";
+ 
+ # Priority.
+ 
+ 	printf "Current priority is %x\n", getpriority(0,0);
+ 	print "Changing priority by +5\n";
+ 	print "Failed!\n" unless setpriority(0,0,+5);
+ 	printf "Priority is now %x\n\n", getpriority(0,0);
+ 
+ # Beep.
+ 	print "Here is an A440.\n\n";
+ 	syscall($OS2_Beep,440,50);
+ 
+ # Pipes.  Unlike MS-DOS, OS/2 supports true asynchronous pipes.
+ 	open(ROT13, '|perl -pe y/a-zA-Z/n-za-mN-ZA-M/') || die;
+ 	select(ROT13); $|=1; select(STDOUT);
+ 	print "Type two lines of stuff, and I'll ROT13 it while you wait.\n".
+ 	      "If you type fast, you might be able to type both of your\n".
+ 	      "lines before I get a chance to translate the first line.\n";
+ 	$_ = <STDIN>; print ROT13 $_;
+ 	$_ = <STDIN>; print ROT13 $_;
+ 	close(ROT13);
+ 	print "Thanks.\n\n";
+ 
+ # Inspecting the disks.
+ 	print "Let's look at the disks you have installed...\n\n";
+ 
+ 	$x = "\0\0";
+ 	syscall($OS2_Config, $x, 2);
+ 	print "You have ", unpack("S", $x), " floppy disks,\n";
+ 
+ 	$x = "  ";
+ 	syscall($OS2_PhysicalDisk, 1, $x, 2, 0, 0);
+ 	($numdisks) = unpack("S", $x);
+ 
+ 	print "and $numdisks partitionable disks.\n\n";
+ 	for ($i = 1; $i <= $numdisks; $i++) {
+ 		$disk = $i . ":";
+ 		$handle = "  ";
+ 		syscall($OS2_PhysicalDisk, 2, $handle, 2, $disk, 3);
+ 		($numhandle) = unpack("S", $handle);
+ 		$zero = pack("C", 0);
+ 		$parmblock = " " x 16;
+ 		syscall($OS2_IOCtl, $parmblock, $zero, 0x63, 9, $numhandle);
+ 		($x, $cylinders, $heads, $sect) = unpack("SSSS", $parmblock);
+ 		print "Hard drive #$i:\n";
+ 		print "   cylinders: $cylinders\n";
+ 		print "       heads: $heads\n";
+ 		print "    sect/trk: $sect\n";
+ 		syscall($OS2_PhysicalDisk, 3, 0, 0, $handle, 2);
+ 	}
+ 
+ # I won't bother with the other stuff.  You get the idea.
+ 

Index: usub/pager
*** usub/pager.old	Thu Aug  9 06:02:01 1990
--- usub/pager	Thu Aug  9 06:02:02 1990
***************
*** 0 ****
--- 1,209 ----
+ #!./curseperl
+ 
+ eval <<'EndOfMain';   $evaloffset = 3;	# line number of this line
+ 
+     $| = 1;		# command buffering on stdout
+     &initterm;
+     &inithelp;
+     &slurpfile && &pagearray;
+ 
+ EndOfMain
+ 
+ &endwin;
+ 
+ if ($@) {
+     print "";		# force flush of stdout
+     $@ =~ s/\(eval\)/$0/ && $@ =~ s/line (\d+)/'line ' . ($1 + $evaloffset)/e;
+     die $@;
+ }
+ 
+ exit;
+ 
+ ################################################################################
+ 
+ sub initterm {
+ 
+     &initscr; &cbreak; &noecho; &scrollok($stdscr, 1);
+     &defbell unless defined &bell;
+ 
+     $lines = $LINES; $lines1 = $lines - 1; $lines2 = $lines - 2;
+     $cols = $COLS;   $cols1  = $cols  - 1; $cols2  = $cols  - 2;;
+ 
+     $dl = &getcap('dl');
+     $al = &getcap('al');
+     $ho = &getcap('ho');
+     $ce = &getcap('ce');
+ }
+ 
+ sub slurpfile {
+     while (<>) {
+ 	s/^(\t+)/'        ' x length($1)/e;
+ 	&expand($_) if /\t/;
+ 	if (length($_) < $cols) {
+ 	    push(@lines, $_);
+ 	}
+ 	else {
+ 	    while ($_ && $_ ne "\n") {
+ 		push(@lines, substr($_,0,$cols));
+ 		substr($_,0,$cols) = '';
+ 	    }
+ 	}
+     }
+     1;
+ }
+ 
+ sub drawscreen {
+     &move(0,0);
+     for ($line .. $line + $lines2) {
+ 	&addstr($lines[$_]);
+     }
+     &clrtobot;
+     &percent;
+     &refresh;
+ }
+ 
+ sub expand {
+     while (($off = index($_[0],"\t")) >= 0) {
+ 	substr($_[0], $off, 1) = ' ' x (8 - $off % 8);
+     }
+ }
+ 
+ sub pagearray {
+     $line = 0;
+ 
+     $| = 1;
+ 
+     for (&drawscreen;;&drawscreen) {
+ 
+ 	$ch = &getch;
+ 	$ch = "j" if $ch eq "\n";
+ 
+ 	if ($ch eq ' ') {
+ 	    last if $percent >= 100;
+ 	    &move(0,0);
+ 	    $line += $lines1;
+ 	}
+ 	elsif ($ch eq 'b') {
+ 	    $line -= $lines1;
+ 	    &move(0,0);
+ 	    $line = 0 if $line < 0;
+ 	}
+ 	elsif ($ch eq "j") {
+ 	    $line += 1;
+ 	    if ($dl) {
+ 		print $ho, $dl;
+ 		&mvcur(0,0,$lines2,0);
+ 		print $ce,$lines[$line+$lines2],$ce;
+ 		&wmove($curscr,0,0);
+ 		&wdeleteln($curscr);
+ 		&wmove($curscr,$lines2,0);
+ 		&waddstr($curscr,$lines[$line+$lines2]);
+ 	    }
+ 	    &wmove($stdscr,0,0);
+ 	    &wdeleteln($stdscr);
+ 	    &wmove($stdscr,$lines2,0);
+ 	    &waddstr($stdscr,$lines[$line+$lines2]);
+ 	    &percent;
+ 	    &refresh;
+ 	    redo;
+ 	}
+ 	elsif ($ch eq "k") {
+ 	    next if $line <= 0;
+ 	    $line -= 1;
+ 	    if ($al) {
+ 		print $ho, $al, $ce, $lines[$line];
+ 		&wmove($curscr,0,0);
+ 		&winsertln($curscr);
+ 		&waddstr($curscr,$lines[$line]);
+ 	    }
+ 	    &wmove($stdscr,0,0);
+ 	    &winsertln($stdscr);
+ 	    &waddstr($stdscr,$lines[$line]);
+ 	    &percent;
+ 	    &refresh;
+ 	    redo;
+ 	}
+ 	elsif ($ch eq "\f") {
+ 	    &clear;
+ 	}
+ 	elsif ($ch eq "q") {
+ 	    last;
+ 	}
+ 	elsif ($ch eq "h") {
+ 	    &clear;
+ 	    &help;
+ 	    &clear;
+ 	}
+ 	else {
+ 	    &bell;
+ 	}
+     }
+ }
+ 
+ sub defbell {
+     eval q#
+ 	sub bell {
+ 	    print "\007";
+ 	}
+     #;
+ }
+ 
+ sub help {
+     local(*lines) = *helplines;
+     local($line);
+     &pagearray;
+ }
+ 
+ sub inithelp {
+     @helplines = split(/\n/,<<'EOT');
+ 
+       Commands marked with * may be preceeded by a number, N.
+ 
+   h              Display this help.
+   q              Exit.
+ 
+   f, SPACE    *  Forward  N lines, default one screen.
+   b           *  Backward N lines, default one screen.
+   e, j, CR    *  Forward  N lines, default 1 line.
+   y, k        *  Backward N lines, default 1 line.
+   d           *  Forward  N lines, default 10 or last N to d or u command.
+   u           *  Backward N lines, default 10 or last N to d or u command.
+   r              Repaint screen.
+   R              Repaint screen, discarding buffered input.
+ 
+   /pattern    *  Search forward for N-th line containing the pattern.
+   ?pattern    *  Search backward for N-th line containing the pattern.
+   n           *  Repeat previous search (for N-th occurence).
+ 
+   g           *  Go to line N, default 1.
+   G           *  Like g, but default is last line in file.
+   p, %        *  Position to N percent into the file.
+   m<letter>      Mark the current position with <letter>.
+   '<letter>      Return to a previously marked position.
+   ''             Return to previous position.
+ 
+   E [file]       Examine a new file.
+   N           *  Examine the next file (from the command line).
+   P           *  Examine the previous file (from the command line).
+   =              Print current file name.
+   V              Print version number of "less".
+ 
+   -<flag>        Toggle a command line flag.
+   +cmd           Execute the less cmd each time a new file is examined.
+ 
+   !command       Passes the command to a shell to be executed.
+   v              Edit the current file with $EDITOR.
+ EOT
+     for (@helplines) {
+ 	s/$/\n/;
+     }
+ }
+ 
+ sub percent {
+     &standout;
+       $percent = int(($line + $lines1) * 100 / @lines);
+       &move($lines1,0);
+       &addstr("($percent%)");
+     &standend;
+     &clrtoeol;
+ }

Index: perl.h
Prereq: 3.0.1.7
*** perl.h.old	Thu Aug  9 06:02:50 1990
--- perl.h	Thu Aug  9 06:02:52 1990
***************
*** 1,4 ****
! /* $Header: perl.h,v 3.0.1.7 90/03/27 16:12:52 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
--- 1,4 ----
! /* $Header: perl.h,v 3.0.1.8 90/08/09 04:10:53 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
***************
*** 6,11 ****
--- 6,16 ----
   *    as specified in the README file that comes with the perl 3.0 kit.
   *
   * $Log:	perl.h,v $
+  * Revision 3.0.1.8  90/08/09  04:10:53  lwall
+  * patch19: various MSDOS and OS/2 patches folded in
+  * patch19: did preliminary work toward debugging packages and evals
+  * patch19: added -x switch to extract script from input trash
+  * 
   * Revision 3.0.1.7  90/03/27  16:12:52  lwall
   * patch16: MSDOS support
   * patch16: support for machines that can't cast negative floats to unsigned ints
***************
*** 134,144 ****
  
  #ifdef MEMCPY
  #ifndef memcpy
! #ifdef __STDC__
  extern void *memcpy(), *memset();
  #else
  extern char *memcpy(), *memset();
  #endif
  #endif
  #define bcopy(s1,s2,l) memcpy(s2,s1,l)
  #define bzero(s,l) memset(s,0,l)
--- 139,150 ----
  
  #ifdef MEMCPY
  #ifndef memcpy
! #if defined(__STDC__ ) || defined(MSDOS)
  extern void *memcpy(), *memset();
  #else
  extern char *memcpy(), *memset();
  #endif
+ extern int memcmp();
  #endif
  #define bcopy(s1,s2,l) memcpy(s2,s1,l)
  #define bzero(s,l) memset(s,0,l)
***************
*** 268,273 ****
--- 274,281 ----
  #   endif
  #endif
  
+ typedef unsigned int STRLEN;
+ 
  typedef struct arg ARG;
  typedef struct cmd CMD;
  typedef struct formcmd FCMD;
***************
*** 293,299 ****
  #include "array.h"
  #include "hash.h"
  
! #if defined(iAPX286) || defined(M_I286) || defined(I80286) || defined(M_I86)
  #   define I286
  #endif
  
--- 301,307 ----
  #include "array.h"
  #include "hash.h"
  
! #if defined(iAPX286) || defined(M_I286) || defined(I80286)
  #   define I286
  #endif
  
***************
*** 361,367 ****
--- 369,383 ----
  
  #define GROWSTR(pp,lp,len) if (*(lp) < (len)) growstr(pp,lp,len)
  
+ #ifndef MSDOS
  #define STR_GROW(str,len) if ((str)->str_len < (len)) str_grow(str,len)
+ #define Str_Grow str_grow
+ #else
+ /* extra parentheses intentionally NOT placed around "len"! */
+ #define STR_GROW(str,len) if ((str)->str_len < (unsigned long)len) \
+ 		str_grow(str,(unsigned long)len)
+ #define Str_Grow(str,len) str_grow(str,(unsigned long)(len))
+ #endif /* MSDOS */
  
  #ifndef BYTEORDER
  #define BYTEORDER 0x1234
***************
*** 504,510 ****
  
  EXT char **origargv;
  EXT int origargc;
- EXT line_t line INIT(0);
  EXT line_t subline INIT(0);
  EXT STR *subname INIT(Nullstr);
  EXT int arybase INIT(0);
--- 520,525 ----
***************
*** 547,552 ****
--- 562,568 ----
  EXT int lastspbase;
  EXT int lastsize;
  
+ EXT char *curpack;
  EXT char *filename;
  EXT char *origfilename;
  EXT FILE * VOLATILE rsfp;
***************
*** 574,579 ****
--- 590,596 ----
  EXT bool minus_a INIT(FALSE);
  EXT bool doswitches INIT(FALSE);
  EXT bool dowarn INIT(FALSE);
+ EXT bool doextract INIT(FALSE);
  EXT bool allstabs INIT(FALSE);	/* init all customary symbols in symbol table?*/
  EXT bool sawampersand INIT(FALSE);	/* must save all match strings */
  EXT bool sawstudy INIT(FALSE);		/* do fbminstr on all strings */
***************
*** 590,596 ****
--- 607,617 ----
  EXT bool tainted INIT(FALSE);		/* using variables controlled by $< */
  #endif
  
+ #ifndef MSDOS
  #define TMPPATH "/tmp/perl-eXXXXXX"
+ #else
+ #define TMPPATH "/tmp/plXXXXXX"
+ #endif /* MSDOS */
  EXT char *e_tmpname;
  EXT FILE *e_fp INIT(Nullfp);
  
***************
*** 657,662 ****
--- 678,689 ----
  EXT jmp_buf top_env;
  
  EXT char * VOLATILE goto_targ INIT(Nullch); /* cmd_exec gets strange when set */
+ 
+ struct ufuncs {
+     int (*uf_val)();
+     int (*uf_set)();
+     int uf_index;
+ };
  
  EXT ARRAY *stack;		/* THE STACK */
  

Index: perl.y
Prereq: 3.0.1.6
*** perl.y.old	Thu Aug  9 06:02:58 1990
--- perl.y	Thu Aug  9 06:03:01 1990
***************
*** 1,4 ****
! /* $Header: perl.y,v 3.0.1.6 90/03/27 16:13:45 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
--- 1,4 ----
! /* $Header: perl.y,v 3.0.1.7 90/08/09 04:17:44 lwall Locked $
   *
   *    Copyright (c) 1989, Larry Wall
   *
***************
*** 6,11 ****
--- 6,18 ----
   *    as specified in the README file that comes with the perl 3.0 kit.
   *
   * $Log:	perl.y,v $
+  * Revision 3.0.1.7  90/08/09  04:17:44  lwall
+  * patch19: did preliminary work toward debugging packages and evals
+  * patch19: added require operator
+  * patch19: bare identifiers are now strings if no other interpretation possible
+  * patch19: null-label lines threw off line number of next statement
+  * patch19: split; didn't pass correct bufend to scanpat
+  * 
   * Revision 3.0.1.6  90/03/27  16:13:45  lwall
   * patch16: formats didn't work inside eval
   * 
***************
*** 57,63 ****
  }
  
  %token <cval> WORD
! %token <ival> APPEND OPEN SELECT LOOPEX
  %token <ival> USING FORMAT DO SHIFT PUSH POP LVALFUN
  %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE SPLIT FLIST
  %token <ival> FOR FILOP FILOP2 FILOP3 FILOP4 FILOP22 FILOP25
--- 64,70 ----
  }
  
  %token <cval> WORD
! %token <ival> APPEND OPEN SSELECT LOOPEX
  %token <ival> USING FORMAT DO SHIFT PUSH POP LVALFUN
  %token <ival> WHILE UNTIL IF UNLESS ELSE ELSIF CONTINUE SPLIT FLIST
  %token <ival> FOR FILOP FILOP2 FILOP3 FILOP4 FILOP22 FILOP25
***************
*** 72,78 ****
  %type <ival> prog decl format remember
  %type <cmdval> block lineseq line loop cond sideff nexpr else
  %type <arg> expr sexpr cexpr csexpr term handle aryword hshword
! %type <arg> texpr listop
  %type <cval> label
  %type <compval> compblock
  
--- 79,85 ----
  %type <ival> prog decl format remember
  %type <cmdval> block lineseq line loop cond sideff nexpr else
  %type <arg> expr sexpr cexpr csexpr term handle aryword hshword
! %type <arg> texpr listop bareword
  %type <cval> label
  %type <compval> compblock
  
***************
*** 153,160 ****
  			{ if ($1 != Nullch) {
  			      $$ = add_label($1, make_acmd(C_EXPR, Nullstab,
  				  Nullarg, Nullarg) );
! 			    } else
! 			      $$ = Nullcmd; }
  	|	label sideff ';'
  			{ $$ = add_label($1,$2); }
  	;
--- 160,170 ----
  			{ if ($1 != Nullch) {
  			      $$ = add_label($1, make_acmd(C_EXPR, Nullstab,
  				  Nullarg, Nullarg) );
! 			    }
! 			    else {
! 			      $$ = Nullcmd;
! 			      cmdline = NOLINE;
! 			    } }
  	|	label sideff ';'
  			{ $$ = add_label($1,$2); }
  	;
***************
*** 228,234 ****
  				      l(make_op(O_ASSIGN,2,
  					listish(make_op(O_ARRAY, 1,
  					  stab2arg(A_STAB,scrstab),
! 					  Nullarg,Nullarg, 1)),
  					listish(make_list($5)),
  					Nullarg)),
  				      Nullarg),
--- 238,244 ----
  				      l(make_op(O_ASSIGN,2,
  					listish(make_op(O_ARRAY, 1,
  					  stab2arg(A_STAB,scrstab),
! 					  Nullarg,Nullarg )),
  					listish(make_list($5)),
  					Nullarg)),
  				      Nullarg),
***************
*** 255,261 ****
  				      l(make_op(O_ASSIGN,2,
  					listish(make_op(O_ARRAY, 1,
  					  stab2arg(A_STAB,scrstab),
! 					  Nullarg,Nullarg, 1 )),
  					listish(make_list($4)),
  					Nullarg)),
  				      Nullarg),
--- 265,271 ----
  				      l(make_op(O_ASSIGN,2,
  					listish(make_op(O_ARRAY, 1,
  					  stab2arg(A_STAB,scrstab),
! 					  Nullarg,Nullarg )),
  					listish(make_list($4)),
  					Nullarg)),
  				      Nullarg),
***************
*** 325,336 ****
  
  package :	PACKAGE WORD ';'
  			{ char tmpbuf[256];
  
  			  savehptr(&curstash);
  			  saveitem(curstname);
  			  str_set(curstname,$2);
  			  sprintf(tmpbuf,"'_%s",$2);
! 			  curstash = stab_xhash(hadd(stabent(tmpbuf,TRUE)));
  			  curstash->tbl_coeffsize = 0;
  			  Safefree($2);
  			}
--- 335,349 ----
  
  package :	PACKAGE WORD ';'
  			{ char tmpbuf[256];
+ 			  STAB *tmpstab;
  
  			  savehptr(&curstash);
  			  saveitem(curstname);
  			  str_set(curstname,$2);
  			  sprintf(tmpbuf,"'_%s",$2);
! 			  tmpstab = hadd(stabent(tmpbuf,TRUE));
! 			  curstash = stab_xhash(tmpstab);
! 			  curpack = stab_name(tmpstab);
  			  curstash->tbl_coeffsize = 0;
  			  Safefree($2);
  			}
***************
*** 569,585 ****
  			    Nullarg,Nullarg); }
  	|	UNIOP
  			{ $$ = make_op($1,0,Nullarg,Nullarg,Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET)
  			    $$ = fixeval($$); }
  	|	UNIOP sexpr
  			{ $$ = make_op($1,1,$2,Nullarg,Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET)
  			    $$ = fixeval($$); }
! 	|	SELECT
  			{ $$ = make_op(O_SELECT, 0, Nullarg, Nullarg, Nullarg);}
! 	|	SELECT '(' handle ')'
  			{ $$ = make_op(O_SELECT, 1, $3, Nullarg, Nullarg); }
! 	|	SELECT '(' sexpr csexpr csexpr csexpr ')'
  			{ arg4 = $6;
  			  $$ = make_op(O_SSELECT, 4, $3, $4, $5); }
  	|	OPEN WORD	%prec '('
--- 582,598 ----
  			    Nullarg,Nullarg); }
  	|	UNIOP
  			{ $$ = make_op($1,0,Nullarg,Nullarg,Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET || $1 == O_REQUIRE)
  			    $$ = fixeval($$); }
  	|	UNIOP sexpr
  			{ $$ = make_op($1,1,$2,Nullarg,Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET || $1 == O_REQUIRE)
  			    $$ = fixeval($$); }
! 	|	SSELECT
  			{ $$ = make_op(O_SELECT, 0, Nullarg, Nullarg, Nullarg);}
! 	|	SSELECT '(' handle ')'
  			{ $$ = make_op(O_SELECT, 1, $3, Nullarg, Nullarg); }
! 	|	SSELECT '(' sexpr csexpr csexpr csexpr ')'
  			{ arg4 = $6;
  			  $$ = make_op(O_SSELECT, 4, $3, $4, $5); }
  	|	OPEN WORD	%prec '('
***************
*** 646,652 ****
  			      aadd(stabent(subline ? "_" : "ARGV", TRUE))),
  			    Nullarg, Nullarg); }
  	|	SPLIT	%prec '('
! 			{ (void)scanpat("/\\s+/");
  			    $$ = make_split(defstab,yylval.arg,Nullarg); }
  	|	SPLIT '(' sexpr csexpr csexpr ')'
  			{ $$ = mod_match(O_MATCH, $4,
--- 659,665 ----
  			      aadd(stabent(subline ? "_" : "ARGV", TRUE))),
  			    Nullarg, Nullarg); }
  	|	SPLIT	%prec '('
! {static char p[]="/\\s+/";char*o=bufend;bufend=p+5;(void)scanpat(p);bufend=o;
  			    $$ = make_split(defstab,yylval.arg,Nullarg); }
  	|	SPLIT '(' sexpr csexpr csexpr ')'
  			{ $$ = mod_match(O_MATCH, $4,
***************
*** 681,691 ****
  			{ $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
  	|	FUNC1 '(' ')'
  			{ $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET)
  			    $$ = fixeval($$); }
  	|	FUNC1 '(' expr ')'
  			{ $$ = make_op($1, 1, $3, Nullarg, Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET)
  			    $$ = fixeval($$); }
  	|	FUNC2 '(' sexpr cexpr ')'
  			{ $$ = make_op($1, 2, $3, $4, Nullarg);
--- 694,704 ----
  			{ $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg); }
  	|	FUNC1 '(' ')'
  			{ $$ = make_op($1, 0, Nullarg, Nullarg, Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET || $1 == O_REQUIRE)
  			    $$ = fixeval($$); }
  	|	FUNC1 '(' expr ')'
  			{ $$ = make_op($1, 1, $3, Nullarg, Nullarg);
! 			  if ($1 == O_EVAL || $1 == O_RESET || $1 == O_REQUIRE)
  			    $$ = fixeval($$); }
  	|	FUNC2 '(' sexpr cexpr ')'
  			{ $$ = make_op($1, 2, $3, $4, Nullarg);
***************
*** 707,712 ****
--- 720,726 ----
  				Nullarg); }
  	|	HSHFUN3 '(' hshword csexpr cexpr ')'
  			{ $$ = make_op($1, 3, $3, $4, $5); }
+ 	|	bareword
  	|	listop
  	;
  
***************
*** 755,759 ****
--- 769,792 ----
  	|	HSH
  			{ $$ = stab2arg(A_STAB,$1); }
  	;
+ 
+ /*
+  * NOTE:  The following entry must stay at the end of the file so that
+  * reduce/reduce conflicts resolve to it only if it's the only option.
+  */
+ 
+ bareword:	WORD
+ 			{ char *s = $1;
+ 			    $$ = op_new(1);
+ 			    $$->arg_type = O_ITEM;
+ 			    $$[1].arg_type = A_SINGLE;
+ 			    $$[1].arg_ptr.arg_str = str_make($1,0);
+ 			    while (*s) {
+ 				if (!islower(*s))
+ 				    break;
+ 			    }
+ 			    if (dowarn && !*s)
+ 				warn("\"%s\" may clash with future reserved word", $1);
+ 			}
  
  %% /* PROGRAM */

Index: perl_man.1
Prereq: 3.0.1.5
*** perl_man.1.old	Thu Aug  9 06:03:13 1990
--- perl_man.1	Thu Aug  9 06:03:17 1990
***************
*** 1,7 ****
  .rn '' }`
! ''' $Header: perl_man.1,v 3.0.1.5 90/03/27 16:14:37 lwall Locked $
  ''' 
  ''' $Log:	perl_man.1,v $
  ''' Revision 3.0.1.5  90/03/27  16:14:37  lwall
  ''' patch16: .. now works using magical string increment
  ''' 
--- 1,18 ----
  .rn '' }`
! ''' $Header: perl_man.1,v 3.0.1.7 90/08/09 04:24:03 lwall Locked $
  ''' 
  ''' $Log:	perl_man.1,v $
+ ''' Revision 3.0.1.7  90/08/09  04:24:03  lwall
+ ''' patch19: added -x switch to extract script from input trash
+ ''' patch19: Added -c switch to do compilation only
+ ''' patch19: bare identifiers are now strings if no other interpretation possible
+ ''' patch19: -s now returns size of file
+ ''' patch19: Added __LINE__ and __FILE__ tokens
+ ''' patch19: Added __END__ token
+ ''' 
+ ''' Revision 3.0.1.6  90/08/03  11:14:44  lwall
+ ''' patch19: Intermediate diffs for Randal
+ ''' 
  ''' Revision 3.0.1.5  90/03/27  16:14:37  lwall
  ''' patch16: .. now works using magical string increment
  ''' 
***************
*** 182,187 ****
--- 193,203 ----
  
  .fi
  .TP 5
+ .B \-c
+ causes
+ .I perl
+ to check the syntax of the script and then exit without executing it.
+ .TP 5
  .BI \-d
  runs the script under the perl debugger.
  See the section on Debugging.
***************
*** 372,377 ****
--- 388,403 ----
  In order to start up sh rather than csh, some systems may have to replace the
  #! line with a line containing just
  a colon, which will be politely ignored by perl.
+ Other systems can't control that, and need a totally devious construct that
+ will work under any of csh, sh or perl, such as the following:
+ .nf
+ 
+ .ne 3
+ 	eval '(exit $?0)' && eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
+ 	& eval 'exec /usr/bin/perl -S $0 $argv:q'
+ 		if 0;
+ 
+ .fi
  .TP 5
  .B \-u
  causes
***************
*** 386,391 ****
--- 412,419 ----
  should probably compile it using taintperl rather than normal perl.
  If you want to execute a portion of your script before dumping, use the
  dump operator instead.
+ Note: availability of undump is platform specific and may not be available
+ for a specific port of perl.
  .TP 5
  .B \-U
  allows
***************
*** 407,412 ****
--- 435,457 ----
  write on.
  Also warns you if you use == on values that don't look like numbers, and if
  your subroutines recurse more than 100 deep.
+ .TP 5
+ .BI \-x directory
+ tells
+ .I perl
+ that the script is embedded in a message.
+ Leading garbage will be discarded until the first line that starts
+ with #! and contains the string "perl".
+ Any meaningful switches on that line will be applied (but only one
+ group of switches, as with normal #! processing).
+ If a directory name is specified, Perl will switch to that directory
+ before running the script.
+ The
+ .B \-x
+ switch only controls the the disposal of leading garbage.
+ The script must be terminated with __END__ if there is trailing garbage
+ to be ignored (the script can process any or all of the trailing garbage
+ via standard input if desired).
  .Sh "Data Types and Objects"
  .PP
  .I Perl
***************
*** 571,576 ****
--- 616,642 ----
  word by a space, since single quote is a valid character in an identifier
  (see Packages).
  .PP
+ Two special literals are __LINE__ and __FILE__, which represent the current
+ line number and filename at that point in your program.
+ They may only be used as separate tokens; they will not be interpolated
+ into strings.
+ In addition, the token __END__ may be used to indicate the logical end of the
+ script before the actual end of file.
+ Any following text is ignored (but if the script is being read from
+ the standard input, then the rest of the input is available by reading
+ from filehandle STDIN).
+ The two control characters ^D and ^Z are synonyms for __END__.
+ .PP
+ A word that doesn't have any other interpretation in the grammar will be
+ treated as if it had single quotes around it.
+ For this purpose, a word consists only of alphanumeric characters and underline,
+ and must start with an alphabetic character.
+ As with filehandles and labels, a bare word that consists entirely of
+ lowercase letters risks conflict with future reserved words, and if you
+ use the
+ .B \-w
+ switch, Perl will warn you about any such words.
+ .PP
  Array values are interpolated into double-quoted strings by joining all the
  elements of the array with the delimiter specified in the $" variable,
  space by default.
***************
*** 739,744 ****
--- 805,815 ----
  variable substitution just like a double quoted string.
  It is then interpreted as a command, and the output of that command
  is the value of the pseudo-literal, like in a shell.
+ In a scalar context, a single string consisting of all the output is
+ returned.
+ In an array context, an array of values is returned, one for each line
+ of output.
+ (You can set $/ to use a different line terminator.)
  The command is executed each time the pseudo-literal is evaluated.
  The status value of the command is returned in $? (see Predefined Names
  for the interpretation of $?).
***************
*** 1046,1051 ****
--- 1117,1124 ----
  .PP
  The foreach loop iterates over a normal array value and sets the variable
  VAR to be each element of the array in turn.
+ The variable is implicitly local to the loop, and regains its former value
+ upon exiting the loop.
  The \*(L"foreach\*(R" keyword is actually identical to the \*(L"for\*(R" keyword,
  so you can use \*(L"foreach\*(R" for readability or \*(L"for\*(R" for brevity.
  If VAR is omitted, $_ is set to each value.
***************
*** 1070,1076 ****
  	for (1..15) { print "Merry Christmas\en"; }
  
  .ne 3
! 	foreach $item (split(/:[\e\e\en:]*/, $ENV{\'TERMCAP\'}) {
  		print "Item: $item\en";
  	}
  
--- 1143,1149 ----
  	for (1..15) { print "Merry Christmas\en"; }
  
  .ne 3
! 	foreach $item (split(/:[\e\e\en:]*/, $ENV{\'TERMCAP\'})) {
  		print "Item: $item\en";
  	}
  
***************
*** 1112,1120 ****
  
  .ne 6
  	foo: {
! 		/^abc/ && do { $abc = 1; last foo; }
! 		/^def/ && do { $def = 1; last foo; }
! 		/^xyz/ && do { $xyz = 1; last foo; }
  		$nothing = 1;
  	}
  
--- 1185,1193 ----
  
  .ne 6
  	foo: {
! 		/^abc/ && do { $abc = 1; last foo; };
! 		/^def/ && do { $def = 1; last foo; };
! 		/^xyz/ && do { $xyz = 1; last foo; };
  		$nothing = 1;
  	}
  
***************
*** 1336,1342 ****
  	\-O	File is owned by real uid.
  	\-e	File exists.
  	\-z	File has zero size.
! 	\-s	File has non-zero size.
  	\-f	File is a plain file.
  	\-d	File is a directory.
  	\-l	File is a symbolic link.
--- 1409,1415 ----
  	\-O	File is owned by real uid.
  	\-e	File exists.
  	\-z	File has zero size.
! 	\-s	File has non-zero size (returns size).
  	\-f	File is a plain file.
  	\-d	File is a directory.
  	\-l	File is a symbolic link.
***************
*** 1472,1474 ****
--- 1545,1557 ----
  (If the final value specified is not in the sequence that the magical increment
  would produce, the sequence goes until the next value would be longer than
  the final value specified.)
+ .PP
+ The || and && operators differ from C's in that, rather than returning 0 or 1,
+ they return the last value evaluated. 
+ Thus, a portable way to find out the home directory might be:
+ .nf
+ 
+ 	$home = $ENV{'HOME'} || $ENV{'LOGDIR'} ||
+ 	    (getpwuid($<))[7] || die "You're homeless!\en";
+ 
+ .fi

Index: perl_man.2
Prereq: 3.0.1.5
*** perl_man.2.old	Thu Aug  9 06:03:34 1990
--- perl_man.2	Thu Aug  9 06:03:39 1990
***************
*** 1,7 ****
  ''' Beginning of part 2
! ''' $Header: perl_man.2,v 3.0.1.5 90/03/27 16:15:17 lwall Locked $
  '''
  ''' $Log:	perl_man.2,v $
  ''' Revision 3.0.1.5  90/03/27  16:15:17  lwall
  ''' patch16: MSDOS support
  ''' 
--- 1,13 ----
  ''' Beginning of part 2
! ''' $Header: perl_man.2,v 3.0.1.7 90/08/09 04:27:04 lwall Locked $
  '''
  ''' $Log:	perl_man.2,v $
+ ''' Revision 3.0.1.7  90/08/09  04:27:04  lwall
+ ''' patch19: added require operator
+ ''' 
+ ''' Revision 3.0.1.6  90/08/03  11:15:29  lwall
+ ''' patch19: Intermediate diffs for Randal
+ ''' 
  ''' Revision 3.0.1.5  90/03/27  16:15:17  lwall
  ''' patch16: MSDOS support
  ''' 
***************
*** 65,70 ****
--- 71,81 ----
  Returns the arctangent of X/Y in the range
  .if t \-\(*p to \(*p.
  .if n \-PI to PI.
+ .Ip "bind(SOCKET,NAME)" 8 2
+ Does the same thing that the bind system call does.
+ Returns true if it succeeded, false otherwise.
+ NAME should be a packed address of the proper type for the socket.
+ See example in section on Interprocess Communication.
  .Ip "binmode(FILEHANDLE)" 8 4
  .Ip "binmode FILEHANDLE" 8 4
  Arranges for the file to be read in \*(L"binary\*(R" mode in operating systems
***************
*** 74,84 ****
  Binmode has no effect under Unix.
  If FILEHANDLE is an expression, the value is taken as the name of
  the filehandle.
- .Ip "bind(SOCKET,NAME)" 8 2
- Does the same thing that the bind system call does.
- Returns true if it succeeded, false otherwise.
- NAME should be a packed address of the proper type for the socket.
- See example in section on Interprocess Communication.
  .Ip "chdir(EXPR)" 8 2
  .Ip "chdir EXPR" 8 2
  Changes the working directory to EXPR, if possible.
--- 85,90 ----
***************
*** 414,419 ****
--- 420,427 ----
  	do $foo();	# call a subroutine
  
  .fi
+ Note that inclusion of library routines is better done with
+ the \*(L"require\*(R" operator.
  .Ip "dump LABEL" 8 6
  This causes an immediate core dump.
  Primarily this is so that you can use the undump program to turn your
***************
*** 433,440 ****
  
  .ne 16
  	#!/usr/bin/perl
! 	do 'getopt.pl';
! 	do 'stat.pl';
  	%days = (
  	    'Sun',1,
  	    'Mon',2,
--- 441,448 ----
  
  .ne 16
  	#!/usr/bin/perl
! 	require 'getopt.pl';
! 	require 'stat.pl';
  	%days = (
  	    'Sun',1,
  	    'Mon',2,
***************
*** 479,484 ****
--- 487,494 ----
  Returns 1 if the next read on FILEHANDLE will return end of file, or if
  FILEHANDLE is not open.
  FILEHANDLE may be an expression whose value gives the real filehandle name.
+ (Note that this function actually reads a character and then ungetc's it,
+ so it is not very useful in an interactive context.)
  An eof without an argument returns the eof status for the last file read.
  Empty parentheses () may be used to indicate the pseudo file formed of the
  files listed on the command line, i.e. eof() is reasonable to use inside
***************
*** 584,590 ****
  You'll probably have to say
  .nf
  
! 	do "fcntl.h";	# probably /usr/local/lib/perl/fcntl.h
  
  .fi
  first to get the correct function definitions.
--- 594,600 ----
  You'll probably have to say
  .nf
  
! 	require "fcntl.ph";	# probably /usr/local/lib/perl/fcntl.ph
  
  .fi
  first to get the correct function definitions.
***************
*** 627,633 ****
  	    flock(MBOX,$LOCK_UN);
  	}
  
! 	open(MBOX, ">>/usr/spool/mail/$USER")
  		|| die "Can't open mailbox: $!";
  
  	do lock();
--- 637,643 ----
  	    flock(MBOX,$LOCK_UN);
  	}
  
! 	open(MBOX, ">>/usr/spool/mail/$ENV{'USER'}")
  		|| die "Can't open mailbox: $!";
  
  	do lock();
***************
*** 650,656 ****
  Returns the current login from /etc/utmp, if any.
  If null, use getpwuid.
  
! 	($login = getlogin) || (($login) = getpwuid($<));
  
  .Ip "getpeername(SOCKET)" 8 3
  Returns the packed sockaddr address of other end of the SOCKET connection.
--- 660,666 ----
  Returns the current login from /etc/utmp, if any.
  If null, use getpwuid.
  
! 	$login = getlogin || (getpwuid($<))[0] || "Somebody";
  
  .Ip "getpeername(SOCKET)" 8 3
  Returns the packed sockaddr address of other end of the SOCKET connection.
***************
*** 805,822 ****
  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.
  (To interpret strings that might start with 0 or 0x see oct().)
  If EXPR is omitted, uses $_.
  .Ip "ioctl(FILEHANDLE,FUNCTION,SCALAR)" 8 4
  Implements the ioctl(2) function.
  You'll probably have to say
  .nf
  
! 	do "ioctl.h";	# probably /usr/local/lib/perl/ioctl.h
  
  .fi
  first to get the correct function definitions.
--- 815,840 ----
  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 is not a named array.
  .Ip "hex(EXPR)" 8 4
  .Ip "hex EXPR" 8
  Returns the decimal value of EXPR interpreted as an hex string.
  (To interpret strings that might start with 0 or 0x see oct().)
  If EXPR is omitted, uses $_.
+ .Ip "index(STR,SUBSTR)" 8 4
+ Returns the position of the first occurrence of SUBSTR in STR, based at 0, or whatever you've
+ set the $[ variable to.
+ If the substring is not found, returns one less than the base, ordinarily \-1.
+ .Ip "int(EXPR)" 8 4
+ .Ip "int EXPR" 8
+ Returns the integer portion of EXPR.
+ If EXPR is omitted, uses $_.
  .Ip "ioctl(FILEHANDLE,FUNCTION,SCALAR)" 8 4
  Implements the ioctl(2) function.
  You'll probably have to say
  .nf
  
! 	require "ioctl.ph";	# probably /usr/local/lib/perl/ioctl.ph
  
  .fi
  first to get the correct function definitions.
***************
*** 837,843 ****
  .nf
  
  .ne 9
! 	do 'ioctl.h';
  	$sgttyb_t = "ccccs";		# 4 chars and a short
  	if (ioctl(STDIN,$TIOCGETP,$sgttyb)) {
  		@ary = unpack($sgttyb_t,$sgttyb);
--- 855,861 ----
  .nf
  
  .ne 9
! 	require 'ioctl.ph';
  	$sgttyb_t = "ccccs";		# 4 chars and a short
  	if (ioctl(STDIN,$TIOCGETP,$sgttyb)) {
  		@ary = unpack($sgttyb_t,$sgttyb);
***************
*** 865,878 ****
  	($retval = ioctl(...)) || ($retval = -1);
  	printf "System returned %d\en", $retval;
  .fi
- .Ip "index(STR,SUBSTR)" 8 4
- Returns the position of the first occurrence of SUBSTR in STR, based at 0, or whatever you've
- set the $[ variable to.
- If the substring is not found, returns one less than the base, ordinarily \-1.
- .Ip "int(EXPR)" 8 4
- .Ip "int EXPR" 8
- Returns the integer portion of EXPR.
- If EXPR is omitted, uses $_.
  .Ip "join(EXPR,LIST)" 8 8
  .Ip "join(EXPR,ARRAY)" 8
  Joins the separate strings of LIST or ARRAY into a single string with fields
--- 883,888 ----
***************
*** 1057,1063 ****
  See also the section on regular expressions.
  .Sp
  If / is the delimiter then the initial \*(L'm\*(R' is optional.
! With the \*(L'm\*(R' you can use any pair of characters as delimiters.
  This is particularly useful for matching Unix path names that contain \*(L'/\*(R'.
  If the final delimiter is followed by the optional letter \*(L'i\*(R', the matching is
  done in a case-insensitive manner.
--- 1067,1074 ----
  See also the section on regular expressions.
  .Sp
  If / is the delimiter then the initial \*(L'm\*(R' is optional.
! With the \*(L'm\*(R' you can use any pair of non-alphanumeric characters
! as delimiters.
  This is particularly useful for matching Unix path names that contain \*(L'/\*(R'.
  If the final delimiter is followed by the optional letter \*(L'i\*(R', the matching is
  done in a case-insensitive manner.

*** End of Patch 23 ***



More information about the Comp.sources.bugs mailing list