Path: utzoo!attcan!uunet!lll-winken!lll-lcc!ames!elroy!devvax!lroot
From: lroot@devvax.JPL.NASA.GOV (The Superuser)
Newsgroups: comp.sources.bugs
Subject: perl 2.0 patch #5
Summary: This is an official patch for perl 2.0.  Please apply it.
Message-ID: <2440@devvax.JPL.NASA.GOV>
Date: 13 Jul 88 00:54:23 GMT
Organization: Jet Propulsion Laboratory, Pasadena, CA
Lines: 1190

System: perl version 2.0
Patch #: 5
Priority: MEDIUM
Subject: patch2 continued

Description:
	See patch 2.

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  #define PATCHLEVEL 5


Index: x2p/s2p
Prereq: 2.0
*** x2p/s2p.old	Mon Jul 11 23:40:01 1988
--- x2p/s2p	Mon Jul 11 23:40:02 1988
***************
*** 1,8 ****
  #!/usr/bin/perl
  
! # $Header: s2p,v 2.0 88/06/05 00:15:55 root Exp $
  #
  # $Log:	s2p,v $
  # Revision 2.0  88/06/05  00:15:55  root
  # Baseline version 2.0.
  # 
--- 1,11 ----
  #!/usr/bin/perl
  
! # $Header: s2p,v 2.0.1.1 88/07/11 23:26:23 root Exp $
  #
  # $Log:	s2p,v $
+ # Revision 2.0.1.1  88/07/11  23:26:23  root
+ # patch2: s2p didn't put a proper prologue on output script
+ # 
  # Revision 2.0  88/06/05  00:15:55  root
  # Baseline version 2.0.
  # 
***************
*** 243,249 ****
      }
      close head;
  
!     print "#!/bin/perl\n\n";
      open(body,"cc -E /tmp/sperl2$$.c |") ||
  	do Die("Can't reopen temp file");
      while () {
--- 246,256 ----
      }
      close head;
  
!     print '#!/usr/bin/perl
! eval "exec /usr/bin/perl -S $0 $*"
! 	if $running_under_some_shell;
! 
! ';
      open(body,"cc -E /tmp/sperl2$$.c |") ||
  	do Die("Can't reopen temp file");
      while () {

Index: x2p/walk.c
Prereq: 2.0
*** x2p/walk.c.old	Mon Jul 11 23:40:08 1988
--- x2p/walk.c	Mon Jul 11 23:40:11 1988
***************
*** 1,6 ****
! /* $Header: walk.c,v 2.0 88/06/05 00:16:12 root Exp $
   *
   * $Log:	walk.c,v $
   * Revision 2.0  88/06/05  00:16:12  root
   * Baseline version 2.0.
   * 
--- 1,13 ----
! /* $Header: walk.c,v 2.0.1.1 88/07/11 23:35:57 root Exp $
   *
   * $Log:	walk.c,v $
+  * Revision 2.0.1.1  88/07/11  23:35:57  root
+  * patch2: changes to support translation of 1985 awk
+  * patch2: handles multiple opens to same file better
+  * patch2: now handles absence of line actions
+  * patch2: now takes advantage of perl's filehandle indirection
+  * patch2: now uses keys() instead of each() to protect against deletes in loop
+  * 
   * Revision 2.0  88/06/05  00:16:12  root
   * Baseline version 2.0.
   * 
***************
*** 14,22 ****
--- 21,34 ----
  bool exitval = FALSE;
  bool realexit = FALSE;
  bool saw_getline = FALSE;
+ bool subretnum = FALSE;
+ bool saw_FNR = FALSE;
+ bool saw_argv0 = FALSE;
  int maxtmp = 0;
  char *lparen;
  char *rparen;
+ STR *subs;
+ STR *curargs = Nullstr;
  
  STR *
  walk(useval,level,node,numericptr)
***************
*** 31,36 ****
--- 43,49 ----
      register int i;
      register STR *tmpstr;
      STR *tmp2str;
+     STR *tmp3str;
      char *t;
      char *d, *s;
      int numarg;
***************
*** 47,54 ****
      type &= 255;
      switch (type) {
      case OPROG:
- 	str = walk(0,level,ops[node+1].ival,&numarg);
  	opens = str_new(0);
  	if (do_split && need_entire && !absmaxfld)
  	    split_to_array = TRUE;
  	if (do_split && split_to_array)
--- 60,68 ----
      type &= 255;
      switch (type) {
      case OPROG:
  	opens = str_new(0);
+ 	subs = str_new(0);
+ 	str = walk(0,level,ops[node+1].ival,&numarg);
  	if (do_split && need_entire && !absmaxfld)
  	    split_to_array = TRUE;
  	if (do_split && split_to_array)
***************
*** 79,84 ****
--- 93,101 ----
  	if (saw_ORS) {
  	    str_cat(str,"$\\ = \"\\n\";\t\t# set output record separator\n");
  	}
+ 	if (saw_argv0) {
+ 	    str_cat(str,"$ARGV0 = $0;\t\t# remember what we ran as\n");
+ 	}
  	if (str->str_cur > 20)
  	    str_cat(str,"\n");
  	if (ops[node+2].ival) {
***************
*** 86,121 ****
  	    str_free(fstr);
  	    str_cat(str,"\n\n");
  	}
! 	if (saw_line_op)
! 	    str_cat(str,"line: ");
! 	str_cat(str,"while (<>) {\n");
! 	tab(str,++level);
! 	if (saw_FS && !const_FS)
! 	    do_chop = TRUE;
! 	if (do_chop) {
! 	    str_cat(str,"chop;\t# strip record separator\n");
! 	    tab(str,level);
! 	}
! 	arymax = 0;
! 	if (namelist) {
! 	    while (isalpha(*namelist)) {
! 		for (d = tokenbuf,s=namelist;
! 		  isalpha(*s) || isdigit(*s) || *s == '_';
! 		  *d++ = *s++) ;
! 		*d = '\0';
! 		while (*s && !isalpha(*s)) s++;
! 		namelist = s;
! 		nameary[++arymax] = savestr(tokenbuf);
  	    }
  	}
! 	if (maxfld < arymax)
! 	    maxfld = arymax;
! 	if (do_split)
! 	    emit_split(str,level);
! 	str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
! 	str_free(fstr);
! 	fixtab(str,--level);
! 	str_cat(str,"}\n");
  	if (ops[node+4].ival) {
  	    realexit = TRUE;
  	    str_cat(str,"\n");
--- 103,145 ----
  	    str_free(fstr);
  	    str_cat(str,"\n\n");
  	}
! 	fstr = walk(0,level+1,ops[node+3].ival,&numarg);
! 	if (*fstr->str_ptr) {
! 	    if (saw_line_op)
! 		str_cat(str,"line: ");
! 	    str_cat(str,"while (<>) {\n");
! 	    tab(str,++level);
! 	    if (saw_FS && !const_FS)
! 		do_chop = TRUE;
! 	    if (do_chop) {
! 		str_cat(str,"chop;\t# strip record separator\n");
! 		tab(str,level);
  	    }
+ 	    arymax = 0;
+ 	    if (namelist) {
+ 		while (isalpha(*namelist)) {
+ 		    for (d = tokenbuf,s=namelist;
+ 		      isalpha(*s) || isdigit(*s) || *s == '_';
+ 		      *d++ = *s++) ;
+ 		    *d = '\0';
+ 		    while (*s && !isalpha(*s)) s++;
+ 		    namelist = s;
+ 		    nameary[++arymax] = savestr(tokenbuf);
+ 		}
+ 	    }
+ 	    if (maxfld < arymax)
+ 		maxfld = arymax;
+ 	    if (do_split)
+ 		emit_split(str,level);
+ 	    str_scat(str,fstr);
+ 	    str_free(fstr);
+ 	    fixtab(str,--level);
+ 	    str_cat(str,"}\n");
+ 	    if (saw_FNR)
+ 		str_cat(str,"continue {\n    $FNRbase = $. if eof;\n}\n");
  	}
! 	else
! 	    str_cat(str,"# (no line actions)\n");
  	if (ops[node+4].ival) {
  	    realexit = TRUE;
  	    str_cat(str,"\n");
***************
*** 126,162 ****
  	}
  	if (exitval)
  	    str_cat(str,"exit ExitValue;\n");
  	if (saw_getline) {
! 	    str_cat(str,"\nsub Getline {\n    $_ = <>;\n");
! 	    tab(str,++level);
! 	    if (do_chop) {
! 		str_cat(str,"chop;\t# strip record separator\n");
! 		tab(str,level);
  	    }
- 	    if (do_split)
- 		emit_split(str,level);
- 	    fixtab(str,--level);
- 	    str_cat(str,"}\n");
  	}
  	if (do_fancy_opens) {
  	    str_cat(str,"\n\
  sub Pick {\n\
!     ($name) = @_;\n\
      $fh = $opened{$name};\n\
      if (!$fh) {\n\
! 	$nextfh == 0 && open(fh_0,$name);\n\
! 	$nextfh == 1 && open(fh_1,$name);\n\
! 	$nextfh == 2 && open(fh_2,$name);\n\
! 	$nextfh == 3 && open(fh_3,$name);\n\
! 	$nextfh == 4 && open(fh_4,$name);\n\
! 	$nextfh == 5 && open(fh_5,$name);\n\
! 	$nextfh == 6 && open(fh_6,$name);\n\
! 	$nextfh == 7 && open(fh_7,$name);\n\
! 	$nextfh == 8 && open(fh_8,$name);\n\
! 	$nextfh == 9 && open(fh_9,$name);\n\
! 	$fh = $opened{$name} = 'fh_' . $nextfh++;\n\
      }\n\
-     select($fh);\n\
  }\n\
  ");
  	}
--- 150,212 ----
  	}
  	if (exitval)
  	    str_cat(str,"exit ExitValue;\n");
+ 	if (subs->str_ptr) {
+ 	    str_cat(str,"\n");
+ 	    str_scat(str,subs);
+ 	}
  	if (saw_getline) {
! 	    for (len = 0; len < 4; len++) {
! 		if (saw_getline & (1 << len)) {
! 		    sprintf(tokenbuf,"\nsub Getline%d {\n",len);
! 		    str_cat(str, tokenbuf);
! 		    if (len & 2) {
! 			if (do_fancy_opens)
! 			    str_cat(str,"    do Pick('',@_);\n");
! 			else
! 			    str_cat(str,"    ($fh) = @_;\n");
! 		    }
! 		    else {
! 			if (saw_FNR)
! 			    str_cat(str,"    $FNRbase = $. if eof;\n");
! 		    }
! 		    if (len & 1)
! 			str_cat(str,"    local($_)\n");
! 		    if (len & 2)
! 			str_cat(str,
! 			  "    if ($getline_ok = (($_ = <$fh>) ne ''))");
! 		    else
! 			str_cat(str,
! 			  "    if ($getline_ok = (($_ = <>) ne ''))");
! 		    str_cat(str, " {\n");
! 		    level += 2;
! 		    tab(str,level);
! 		    i = 0;
! 		    if (do_chop) {
! 			i++;
! 			str_cat(str,"chop;\t# strip record separator\n");
! 			tab(str,level);
! 		    }
! 		    if (do_split && !(len & 1)) {
! 			i++;
! 			emit_split(str,level);
! 		    }
! 		    if (!i)
! 			str_cat(str,";\n");
! 		    fixtab(str,--level);
! 		    str_cat(str,"}\n    $_;\n}\n");
! 		    --level;
! 		}
  	    }
  	}
  	if (do_fancy_opens) {
  	    str_cat(str,"\n\
  sub Pick {\n\
!     local($mode,$name,$pipe) = @_;\n\
      $fh = $opened{$name};\n\
      if (!$fh) {\n\
! 	$fh = $opened{$name} = 'fh_' . ($nextfh++ + 0);\n\
! 	open($fh,$mode.$name.$pipe);\n\
      }\n\
  }\n\
  ");
  	}
***************
*** 345,352 ****
--- 395,407 ----
  	    str_free(tmpstr);
  	}
  	str_cat(str," ");
+ 	type = ops[ops[node+3].ival].ival & 255;
+ 	if (type != OREGEX && type != OVAR)
+ 	    str_cat(str,"(");
  	str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg));
  	str_free(fstr);
+ 	if (type != OREGEX && type != OVAR)
+ 	    str_cat(str,")");
  	numeric = 1;
  	break;
      case OMPAREN:
***************
*** 383,389 ****
  	str_free(fstr);
  	numeric = 1;
  	break;
!     case OSUB:
  	str = walk(1,level,ops[node+1].ival,&numarg);
  	str_cat(str," - ");
  	str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
--- 438,444 ----
  	str_free(fstr);
  	numeric = 1;
  	break;
!     case OSUBTRACT:
  	str = walk(1,level,ops[node+1].ival,&numarg);
  	str_cat(str," - ");
  	str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
***************
*** 404,409 ****
--- 459,471 ----
  	str_free(fstr);
  	numeric = 1;
  	break;
+     case OPOW:
+ 	str = walk(1,level,ops[node+1].ival,&numarg);
+ 	str_cat(str," ** ");
+ 	str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
+ 	str_free(fstr);
+ 	numeric = 1;
+ 	break;
      case OMOD:
  	str = walk(1,level,ops[node+1].ival,&numarg);
  	str_cat(str," % ");
***************
*** 455,462 ****
  	break;
      case OGETLINE:
  	str = str_new(0);
! 	str_set(str,"do Getline()");
! 	saw_getline = TRUE;
  	break;
      case OSPRINTF:
  	str = str_new(0);
--- 517,596 ----
  	break;
      case OGETLINE:
  	str = str_new(0);
! 	if (useval)
! 	    str_cat(str,"(");
! 	if (len > 0) {
! 	    str_cat(str,"$");
! 	    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
! 	    if (!*fstr->str_ptr) {
! 		str_cat(str,"_");
! 		len = 2;		/* a legal fiction */
! 	    }
! 	    str_free(fstr);
! 	}
! 	else
! 	    str_cat(str,"$_");
! 	if (len > 1) {
! 	    tmpstr=walk(1,level,ops[node+3].ival,&numarg);
! 	    fstr=walk(1,level,ops[node+2].ival,&numarg);
! 	    if (!do_fancy_opens) {
! 		t = tmpstr->str_ptr;
! 		if (*t == '"' || *t == '\'')
! 		    t = cpytill(tokenbuf,t+1,*t);
! 		else
! 		    fatal("Internal error: OGETLINE %s", t);
! 		d = savestr(t);
! 		s = savestr(tokenbuf);
! 		for (t = tokenbuf; *t; t++) {
! 		    *t &= 127;
! 		    if (!isalpha(*t) && !isdigit(*t))
! 			*t = '_';
! 		}
! 		if (!index(tokenbuf,'_'))
! 		    strcpy(t,"_fh");
! 		tmp3str = hfetch(symtab,tokenbuf);
! 		if (!tmp3str) {
! 		    do_opens = TRUE;
! 		    str_cat(opens,"open(");
! 		    str_cat(opens,tokenbuf);
! 		    str_cat(opens,", ");
! 		    d[1] = '\0';
! 		    str_cat(opens,d);
! 		    str_cat(opens,tmpstr->str_ptr+1);
! 		    opens->str_cur--;
! 		    if (*fstr->str_ptr == '|')
! 			str_cat(opens,"|");
! 		    str_cat(opens,d);
! 		    if (*fstr->str_ptr == '|')
! 			str_cat(opens,") || die 'Cannot pipe from \"");
! 		    else
! 			str_cat(opens,") || die 'Cannot open file \"");
! 		    if (*d == '"')
! 			str_cat(opens,"'.\"");
! 		    str_cat(opens,s);
! 		    if (*d == '"')
! 			str_cat(opens,"\".'");
! 		    str_cat(opens,"\".';\n");
! 		    hstore(symtab,tokenbuf,str_make("x"));
! 		}
! 		safefree(s);
! 		safefree(d);
! 		str_set(tmpstr,"'");
! 		str_cat(tmpstr,tokenbuf);
! 		str_cat(tmpstr,"'");
! 	    }
! 	    if (*fstr->str_ptr == '|')
! 		str_cat(tmpstr,", '|'");
! 	    str_free(fstr);
! 	}
! 	else
! 	    tmpstr = str_make("");
! 	sprintf(tokenbuf," = do Getline%d(%s)",len,tmpstr->str_ptr);
! 	str_cat(str,tokenbuf); 
! 	str_free(tmpstr);
! 	if (useval)
! 	    str_cat(str,",getline_ok)");
! 	saw_getline |= 1 << len;
  	break;
      case OSPRINTF:
  	str = str_new(0);
***************
*** 538,543 ****
--- 672,862 ----
  	str_cat(str,")");
  	numeric = 1;
  	break;
+     case OMATCH:
+ 	str = str_new(0);
+ 	str_set(str,"(");
+ 	str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
+ 	str_free(fstr);
+ 	str_cat(str," =~ ");
+ 	str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
+ 	str_free(fstr);
+ 	str_cat(str," && ($RLENGTH = length($&), $RSTART = length($`)+1))");
+ 	numeric = 1;
+ 	break;
+     case OUSERDEF:
+ 	str = str_new(0);
+ 	subretnum = FALSE;
+ 	fstr=walk(1,level-1,ops[node+2].ival,&numarg);
+ 	curargs = str_new(0);
+ 	str_sset(curargs,fstr);
+ 	str_cat(curargs,",");
+ 	tmp2str=walk(1,level,ops[node+5].ival,&numarg);
+ 	str_free(curargs);
+ 	curargs = Nullstr;
+ 	level--;
+ 	subretnum |= numarg;
+ 	s = Nullch;
+ 	t = tmp2str->str_ptr;
+ 	while (t = instr(t,"return "))
+ 	    s = t++;
+ 	if (s) {
+ 	    i = 0;
+ 	    for (t = s+7; *t; t++) {
+ 		if (*t == ';' || *t == '}')
+ 		    i++;
+ 	    }
+ 	    if (i == 1) {
+ 		strcpy(s,s+7);
+ 		tmp2str->str_cur -= 7;
+ 	    }
+ 	}
+ 	str_set(str,"sub ");
+ 	str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg));
+ 	str_cat(str," {\n");
+ 	tab(str,++level);
+ 	str_cat(str,"local(");
+ 	str_scat(str,fstr);
+ 	str_free(fstr);
+ 	str_cat(str,") = @_;");
+ 	str_scat(str,fstr=walk(1,level,ops[node+3].ival,&numarg));
+ 	str_free(fstr);
+ 	fixtab(str,level);
+ 	str_scat(str,fstr=walk(1,level,ops[node+4].ival,&numarg));
+ 	str_free(fstr);
+ 	fixtab(str,level);
+ 	str_scat(str,tmp2str);
+ 	str_free(tmp2str);
+ 	fixtab(str,--level);
+ 	str_cat(str,"}\n");
+ 	tab(str,level);
+ 	str_scat(subs,str);
+ 	str_set(str,"");
+ 	str_cat(tmpstr,"(");
+ 	tmp2str = str_new(0);
+ 	if (subretnum)
+ 	    str_set(tmp2str,"1");
+ 	hstore(symtab,tmpstr->str_ptr,tmp2str);
+ 	str_free(tmpstr);
+ 	level++;
+ 	break;
+     case ORETURN:
+ 	str = str_new(0);
+ 	if (len > 0) {
+ 	    str_cat(str,"return ");
+ 	    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
+ 	    str_free(fstr);
+ 	    if (numarg)
+ 		subretnum = TRUE;
+ 	}
+ 	else
+ 	    str_cat(str,"return");
+ 	break;
+     case OUSERFUN:
+ 	str = str_new(0);
+ 	str_set(str,"do ");
+ 	str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
+ 	str_free(fstr);
+ 	str_cat(str,"(");
+ 	tmpstr = hfetch(symtab,str->str_ptr+3);
+ 	if (tmpstr)
+ 	    numeric |= atoi(tmpstr->str_ptr);
+ 	str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
+ 	str_free(fstr);
+ 	str_cat(str,")");
+ 	break;
+     case OGSUB:
+     case OSUB:
+ 	if (type == OGSUB)
+ 	    s = "g";
+ 	else
+ 	    s = "";
+ 	str = str_new(0);
+ 	tmpstr = str_new(0);
+ 	i = 0;
+ 	if (len == 3) {
+ 	    tmpstr = walk(1,level,ops[node+3].ival,&numarg);
+ 	    if (strNE(tmpstr->str_ptr,"$_")) {
+ 		str_cat(tmpstr, " =~ s");
+ 		i++;
+ 	    }
+ 	    else
+ 		str_set(tmpstr, "s");
+ 	}
+ 	else
+ 	    str_set(tmpstr, "s");
+ 	type = ops[ops[node+2].ival].ival;
+ 	len = type >> 8;
+ 	type &= 255;
+ 	tmp3str = str_new(0);
+ 	if (type == OSTR) {
+ 	    tmp2str=walk(1,level,ops[ops[node+2].ival+1].ival,&numarg);
+ 	    for (t = tmp2str->str_ptr, d=tokenbuf; *t; d++,t++) {
+ 		if (*t == '&')
+ 		    *d++ = '$' + 128;
+ 		else if (*t == '$')
+ 		    *d++ = '\\' + 128;
+ 		*d = *t + 128;
+ 	    }
+ 	    *d = '\0';
+ 	    str_set(tmp2str,tokenbuf);
+ 	}
+ 	else {
+ 	    tmp2str=walk(1,level,ops[node+2].ival,&numarg);
+ 	    str_set(tmp3str,"($s_ = '\"'.(");
+ 	    str_scat(tmp3str,tmp2str);
+ 	    str_cat(tmp3str,").'\"') =~ s/&/\$&/g, ");
+ 	    str_set(tmp2str,"eval $s_");
+ 	    s = (*s == 'g' ? "ge" : "e");
+ 	    i++;
+ 	}
+ 	type = ops[ops[node+1].ival].ival;
+ 	len = type >> 8;
+ 	type &= 255;
+ 	fstr=walk(1,level,ops[node+1].ival,&numarg);
+ 	if (type == OREGEX) {
+ 	    if (useval && i)
+ 		str_cat(str,"(");
+ 	    str_scat(str,tmp3str);
+ 	    str_scat(str,tmpstr);
+ 	    str_scat(str,fstr);
+ 	    str_scat(str,tmp2str);
+ 	    str_cat(str,"/");
+ 	    str_cat(str,s);
+ 	}
+ 	else if ((type == OFLD && !split_to_array) || (type == OVAR && len == 1)) {
+ 	    if (useval && i)
+ 		str_cat(str,"(");
+ 	    str_scat(str,tmp3str);
+ 	    str_scat(str,tmpstr);
+ 	    str_cat(str,"/");
+ 	    str_scat(str,fstr);
+ 	    str_cat(str,"/");
+ 	    str_scat(str,tmp2str);
+ 	    str_cat(str,"/");
+ 	    str_cat(str,s);
+ 	}
+ 	else {
+ 	    i++;
+ 	    if (useval)
+ 		str_cat(str,"(");
+ 	    str_cat(str,"$s = ");
+ 	    str_scat(str,fstr);
+ 	    str_cat(str,", ");
+ 	    str_scat(str,tmp3str);
+ 	    str_scat(str,tmpstr);
+ 	    str_cat(str,"/$s/");
+ 	    str_scat(str,tmp2str);
+ 	    str_cat(str,"/");
+ 	    str_cat(str,s);
+ 	}
+ 	if (useval && i)
+ 	    str_cat(str,")");
+ 	str_free(fstr);
+ 	str_free(tmpstr);
+ 	str_free(tmp2str);
+ 	str_free(tmp3str);
+ 	numeric = 1;
+ 	break;
      case ONUM:
  	str = walk(1,level,ops[node+1].ival,&numarg);
  	numeric = 1;
***************
*** 567,582 ****
  	str_free(tmpstr);
  	str_cat(str,s);
  	break;
      case OVAR:
  	str = str_new(0);
  	str_set(str,"$");
  	str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg));
  	if (len == 1) {
  	    tmp2str = hfetch(symtab,tmpstr->str_ptr);
  	    if (tmp2str && atoi(tmp2str->str_ptr))
  		numeric = 2;
! 	    if (strEQ(str->str_ptr,"$NR")) {
  		numeric = 1;
  		str_set(str,"$.");
  	    }
  	    else if (strEQ(str->str_ptr,"$NF")) {
--- 886,911 ----
  	str_free(tmpstr);
  	str_cat(str,s);
  	break;
+     case ODELETE:
+ 	str = str_new(0);
+ 	str_set(str,"delete $");
+ 	goto addvar;
      case OVAR:
  	str = str_new(0);
  	str_set(str,"$");
+       addvar:
  	str_scat(str,tmpstr=walk(1,level,ops[node+1].ival,&numarg));
  	if (len == 1) {
  	    tmp2str = hfetch(symtab,tmpstr->str_ptr);
  	    if (tmp2str && atoi(tmp2str->str_ptr))
  		numeric = 2;
! 	    if (strEQ(str->str_ptr,"$FNR")) {
  		numeric = 1;
+ 		saw_FNR++;
+ 		str_set(str,"($.-$FNRbase)");
+ 	    }
+ 	    else if (strEQ(str->str_ptr,"$NR")) {
+ 		numeric = 1;
  		str_set(str,"$.");
  	    }
  	    else if (strEQ(str->str_ptr,"$NF")) {
***************
*** 585,592 ****
--- 914,928 ----
  	    }
  	    else if (strEQ(str->str_ptr,"$0"))
  		str_set(str,"$_");
+ 	    else if (strEQ(str->str_ptr,"$ARGC"))
+ 		str_set(str,"($#ARGV+1)");
  	}
  	else {
+ 	    if (curargs) {
+ 		sprintf(tokenbuf,"$%s,",tmpstr->str_ptr);
+ 		if (instr(curargs->str_ptr,tokenbuf))
+ 		    str_cat(str,"\377");	/* can't translate yet */
+ 	    }
  	    str_cat(tmpstr,"[]");
  	    tmp2str = hfetch(symtab,tmpstr->str_ptr);
  	    if (tmp2str && atoi(tmp2str->str_ptr))
***************
*** 595,606 ****
  		str_cat(str,"{");
  	    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
  	    str_free(fstr);
! 	    if (tmp2str && atoi(tmp2str->str_ptr))
! 		strcpy(tokenbuf,"]");
! 	    else
! 		strcpy(tokenbuf,"}");
! 	    *tokenbuf += 128;
! 	    str_cat(str,tokenbuf);
  	}
  	str_free(tmpstr);
  	break;
--- 931,948 ----
  		str_cat(str,"{");
  	    str_scat(str,fstr=walk(1,level,ops[node+2].ival,&numarg));
  	    str_free(fstr);
! 	    if (strEQ(str->str_ptr,"$ARGV[0")) {
! 		str_set(str,"$ARGV0");
! 		saw_argv0++;
! 	    }
! 	    else {
! 		if (tmp2str && atoi(tmp2str->str_ptr))
! 		    strcpy(tokenbuf,"]");
! 		else
! 		    strcpy(tokenbuf,"}");
! 		*tokenbuf += 128;
! 		str_cat(str,tokenbuf);
! 	    }
  	}
  	str_free(tmpstr);
  	break;
***************
*** 694,699 ****
--- 1036,1070 ----
  	    }
  	}
  	break;
+     case OCLOSE:
+ 	str = str_make("close(");
+ 	tmpstr = walk(1,level,ops[node+1].ival,&numarg);
+ 	if (!do_fancy_opens) {
+ 	    t = tmpstr->str_ptr;
+ 	    if (*t == '"' || *t == '\'')
+ 		t = cpytill(tokenbuf,t+1,*t);
+ 	    else
+ 		fatal("Internal error: OCLOSE %s",t);
+ 	    s = savestr(tokenbuf);
+ 	    for (t = tokenbuf; *t; t++) {
+ 		*t &= 127;
+ 		if (!isalpha(*t) && !isdigit(*t))
+ 		    *t = '_';
+ 	    }
+ 	    if (!index(tokenbuf,'_'))
+ 		strcpy(t,"_fh");
+ 	    str_free(tmpstr);
+ 	    safefree(s);
+ 	    str_set(str,"close ");
+ 	    str_cat(str,tokenbuf);
+ 	}
+ 	else {
+ 	    sprintf(tokenbuf,"$fh = delete $opened{%s} && close $fh",
+ 	       tmpstr->str_ptr);
+ 	    str_free(tmpstr);
+ 	    str_set(str,tokenbuf);
+ 	}
+ 	break;
      case OPRINTF:
      case OPRINT:
  	lparen = "";	/* set to parens if necessary */
***************
*** 717,739 ****
  		}
  		if (!index(tokenbuf,'_'))
  		    strcpy(t,"_fh");
! 		str_cat(opens,"open(");
! 		str_cat(opens,tokenbuf);
! 		str_cat(opens,", ");
! 		d[1] = '\0';
! 		str_cat(opens,d);
! 		str_scat(opens,tmp2str);
! 		str_cat(opens,tmpstr->str_ptr+1);
! 		if (*tmp2str->str_ptr == '|')
! 		    str_cat(opens,") || die 'Cannot pipe to \"");
! 		else
! 		    str_cat(opens,") || die 'Cannot create file \"");
! 		if (*d == '"')
! 		    str_cat(opens,"'.\"");
! 		str_cat(opens,s);
! 		if (*d == '"')
! 		    str_cat(opens,"\".'");
! 		str_cat(opens,"\".';\n");
  		str_free(tmpstr);
  		str_free(tmp2str);
  		safefree(s);
--- 1088,1114 ----
  		}
  		if (!index(tokenbuf,'_'))
  		    strcpy(t,"_fh");
! 		tmp3str = hfetch(symtab,tokenbuf);
! 		if (!tmp3str) {
! 		    str_cat(opens,"open(");
! 		    str_cat(opens,tokenbuf);
! 		    str_cat(opens,", ");
! 		    d[1] = '\0';
! 		    str_cat(opens,d);
! 		    str_scat(opens,tmp2str);
! 		    str_cat(opens,tmpstr->str_ptr+1);
! 		    if (*tmp2str->str_ptr == '|')
! 			str_cat(opens,") || die 'Cannot pipe to \"");
! 		    else
! 			str_cat(opens,") || die 'Cannot create file \"");
! 		    if (*d == '"')
! 			str_cat(opens,"'.\"");
! 		    str_cat(opens,s);
! 		    if (*d == '"')
! 			str_cat(opens,"\".'");
! 		    str_cat(opens,"\".';\n");
! 		    hstore(symtab,tokenbuf,str_make("x"));
! 		}
  		str_free(tmpstr);
  		str_free(tmp2str);
  		safefree(s);
***************
*** 740,750 ****
  		safefree(d);
  	    }
  	    else {
! 		sprintf(tokenbuf,"do Pick('%s' . (%s)) &&\n",
  		   tmp2str->str_ptr, tmpstr->str_ptr);
  		str_cat(str,tokenbuf);
  		tab(str,level+1);
! 		*tokenbuf = '\0';
  		str_free(tmpstr);
  		str_free(tmp2str);
  		lparen = "(";
--- 1115,1125 ----
  		safefree(d);
  	    }
  	    else {
! 		sprintf(tokenbuf,"do Pick('%s', %s) &&\n",
  		   tmp2str->str_ptr, tmpstr->str_ptr);
  		str_cat(str,tokenbuf);
  		tab(str,level+1);
! 		strcpy(tokenbuf,"$fh");
  		str_free(tmpstr);
  		str_free(tmp2str);
  		lparen = "(";
***************
*** 795,800 ****
--- 1170,1193 ----
  	str_cat(str,rparen);	/* may be null */
  	str_free(tmpstr);
  	break;
+     case ORAND:
+ 	str = str_make("rand(1)");
+ 	break;
+     case OSRAND:
+ 	str = str_make("srand(");
+ 	goto maybe0;
+     case OATAN2:
+ 	str = str_make("atan2(");
+ 	goto maybe0;
+     case OSIN:
+ 	str = str_make("sin(");
+ 	goto maybe0;
+     case OCOS:
+ 	str = str_make("cos(");
+ 	goto maybe0;
+     case OSYSTEM:
+ 	str = str_make("system(");
+ 	goto maybe0;
      case OLENGTH:
  	str = str_make("length(");
  	goto maybe0;
***************
*** 960,991 ****
  	str_free(fstr);
  	break;
      case OFORIN:
! 	tmpstr=walk(0,level,ops[node+2].ival,&numarg);
  	str = str_new(0);
! 	str_sset(str,tmpstr);
  	str_cat(str,"[]");
  	tmp2str = hfetch(symtab,str->str_ptr);
  	if (tmp2str && atoi(tmp2str->str_ptr)) {
- 	    fstr=walk(1,level,ops[node+1].ival,&numarg);
  	    sprintf(tokenbuf,
! 	      "foreach $%s (@%s) ",
! 	      fstr->str_ptr,
! 	      tmpstr->str_ptr);
! 	    str_set(str,tokenbuf);
! 	    str_free(fstr);
! 	    str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
! 	    str_free(fstr);
  	}
  	else {
! 	    str_set(str,"while (($");
! 	    str_scat(str,fstr=walk(1,level,ops[node+1].ival,&numarg));
! 	    str_free(fstr);
! 	    str_cat(str,",$junkval) = each(");
! 	    str_scat(str,tmpstr);
! 	    str_cat(str,")) ");
! 	    str_scat(str,fstr=walk(0,level,ops[node+3].ival,&numarg));
! 	    str_free(fstr);
  	}
  	str_free(tmpstr);
  	break;
      case OBLOCK:
--- 1353,1389 ----
  	str_free(fstr);
  	break;
      case OFORIN:
! 	tmpstr = walk(0,level,ops[node+1].ival,&numarg);
! 	s = index(tmpstr->str_ptr,'{');
! 	if (!s)
! 	    s = index(tmpstr->str_ptr,'[');
! 	if (!s)
! 	    fatal("Illegal for loop: %s",tmpstr->str_ptr);
! 	*s++ = '\0';
! 	t = index(s,'}' + 128);
! 	if (!t)
! 	    t = index(s,']' + 128);
! 	if (t)
! 	    *t = '\0';
  	str = str_new(0);
! 	str_set(str,tmpstr->str_ptr+1);
  	str_cat(str,"[]");
  	tmp2str = hfetch(symtab,str->str_ptr);
  	if (tmp2str && atoi(tmp2str->str_ptr)) {
  	    sprintf(tokenbuf,
! 	      "foreach %s (@%s) ",
! 	      s,
! 	      tmpstr->str_ptr+1);
  	}
  	else {
! 	    sprintf(tokenbuf,
! 	      "foreach %s (keys(%s)) ",
! 	      s,
! 	      tmpstr->str_ptr+1);
  	}
+ 	str_set(str,tokenbuf);
+ 	str_scat(str,fstr=walk(0,level,ops[node+2].ival,&numarg));
+ 	str_free(fstr);
  	str_free(tmpstr);
  	break;
      case OBLOCK:
***************
*** 1132,1137 ****
--- 1530,1537 ----
      char *d, *s;
      int numarg;
      int numeric = FALSE;
+     STR *tmpstr;
+     STR *tmp2str;
  
      if (!node) {
  	*numericptr = 0;
***************
*** 1259,1265 ****
  	prewalk(1,level,ops[node+2].ival,&numarg);
  	numeric = 1;
  	break;
!     case OSUB:
  	prewalk(1,level,ops[node+1].ival,&numarg);
  	prewalk(1,level,ops[node+2].ival,&numarg);
  	numeric = 1;
--- 1659,1665 ----
  	prewalk(1,level,ops[node+2].ival,&numarg);
  	numeric = 1;
  	break;
!     case OSUBTRACT:
  	prewalk(1,level,ops[node+1].ival,&numarg);
  	prewalk(1,level,ops[node+2].ival,&numarg);
  	numeric = 1;
***************
*** 1274,1279 ****
--- 1674,1684 ----
  	prewalk(1,level,ops[node+2].ival,&numarg);
  	numeric = 1;
  	break;
+     case OPOW:
+ 	prewalk(1,level,ops[node+1].ival,&numarg);
+ 	prewalk(1,level,ops[node+2].ival,&numarg);
+ 	numeric = 1;
+ 	break;
      case OMOD:
  	prewalk(1,level,ops[node+1].ival,&numarg);
  	prewalk(1,level,ops[node+2].ival,&numarg);
***************
*** 1333,1338 ****
--- 1738,1791 ----
  	prewalk(0,level,ops[node+2].ival,&numarg);
  	numeric = 1;
  	break;
+     case OMATCH:
+ 	prewalk(0,level,ops[node+1].ival,&numarg);
+ 	prewalk(0,level,ops[node+2].ival,&numarg);
+ 	numeric = 1;
+ 	break;
+     case OUSERDEF:
+ 	subretnum = FALSE;
+ 	--level;
+ 	tmpstr = walk(0,level,ops[node+1].ival,&numarg);
+ 	++level;
+ 	prewalk(0,level,ops[node+2].ival,&numarg);
+ 	prewalk(0,level,ops[node+4].ival,&numarg);
+ 	prewalk(0,level,ops[node+5].ival,&numarg);
+ 	--level;
+ 	str_cat(tmpstr,"(");
+ 	tmp2str = str_new(0);
+ 	if (subretnum || numarg)
+ 	    str_set(tmp2str,"1");
+ 	hstore(symtab,tmpstr->str_ptr,tmp2str);
+ 	str_free(tmpstr);
+ 	level++;
+ 	break;
+     case ORETURN:
+ 	if (len > 0) {
+ 	    prewalk(0,level,ops[node+1].ival,&numarg);
+ 	    if (numarg)
+ 		subretnum = TRUE;
+ 	}
+ 	break;
+     case OUSERFUN:
+ 	tmp2str = str_new(0);
+ 	str_scat(tmp2str,tmpstr=walk(1,level,ops[node+1].ival,&numarg));
+ 	str_free(tmpstr);
+ 	str_cat(tmp2str,"(");
+ 	tmpstr = hfetch(symtab,tmp2str->str_ptr);
+ 	if (tmpstr)
+ 	    numeric |= atoi(tmpstr->str_ptr);
+ 	prewalk(0,level,ops[node+2].ival,&numarg);
+ 	str_free(tmp2str);
+ 	break;
+     case OGSUB:
+     case OSUB:
+ 	if (len >= 3)
+ 	    prewalk(0,level,ops[node+3].ival,&numarg);
+ 	prewalk(0,level,ops[ops[node+2].ival+1].ival,&numarg);
+ 	prewalk(0,level,ops[node+1].ival,&numarg);
+ 	numeric = 1;
+ 	break;
      case ONUM:
  	prewalk(0,level,ops[node+1].ival,&numarg);
  	numeric = 1;
***************
*** 1340,1345 ****
--- 1793,1799 ----
      case OSTR:
  	prewalk(0,level,ops[node+1].ival,&numarg);
  	break;
+     case ODELETE:
      case OVAR:
  	prewalk(0,level,ops[node+1].ival,&numarg);
  	if (len == 1) {
***************
*** 1385,1390 ****
--- 1839,1847 ----
  	    }
  	}
  	break;
+     case OCLOSE:
+ 	prewalk(0,level,ops[node+1].ival,&numarg);
+ 	break;
      case OPRINTF:
      case OPRINT:
  	if (len == 3) {		/* output redirection */
***************
*** 1393,1398 ****
--- 1850,1867 ----
  	}
  	prewalk(0+(type==OPRINT),level,ops[node+1].ival,&numarg);
  	break;
+     case ORAND:
+ 	break;
+     case OSRAND:
+ 	goto maybe0;
+     case OATAN2:
+ 	goto maybe0;
+     case OSIN:
+ 	goto maybe0;
+     case OCOS:
+ 	goto maybe0;
+     case OSYSTEM:
+ 	goto maybe0;
      case OLENGTH:
  	goto maybe0;
      case OLOG:
***************
*** 1405,1411 ****
        maybe0:
  	numeric = 1;
  	if (len > 0)
! 	    prewalk(type != OLENGTH,level,ops[node+1].ival,&numarg);
  	break;
      case OBREAK:
  	break;
--- 1874,1881 ----
        maybe0:
  	numeric = 1;
  	if (len > 0)
! 	    prewalk(type != OLENGTH && type != OSYSTEM,
! 	      level,ops[node+1].ival,&numarg);
  	break;
      case OBREAK:
  	break;
***************
*** 1440,1446 ****
      case OFORIN:
  	prewalk(0,level,ops[node+2].ival,&numarg);
  	prewalk(0,level,ops[node+1].ival,&numarg);
- 	prewalk(0,level,ops[node+3].ival,&numarg);
  	break;
      case OBLOCK:
  	if (len == 2) {
--- 1910,1915 ----