perl 4.0 patch 25: patch #20, continued
authorLarry Wall <lwall@netlabs.com>
Mon, 8 Jun 1992 04:52:56 +0000 (04:52 +0000)
committerLarry Wall <lwall@netlabs.com>
Mon, 8 Jun 1992 04:52:56 +0000 (04:52 +0000)
See patch #20.

atarist/explain [new file with mode: 0644]
atarist/test/dbm [new file with mode: 0644]
cons.c
doarg.c
dump.c
eval.c
lib/find.pl
lib/getopts.pl
patchlevel.h
x2p/find2perl.SH

diff --git a/atarist/explain b/atarist/explain
new file mode 100644 (file)
index 0000000..9e8fca0
--- /dev/null
@@ -0,0 +1,77 @@
+Here is a brief explaination of the diffs in perl.diffs. If anything
+is unclear please just ask:
+
+General:
+  Many of the  #ifdef MSDOS where required for the atari too. In order
+to avoid cluttering up the source, upfront in perl.h we #define
+MSDOS_OR_ATARI if either defined(MSDOS) or defined(atarist).
+
+ Some of the diffs that i felt were universally applicable are not protected
+with #ifdef's. In the explainations below i has indicated all such
+changes.
+
+perl.h:
+  -- define MSDOS_OR_ATARI if appro.
+  -- typedef size_t - assume its there in <stddef.h> if STANDARD_C otherwise
+     typedef it to unsigned int (i would have ideally liked unsigned long,
+     but we get into trouble with half-assed headers from sun etc)
+(this change not protected with a #ifdef since hopefully its universally appli)
+
+  -- make the type of STRLEN size_t for all systems
+(this change not protected with a #ifdef since hopefully its universally appli)
+
+  -- more #ifdef MSDOS -> #ifdef MSDOS_OR_ATARI changes.
+
+arg.h:
+  -- in the atari headers we already have O_PIPE. Change all instances of
+     O_PIPE to PERL_O_PIPE. All such changes protected with #ifdef atarist.
+
+handy.h:
+  -- make MEM_SIZE size_t like STRLEN.
+(this change not protected with a #ifdef since hopefully its universally appli)
+
+doarg.c:
+  -- accomodate the large number of args needed for the atari syscall().
+  -- do the 9 thru 14 arg versions of syscall for the atarist.
+
+doio.c:
+  -- mode[] needed to be  initialized.
+(this change not protected with a #ifdef since hopefully its universally appli)
+
+  -- you may find this strange, we do not define STDSTDIO, because even
+     though we have the "standard" field in FILE, the semantics are
+     different. However, some contexts will work correctly, and there
+     you will see #if defined(STDSTDIO) || defined(atarist)
+
+  -- more #ifdef MSDOS -> #ifdef MSDOS_OR_ATARI changes.
+
+eval.c:
+  -- more #ifdef MSDOS -> #ifdef MSDOS_OR_ATARI changes.
+
+malloc.c::
+  -- instead of bashfully using ints to hold sizes use MEM_SIZE.
+     adjust some casts and printf format specifiers due to this.
+     (atarigcc can run in two modes, with 16 or 32 bit ints, so...)
+(this change not protected with a #ifdef since hopefully its universally appli)
+
+  -- atarist changes sometimes ||'ed with I286 as appro.
+
+perl.c:
+  -- more #ifdef MSDOS -> #ifdef MSDOS_OR_ATARI changes.
+
+regcomp.c:
+  -- like O_PIPE the atarist headers already has META defined. Change all
+     instances of META to PERL_META. All such changes protected with
+     #ifdef atarist.
+
+str.c:
+  -- more #ifdef MSDOS -> #ifdef MSDOS_OR_ATARI changes.
+
+token.c::
+  -- META -> PERL_META renaming for atari
+
+util.c::
+  -- more adjustments for memory sizes being MEM_SIZE instead of int.
+  -- more #ifdef MSDOS -> #ifdef MSDOS_OR_ATARI changes.
+
+++jrb  bammi@cadence.com
diff --git a/atarist/test/dbm b/atarist/test/dbm
new file mode 100644 (file)
index 0000000..b73e07d
--- /dev/null
@@ -0,0 +1,124 @@
+die "cant create dbmtest" unless dbmopen(%keys, "dbmtest", 0666);
+
+print "Writing...\n";
+$keys{'key0'} = 0;
+$keys{'key1'} = 1;
+$keys{'key2'} = 2;
+$keys{'key3'} = 3;
+$keys{'key4'} = 4;
+$keys{'key5'} = 5;
+$keys{'key6'} = 6;
+$keys{'key7'} = 7;
+$keys{'key8'} = 8;
+$keys{'key9'} = 9;
+$keys{'key10'} = 10;
+$keys{'key11'} = 11;
+$keys{'key12'} = 12;
+$keys{'key13'} = 13;
+$keys{'key14'} = 14;
+$keys{'key15'} = 15;
+$keys{'key16'} = 16;
+$keys{'key17'} = 17;
+$keys{'key18'} = 18;
+$keys{'key19'} = 19;
+$keys{'key20'} = 20;
+$keys{'key21'} = 21;
+$keys{'key22'} = 22;
+$keys{'key23'} = 23;
+$keys{'key24'} = 24;
+$keys{'key25'} = 25;
+$keys{'key26'} = 26;
+$keys{'key27'} = 27;
+$keys{'key28'} = 28;
+$keys{'key29'} = 29;
+$keys{'key30'} = 30;
+$keys{'key31'} = 31;
+$keys{'key32'} = 32;
+$keys{'key33'} = 33;
+$keys{'key34'} = 34;
+$keys{'key35'} = 35;
+$keys{'key36'} = 36;
+$keys{'key37'} = 37;
+$keys{'key38'} = 38;
+$keys{'key39'} = 39;
+$keys{'key40'} = 40;
+$keys{'key41'} = 41;
+$keys{'key42'} = 42;
+$keys{'key43'} = 43;
+$keys{'key44'} = 44;
+$keys{'key45'} = 45;
+$keys{'key46'} = 46;
+$keys{'key47'} = 47;
+$keys{'key48'} = 48;
+$keys{'key49'} = 49;
+$keys{'key50'} = 50;
+$keys{'key51'} = 51;
+$keys{'key52'} = 52;
+$keys{'key53'} = 53;
+$keys{'key54'} = 54;
+$keys{'key55'} = 55;
+$keys{'key56'} = 56;
+$keys{'key57'} = 57;
+$keys{'key58'} = 58;
+$keys{'key59'} = 59;
+$keys{'key60'} = 60;
+$keys{'key61'} = 61;
+$keys{'key62'} = 62;
+$keys{'key63'} = 63;
+$keys{'key64'} = 64;
+$keys{'key65'} = 65;
+$keys{'key66'} = 66;
+$keys{'key67'} = 67;
+$keys{'key68'} = 68;
+$keys{'key69'} = 69;
+$keys{'key70'} = 70;
+$keys{'key71'} = 71;
+$keys{'key72'} = 72;
+$keys{'key73'} = 73;
+$keys{'key74'} = 74;
+$keys{'key75'} = 75;
+$keys{'key76'} = 76;
+$keys{'key77'} = 77;
+$keys{'key78'} = 78;
+$keys{'key79'} = 79;
+$keys{'key80'} = 80;
+$keys{'key81'} = 81;
+$keys{'key82'} = 82;
+$keys{'key83'} = 83;
+$keys{'key84'} = 84;
+$keys{'key85'} = 85;
+$keys{'key86'} = 86;
+$keys{'key87'} = 87;
+$keys{'key88'} = 88;
+$keys{'key89'} = 89;
+$keys{'key90'} = 90;
+$keys{'key91'} = 91;
+$keys{'key92'} = 92;
+$keys{'key93'} = 93;
+$keys{'key94'} = 94;
+$keys{'key95'} = 95;
+$keys{'key96'} = 96;
+$keys{'key97'} = 97;
+$keys{'key98'} = 98;
+$keys{'key99'} = 99;
+$keys{'key9998'} = 9998;
+$keys{'key9999'} = 9999;
+print "Done\n";
+
+dbmclose (%keys);
+
+die "cant read dbmtest" unless dbmopen(%rkeys, "dbmtest", undef);
+
+$i = 0;
+print "Reading...\n";
+while (($key, $val) = each %rkeys)
+{
+  if ($keys{$key} != $val)
+  {
+     print 'Incorrect val ', $key, ' = ', $val, ' expecting ', $keys{$key}, "\n";
+     $i = $i + 1;
+  }
+}
+print "Done\n";
+dbmclose (%keys);
+print $i, "Error(s)\n";
diff --git a/cons.c b/cons.c
index a3572b3..54fa14d 100644 (file)
--- a/cons.c
+++ b/cons.c
@@ -1,4 +1,4 @@
-/* $RCSfile: cons.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 16:15:13 $
+/* $RCSfile: cons.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 12:18:35 $
  *
  *    Copyright (c) 1991, Larry Wall
  *
@@ -6,6 +6,16 @@
  *    License or the Artistic License, as specified in the README file.
  *
  * $Log:       cons.c,v $
+ * Revision 4.0.1.3  92/06/08  12:18:35  lwall
+ * patch20: removed implicit int declarations on funcions
+ * patch20: deleted some minor memory leaks
+ * patch20: fixed double debug break in foreach with implicit array assignment
+ * patch20: fixed confusion between a *var's real name and its effective name
+ * patch20: Perl now distinguishes overlapped copies from non-overlapped
+ * patch20: debugger sometimes displayed wrong source line
+ * patch20: various error messages have been clarified
+ * patch20: an eval block containing a null block or statement could dump core
+ * 
  * Revision 4.0.1.2  91/11/05  16:15:13  lwall
  * patch11: debugger got confused over nested subroutine definitions
  * patch11: prepared for ctype implementations that don't define isascii()
@@ -29,6 +39,8 @@ extern int yychar;
 static int cmd_tosave();
 static int arg_tosave();
 static int spat_tosave();
+static void make_cswitch();
+static void make_nswitch();
 
 static bool saw_return;
 
@@ -40,8 +52,7 @@ CMD *cmd;
     register SUBR *sub;
     STAB *stab = stabent(name,TRUE);
 
-    Newz(101,sub,1,SUBR);
-    if (stab_sub(stab)) {
+    if (sub = stab_sub(stab)) {
        if (dowarn) {
            CMD *oldcurcmd = curcmd;
 
@@ -50,13 +61,14 @@ CMD *cmd;
            warn("Subroutine %s redefined",name);
            curcmd = oldcurcmd;
        }
-       if (stab_sub(stab)->cmd) {
-           cmd_free(stab_sub(stab)->cmd);
-           stab_sub(stab)->cmd = Nullcmd;
-           afree(stab_sub(stab)->tosave);
+       if (!sub->usersub && sub->cmd) {
+           cmd_free(sub->cmd);
+           sub->cmd = Nullcmd;
+           afree(sub->tosave);
        }
-       Safefree(stab_sub(stab));
+       Safefree(sub);
     }
+    Newz(101,sub,1,SUBR);
     stab_sub(stab) = sub;
     sub->filestab = curcmd->c_filestab;
     saw_return = FALSE;
@@ -69,7 +81,8 @@ CMD *cmd;
 
        mycompblock.comp_true = cmd;
        mycompblock.comp_alt = Nullcmd;
-       cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,Nullarg,mycompblock));
+       cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,0,
+           Nullarg,mycompblock));
        saw_return = FALSE;
        cmd->c_flags |= CF_TERM;
     }
@@ -83,10 +96,10 @@ CMD *cmd;
        str_cat(str,"-");
        sprintf(buf,"%ld",(long)curcmd->c_line);
        str_cat(str,buf);
-       name = str_get(subname);
-       stab_fullname(tmpstr,stab);
+       stab_efullname(tmpstr,stab);
        hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0);
     }
+    Safefree(name);
     return sub;
 }
 
@@ -102,17 +115,17 @@ char *filename;
 
     if (!stab)                         /* unused function */
        return Null(SUBR*);
-    Newz(101,sub,1,SUBR);
-    if (stab_sub(stab)) {
+    if (sub = stab_sub(stab)) {
        if (dowarn)
            warn("Subroutine %s redefined",name);
-       if (stab_sub(stab)->cmd) {
-           cmd_free(stab_sub(stab)->cmd);
-           stab_sub(stab)->cmd = Nullcmd;
-           afree(stab_sub(stab)->tosave);
+       if (!sub->usersub && sub->cmd) {
+           cmd_free(sub->cmd);
+           sub->cmd = Nullcmd;
+           afree(sub->tosave);
        }
-       Safefree(stab_sub(stab));
+       Safefree(sub);
     }
+    Newz(101,sub,1,SUBR);
     stab_sub(stab) = sub;
     sub->filestab = fstab(filename);
     sub->usersub = subaddr;
@@ -120,6 +133,7 @@ char *filename;
     return sub;
 }
 
+void
 make_form(stab,fcmd)
 STAB *stab;
 FCMD *fcmd;
@@ -188,11 +202,6 @@ register CMD *tail;
        /* now do a little optimization on case-ish structures */
        switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) {
        case CFT_ANCHOR:
-           if (stabent("*",FALSE)) {   /* bad assumption here!!! */
-               opt = 0;
-               break;
-           }
-           /* FALL THROUGH */
        case CFT_STROP:
            opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0;
            break;
@@ -239,6 +248,7 @@ register CMD *tail;
  * spat.  Thus we can insert a SWITCH in front and jump directly
  * to the correct one.
  */
+static void
 make_cswitch(head,count)
 register CMD *head;
 int count;
@@ -251,12 +261,9 @@ int count;
 
     /* make a new head in the exact same spot */
     New(102,cur, 1, CMD);
-#ifdef STRUCTCOPY
-    *cur = *head;
-#else
-    Copy(head,cur,1,CMD);
-#endif
+    StructCopy(head,cur,CMD);
     Zero(head,1,CMD);
+    head->c_head = cur->c_head;
     head->c_type = C_CSWITCH;
     head->c_next = cur;                /* insert new cmd at front of list */
     head->c_stab = cur->c_stab;
@@ -289,7 +296,7 @@ int count;
     }
     max++;
     if (min > 0)
-       Copy(&loc[min],&loc[0], max - min, CMD*);
+       Move(&loc[min],&loc[0], max - min, CMD*);
     loc--;
     min--;
     max -= min;
@@ -302,6 +309,7 @@ int count;
     head->ucmd.scmd.sc_next = loc;
 }
 
+static void
 make_nswitch(head,count)
 register CMD *head;
 int count;
@@ -339,12 +347,9 @@ int count;
 
     /* now make a new head in the exact same spot */
     New(104,cur, 1, CMD);
-#ifdef STRUCTCOPY
-    *cur = *head;
-#else
-    Copy(head,cur,1,CMD);
-#endif
+    StructCopy(head,cur,CMD);
     Zero(head,1,CMD);
+    head->c_head = cur->c_head;
     head->c_type = C_NSWITCH;
     head->c_next = cur;                /* insert new cmd at front of list */
     head->c_stab = cur->c_stab;
@@ -443,6 +448,7 @@ CMD *cur;
        stab2arg(A_WORD,DBstab),
        Nullarg,
        Nullarg);
+    /*SUPPRESS 53*/
     cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0;
     cmd->c_line = head->c_line;
     cmd->c_label = head->c_label;
@@ -481,8 +487,9 @@ ARG *arg;
 }
 
 CMD *
-make_ccmd(type,arg,cblock)
+make_ccmd(type,debuggable,arg,cblock)
 int type;
+int debuggable;
 ARG *arg;
 struct compcmd cblock;
 {
@@ -503,7 +510,7 @@ struct compcmd cblock;
     }
     cmd->c_filestab = curcmd->c_filestab;
     cmd->c_stash = curstash;
-    if (perldb)
+    if (perldb && debuggable)
        cmd = dodb(cmd);
     return cmd;
 }
@@ -545,7 +552,7 @@ struct compcmd cblock;
     if (alt) {                 /* a real life ELSE at the end? */
        ncblock.comp_true = alt;
        ncblock.comp_alt = Nullcmd;
-       alt = append_line(cur,make_ccmd(C_ELSE,Nullarg,ncblock));
+       alt = append_line(cur,make_ccmd(C_ELSE,1,Nullarg,ncblock));
        cur->ucmd.ccmd.cc_alt = alt;
     }
     else
@@ -693,6 +700,7 @@ int acmd;
                sure |= CF_EQSURE;              /* (SUBST must be forced even */
                                                /* if we know it will work.) */
            if (arg->arg_type != O_SUBST) {
+               str_free(arg[2].arg_ptr.arg_spat->spat_short);
                arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
                arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
            }
@@ -901,6 +909,18 @@ CMD *cmd;
     return cmd;
 }
 
+void
+cpy7bit(d,s,l)
+register char *d;
+register char *s;
+register int l;
+{
+    while (l--)
+       *d++ = *s++ & 127;
+    *d = '\0';
+}
+
+int
 yyerror(s)
 char *s;
 {
@@ -912,16 +932,14 @@ char *s;
       oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
        while (isSPACE(*oldoldbufptr))
            oldoldbufptr++;
-       strncpy(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
-       tmp2buf[bufptr - oldoldbufptr] = '\0';
+       cpy7bit(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
        sprintf(tname,"next 2 tokens \"%s\"",tmp2buf);
     }
     else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
       oldbufptr != bufptr) {
        while (isSPACE(*oldbufptr))
            oldbufptr++;
-       strncpy(tmp2buf, oldbufptr, bufptr - oldbufptr);
-       tmp2buf[bufptr - oldbufptr] = '\0';
+       cpy7bit(tmp2buf, oldbufptr, bufptr - oldbufptr);
        sprintf(tname,"next token \"%s\"",tmp2buf);
     }
     else if (yychar > 256)
@@ -1101,7 +1119,7 @@ register CMD *cmd;
        cmd->ucmd.ccmd.cc_alt = tail;   /* every loop has a continue now */
 
 #ifndef lint
-    (void)bcopy((char *)cmd, (char *)tail, sizeof(CMD));
+    Copy((char *)cmd, (char *)tail, 1, CMD);
 #endif
     tail->c_type = C_EXPR;
     tail->c_flags ^= CF_INVERT;                /* turn into "last unless" */
@@ -1127,12 +1145,17 @@ register CMD *cmd;
     return cmd;
 }
 
+void
 cmd_free(cmd)
 register CMD *cmd;
 {
     register CMD *tofree;
     register CMD *head = cmd;
 
+    if (!cmd)
+       return;
+    if (cmd->c_head != cmd)
+       warn("Malformed cmd links\n");
     while (cmd) {
        if (cmd->c_type != C_WHILE) {   /* WHILE block is duplicated */
            if (cmd->c_label) {
@@ -1175,11 +1198,14 @@ register CMD *cmd;
     Safefree(head);
 }
 
+void
 arg_free(arg)
 register ARG *arg;
 {
     register int i;
 
+    if (!arg)
+       return;
     for (i = 1; i <= arg->arg_len; i++) {
        switch (arg[i].arg_type & A_MASK) {
        case A_NULL:
@@ -1231,12 +1257,15 @@ register ARG *arg;
     free_arg(arg);
 }
 
+void
 spat_free(spat)
 register SPAT *spat;
 {
     register SPAT *sp;
     HENT *entry;
 
+    if (!spat)
+       return;
     if (spat->spat_runtime) {
        arg_free(spat->spat_runtime);
        spat->spat_runtime = Nullarg;
diff --git a/doarg.c b/doarg.c
index c40bf68..01a9631 100644 (file)
--- a/doarg.c
+++ b/doarg.c
@@ -1,4 +1,4 @@
-/* $RCSfile: doarg.c,v $$Revision: 4.0.1.5 $$Date: 91/11/11 16:31:58 $
+/* $RCSfile: doarg.c,v $$Revision: 4.0.1.6 $$Date: 92/06/08 12:34:30 $
  *
  *    Copyright (c) 1991, Larry Wall
  *
@@ -6,6 +6,16 @@
  *    License or the Artistic License, as specified in the README file.
  *
  * $Log:       doarg.c,v $
+ * Revision 4.0.1.6  92/06/08  12:34:30  lwall
+ * patch20: removed implicit int declarations on funcions
+ * patch20: pattern modifiers i and o didn't interact right
+ * patch20: join() now pre-extends target string to avoid excessive copying
+ * patch20: fixed confusion between a *var's real name and its effective name
+ * patch20: subroutines didn't localize $`, $&, $', $1 et al correctly
+ * patch20: usersub routines didn't reclaim temp values soon enough
+ * patch20: ($<,$>) = ... didn't work on some architectures
+ * patch20: added Atari ST portability
+ * 
  * Revision 4.0.1.5  91/11/11  16:31:58  lwall
  * patch19: added little-endian pack/unpack options
  * 
@@ -53,6 +63,8 @@ extern unsigned char fold[];
  #pragma function(memcmp)
 #endif /* BUGGY_MSC */
 
+static void doencodes();
+
 int
 do_subst(str,arg,sp)
 STR *str;
@@ -90,7 +102,8 @@ int sp;
        spat->spat_regexp = regcomp(m,m+dstr->str_cur,
            spat->spat_flags & SPAT_FOLD);
        if (spat->spat_flags & SPAT_KEEP) {
-           scanconst(spat, m, dstr->str_cur);
+           if (!(spat->spat_flags & SPAT_FOLD))
+               scanconst(spat, m, dstr->str_cur);
            arg_free(spat->spat_runtime);       /* it won't change, so */
            spat->spat_runtime = Nullarg;       /* no point compiling again */
            hoistmust(spat);
@@ -178,12 +191,12 @@ int sp;
                    s = orig;
                    if (m - s > strend - d) {   /* faster to shorten from end */
                        if (clen) {
-                           (void)bcopy(c, m, clen);
+                           Copy(c, m, clen, char);
                            m += clen;
                        }
                        i = strend - d;
                        if (i > 0) {
-                           (void)bcopy(d, m, i);
+                           Move(d, m, i, char);
                            m += i;
                        }
                        *m = '\0';
@@ -202,7 +215,7 @@ int sp;
                        while (i--)
                            *--d = *--s;
                        if (clen)
-                           (void)bcopy(c, m, clen);
+                           Copy(c, m, clen, char);
                        STABSET(str);
                        str_numset(arg->arg_ptr.arg_str, 1.0);
                        stack->ary_array[++sp] = arg->arg_ptr.arg_str;
@@ -211,7 +224,7 @@ int sp;
                    else if (clen) {
                        d -= clen;
                        str_chop(str,d);
-                       (void)bcopy(c,d,clen);
+                       Copy(c,d,clen,char);
                        STABSET(str);
                        str_numset(arg->arg_ptr.arg_str, 1.0);
                        stack->ary_array[++sp] = arg->arg_ptr.arg_str;
@@ -233,11 +246,11 @@ int sp;
                    /*SUPPRESS 560*/
                    if (i = m - s) {
                        if (s != d)
-                           (void)bcopy(s,d,i);
+                           Move(s,d,i,char);
                        d += i;
                    }
                    if (clen) {
-                       (void)bcopy(c,d,clen);
+                       Copy(c,d,clen,char);
                        d += clen;
                    }
                    s = spat->spat_regexp->endp[0];
@@ -246,7 +259,7 @@ int sp;
                if (s != d) {
                    i = strend - s;
                    str->str_cur = d - str->str_ptr + i;
-                   (void)bcopy(s,d,i+1);               /* include the Null */
+                   Move(s,d,i+1,char);         /* include the Null */
                }
                STABSET(str);
                str_numset(arg->arg_ptr.arg_str, (double)iters);
@@ -385,19 +398,35 @@ register STR *str;
 int *arglast;
 {
     register STR **st = stack->ary_array;
-    register int sp = arglast[1];
+    int sp = arglast[1];
     register int items = arglast[2] - sp;
     register char *delim = str_get(st[sp]);
+    register STRLEN len;
     int delimlen = st[sp]->str_cur;
 
-    st += ++sp;
+    st += sp + 1;
+
+    len = delimlen * (items - 1);
+    if (str->str_len < len + items) {  /* current length is way too short */
+       while (items-- > 0) {
+           if (*st)
+               len += (*st)->str_cur;
+           st++;
+       }
+       STR_GROW(str, len + 1);         /* so try to pre-extend */
+
+       items = arglast[2] - sp;
+       st -= items;
+    }
+
     if (items-- > 0)
        str_sset(str, *st++);
     else
        str_set(str,"");
-    if (delimlen) {
+    len = delimlen;
+    if (len) {
        for (; items > 0; items--,st++) {
-           str_ncat(str,delim,delimlen);
+           str_ncat(str,delim,len);
            str_scat(str,*st);
        }
     }
@@ -780,6 +809,7 @@ int *arglast;
 }
 #undef NEXTFROM
 
+static void
 doencodes(str, s, len)
 register STR *str;
 register char *s;
@@ -938,7 +968,7 @@ register STR **sarg;
                  && xlen == sizeof(STBP)) {
                    STR *tmpstr = Str_new(24,0);
 
-                   stab_fullname(tmpstr, ((STAB*)arg)); /* a stab value! */
+                   stab_efullname(tmpstr, ((STAB*)arg)); /* a stab value! */
                    sprintf(tokenbuf,"*%s",tmpstr->str_ptr);
                                        /* reformat to non-binary */
                    xs = tokenbuf;
@@ -1053,6 +1083,7 @@ int *arglast;
     register int sp = arglast[1];
     register int items = arglast[2] - sp;
     register SUBR *sub;
+    SPAT * VOLATILE oldspat = curspat;
     STR *str;
     STAB *stab;
     int oldsave = savestack->ary_fill;
@@ -1075,13 +1106,13 @@ int *arglast;
     if (!(sub = stab_sub(stab))) {
        STR *tmpstr = arg[0].arg_ptr.arg_str;
 
-       stab_fullname(tmpstr, stab);
+       stab_efullname(tmpstr, stab);
        fatal("Undefined subroutine \"%s\" called",tmpstr->str_ptr);
     }
     if (arg->arg_type == O_DBSUBR && !sub->usersub) {
        str = stab_val(DBsub);
        saveitem(str);
-       stab_fullname(str,stab);
+       stab_efullname(str,stab);
        sub = stab_sub(DBsub);
        if (!sub)
            fatal("No DBsub routine");
@@ -1098,6 +1129,7 @@ int *arglast;
     csv->wantarray = gimme;
     csv->hasargs = hasargs;
     curcsv = csv;
+    tmps_base = tmps_max;
     if (sub->usersub) {
        csv->hasargs = 0;
        csv->savearray = Null(ARRAY*);;
@@ -1105,28 +1137,30 @@ int *arglast;
        st[sp] = arg->arg_ptr.arg_str;
        if (!hasargs)
            items = 0;
-       return (*sub->usersub)(sub->userindex,sp,items);
-    }
-    if (hasargs) {
-       csv->savearray = stab_xarray(defstab);
-       csv->argarray = afake(defstab, items, &st[sp+1]);
-       stab_xarray(defstab) = csv->argarray;
+       sp = (*sub->usersub)(sub->userindex,sp,items);
     }
-    sub->depth++;
-    if (sub->depth >= 2) {     /* save temporaries on recursion? */
-       if (sub->depth == 100 && dowarn)
-           warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
-       savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
+    else {
+       if (hasargs) {
+           csv->savearray = stab_xarray(defstab);
+           csv->argarray = afake(defstab, items, &st[sp+1]);
+           stab_xarray(defstab) = csv->argarray;
+       }
+       sub->depth++;
+       if (sub->depth >= 2) {  /* save temporaries on recursion? */
+           if (sub->depth == 100 && dowarn)
+               warn("Deep recursion on subroutine \"%s\"",stab_ename(stab));
+           savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
+       }
+       sp = cmd_exec(sub->cmd,gimme, --sp);    /* so do it already */
     }
-    tmps_base = tmps_max;
-    sp = cmd_exec(sub->cmd,gimme, --sp);       /* so do it already */
-    st = stack->ary_array;
 
+    st = stack->ary_array;
     tmps_base = oldtmps_base;
     for (items = arglast[0] + 1; items <= sp; items++)
        st[items] = str_mortal(st[items]);
            /* in case restore wipes old str */
     restorelist(oldsave);
+    curspat = oldspat;
     return sp;
 }
 
@@ -1264,22 +1298,56 @@ int *arglast;
            STABSET(str);
        }
     }
-    if (delaymagic > 1) {
-       if (delaymagic & DM_REUID) {
+    if (delaymagic & ~DM_DELAY) {
+       if (delaymagic & DM_UID) {
 #ifdef HAS_SETREUID
-           setreuid(uid,euid);
-#else
-           if (uid != euid || setuid(uid) < 0)
-               fatal("No setreuid available");
-#endif
+           (void)setreuid(uid,euid);
+#else /* not HAS_SETREUID */
+#ifdef HAS_SETRUID
+           if ((delaymagic & DM_UID) == DM_RUID) {
+               (void)setruid(uid);
+               delaymagic =~ DM_RUID;
+           }
+#endif /* HAS_SETRUID */
+#ifdef HAS_SETEUID
+           if ((delaymagic & DM_UID) == DM_EUID) {
+               (void)seteuid(uid);
+               delaymagic =~ DM_EUID;
+           }
+#endif /* HAS_SETEUID */
+           if (delaymagic & DM_UID) {
+               if (uid != euid)
+                   fatal("No setreuid available");
+               (void)setuid(uid);
+           }
+#endif /* not HAS_SETREUID */
+           uid = (int)getuid();
+           euid = (int)geteuid();
        }
-       if (delaymagic & DM_REGID) {
+       if (delaymagic & DM_GID) {
 #ifdef HAS_SETREGID
-           setregid(gid,egid);
-#else
-           if (gid != egid || setgid(gid) < 0)
-               fatal("No setregid available");
-#endif
+           (void)setregid(gid,egid);
+#else /* not HAS_SETREGID */
+#ifdef HAS_SETRGID
+           if ((delaymagic & DM_GID) == DM_RGID) {
+               (void)setrgid(gid);
+               delaymagic =~ DM_RGID;
+           }
+#endif /* HAS_SETRGID */
+#ifdef HAS_SETEGID
+           if ((delaymagic & DM_GID) == DM_EGID) {
+               (void)setegid(gid);
+               delaymagic =~ DM_EGID;
+           }
+#endif /* HAS_SETEGID */
+           if (delaymagic & DM_GID) {
+               if (gid != egid)
+                   fatal("No setregid available");
+               (void)setgid(gid);
+           }
+#endif /* not HAS_SETREGID */
+           gid = (int)getgid();
+           egid = (int)getegid();
        }
     }
     delaymagic = 0;
@@ -1498,7 +1566,7 @@ int *arglast;
     else {
        if (len > str->str_cur) {
            STR_GROW(str,len);
-           (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
+           (void)memzero(str->str_ptr + str->str_cur, len - str->str_cur);
            str->str_cur = len;
        }
        s = (unsigned char*)str_get(str);
@@ -1571,6 +1639,7 @@ STR *str;
     }
 }
 
+void
 do_chop(astr,str)
 register STR *astr;
 register STR *str;
@@ -1610,6 +1679,7 @@ register STR *str;
        str_nset(astr,"",0);
 }
 
+void
 do_vop(optype,str,left,right)
 STR *str;
 STR *left;
@@ -1627,7 +1697,7 @@ STR *right;
        str->str_cur = len;
     else if (str->str_cur < len) {
        STR_GROW(str,len);
-       (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
+       (void)memzero(str->str_ptr + str->str_cur, len - str->str_cur);
        str->str_cur = len;
     }
     str->str_pok = 1;
@@ -1666,7 +1736,11 @@ int *arglast;
     register STR **st = stack->ary_array;
     register int sp = arglast[1];
     register int items = arglast[2] - sp;
+#ifdef atarist
+    unsigned long arg[14]; /* yes, we really need that many ! */
+#else
     unsigned long arg[8];
+#endif
     register int i = 0;
     int retval = -1;
 
@@ -1723,6 +1797,32 @@ int *arglast;
        retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
          arg[7]);
        break;
+#ifdef atarist
+    case 9:
+       retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
+         arg[7], arg[8]);
+       break;
+    case 10:
+       retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
+         arg[7], arg[8], arg[9]);
+       break;
+    case 11:
+       retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
+         arg[7], arg[8], arg[9], arg[10]);
+       break;
+    case 12:
+       retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
+         arg[7], arg[8], arg[9], arg[10], arg[11]);
+       break;
+    case 13:
+       retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
+         arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
+       break;
+    case 14:
+       retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
+         arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13]);
+       break;
+#endif /* atarist */
     }
     return retval;
 #else
diff --git a/dump.c b/dump.c
index 273e6cc..f7abd02 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -1,4 +1,4 @@
-/* $RCSfile: dump.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 10:58:44 $
+/* $RCSfile: dump.c,v $$Revision: 4.0.1.2 $$Date: 92/06/08 13:14:22 $
  *
  *    Copyright (c) 1991, Larry Wall
  *
@@ -6,6 +6,10 @@
  *    License or the Artistic License, as specified in the README file.
  *
  * $Log:       dump.c,v $
+ * Revision 4.0.1.2  92/06/08  13:14:22  lwall
+ * patch20: removed implicit int declarations on funcions
+ * patch20: fixed confusion between a *var's real name and its effective name
+ * 
  * Revision 4.0.1.1  91/06/07  10:58:44  lwall
  * patch4: new copyright notice
  * 
@@ -20,6 +24,9 @@
 #ifdef DEBUGGING
 static int dumplvl = 0;
 
+static void dump();
+
+void
 dump_all()
 {
     register int i;
@@ -40,6 +47,7 @@ dump_all()
     }
 }
 
+void
 dump_cmd(cmd,alt)
 register CMD *cmd;
 register CMD *alt;
@@ -160,6 +168,7 @@ register CMD *alt;
     }
 }
 
+void
 dump_arg(arg)
 register ARG *arg;
 {
@@ -231,6 +240,7 @@ register ARG *arg;
     dump("}\n");
 }
 
+void
 dump_flags(b,flags)
 char *b;
 unsigned int flags;
@@ -256,6 +266,7 @@ unsigned int flags;
        b[strlen(b)-1] = '\0';
 }
 
+void
 dump_stab(stab)
 register STAB *stab;
 {
@@ -269,11 +280,17 @@ register STAB *stab;
     dumplvl++;
     fprintf(stderr,"{\n");
     stab_fullname(str,stab);
-    dump("STAB_NAME = %s\n", str->str_ptr);
+    dump("STAB_NAME = %s", str->str_ptr);
+    if (stab != stab_estab(stab)) {
+       stab_efullname(str,stab_estab(stab));
+       dump("-> %s", str->str_ptr);
+    }
+    dump("\n");
     dumplvl--;
     dump("}\n");
 }
 
+void
 dump_spat(spat)
 register SPAT *spat;
 {
@@ -307,7 +324,7 @@ register SPAT *spat;
 }
 
 /* VARARGS1 */
-dump(arg1,arg2,arg3,arg4,arg5)
+static void dump(arg1,arg2,arg3,arg4,arg5)
 char *arg1;
 long arg2, arg3, arg4, arg5;
 {
diff --git a/eval.c b/eval.c
index c8782e2..82b7a8b 100644 (file)
--- a/eval.c
+++ b/eval.c
@@ -1,4 +1,4 @@
-/* $RCSfile: eval.c,v $$Revision: 4.0.1.3 $$Date: 91/11/05 17:15:21 $
+/* $RCSfile: eval.c,v $$Revision: 4.0.1.4 $$Date: 92/06/08 13:20:20 $
  *
  *    Copyright (c) 1991, Larry Wall
  *
@@ -6,6 +6,16 @@
  *    License or the Artistic License, as specified in the README file.
  *
  * $Log:       eval.c,v $
+ * Revision 4.0.1.4  92/06/08  13:20:20  lwall
+ * patch20: added explicit time_t support
+ * patch20: fixed confusion between a *var's real name and its effective name
+ * patch20: added Atari ST portability
+ * patch20: new warning for use of x with non-numeric right operand
+ * patch20: modulus with highest bit in left operand set didn't always work
+ * patch20: dbmclose(%array) didn't work
+ * patch20: added ... as variant on ..
+ * patch20: O_PIPE conflicted with Atari
+ * 
  * Revision 4.0.1.3  91/11/05  17:15:21  lwall
  * patch11: prepared for ctype implementations that don't define isascii()
  * patch11: various portability fixes
 #ifdef I_FCNTL
 #include <fcntl.h>
 #endif
+#ifdef MSDOS
+/* I_FCNTL *MUST* not be defined for MS-DOS and OS/2
+   but fcntl.h is required for O_BINARY */
+#include <fcntl.h>
+#endif
 #ifdef I_SYS_FILE
 #include <sys/file.h>
 #endif
@@ -89,8 +104,10 @@ register int sp;
     int argtype;
     union argptr argptr;
     int arglast[8];    /* highest sp for arg--valid only for non-O_LIST args */
-    unsigned long tmplong;
-    long when;
+    unsigned long tmpulong;
+    long tmplong;
+    time_t when;
+    STRLEN tmplen;
     FILE *fp;
     STR *tmpstr;
     FCMD *form;
@@ -204,7 +221,8 @@ register int sp;
                stab_io(stab) = stio_new();
 #ifdef DEBUGGING
            if (debug & 8) {
-               (void)sprintf(buf,"STAR *%s",stab_name(argptr.arg_stab));
+               (void)sprintf(buf,"STAR *%s -> *%s",
+                   stab_name(argptr.arg_stab), stab_ename(argptr.arg_stab));
                tmps = buf;
            }
 #endif
@@ -213,7 +231,8 @@ register int sp;
            str = st[++sp] = (STR*)argptr.arg_stab;
 #ifdef DEBUGGING
            if (debug & 8) {
-               (void)sprintf(buf,"LSTAR *%s",stab_name(argptr.arg_stab));
+               (void)sprintf(buf,"LSTAR *%s -> *%s",
+               stab_name(argptr.arg_stab), stab_ename(argptr.arg_stab));
                tmps = buf;
            }
 #endif
@@ -390,7 +409,7 @@ register int sp;
            old_rschar = rschar;
            old_rslen = rslen;
            rslen = 1;
-#ifdef MSDOS
+#ifdef DOSISH
            rschar = 0;
 #else
 #ifdef CSH
@@ -433,7 +452,7 @@ register int sp;
                        (void) interp(str,stab_val(last_in_stab),sp);
                        st = stack->ary_array;
                        tmpstr = Str_new(55,0);
-#ifdef MSDOS
+#ifdef DOSISH
                        str_set(tmpstr, "perlglob ");
                        str_scat(tmpstr,str);
                        str_cat(tmpstr," |");
@@ -458,9 +477,9 @@ register int sp;
                }
            }
            if (!fp && dowarn)
-               warn("Read on closed filehandle <%s>",stab_name(last_in_stab));
-           when = str->str_len;        /* remember if already alloced */
-           if (!when)
+               warn("Read on closed filehandle <%s>",stab_ename(last_in_stab));
+           tmplen = str->str_len;      /* remember if already alloced */
+           if (!tmplen)
                Str_Grow(str,80);       /* try short-buffering it */
          keepgoing:
            if (!fp)
@@ -520,7 +539,7 @@ register int sp;
                    str = Str_new(58,80);
                    goto keepgoing;
                }
-               else if (!when && str->str_len - str->str_cur > 80) {
+               else if (!tmplen && str->str_len - str->str_cur > 80) {
                    /* try to reclaim a bit of scalar space on 1st alloc */
                    if (str->str_cur < 60)
                        str->str_len = 80;
@@ -584,8 +603,8 @@ register int sp;
            sp = do_repeatary(arglast);
            goto array_return;
        }
-       STR_SSET(str,st[arglast[1] - arglast[0]]);
-       anum = (int)str_gnum(st[arglast[2] - arglast[0]]);
+       STR_SSET(str,st[1]);
+       anum = (int)str_gnum(st[2]);
        if (anum >= 1) {
            tmpstr = Str_new(50, 0);
            tmps = str_get(str);
@@ -598,8 +617,11 @@ register int sp;
            str->str_nok = 0;
            str_free(tmpstr);
        }
-       else
+       else {
+           if (dowarn && st[2]->str_pok && !looks_like_number(st[2]))
+               warn("Right operand of x is not numeric");
            str_sset(str,&str_no);
+       }
        STABSET(str);
        break;
     case O_MATCH:
@@ -724,15 +746,17 @@ register int sp;
 #endif
        goto donumset;
     case O_MODULO:
-       tmplong = (long) str_gnum(st[2]);
-       if (tmplong == 0L)
+       tmpulong = (unsigned long) str_gnum(st[2]);
+       if (tmpulong == 0L)
            fatal("Illegal modulus zero");
-       when = (long)str_gnum(st[1]);
 #ifndef lint
-       if (when >= 0)
-           value = (double)(when % tmplong);
-       else
-           value = (double)(tmplong - ((-when - 1) % tmplong)) - 1;
+       value = str_gnum(st[1]);
+       if (value >= 0.0)
+           value = (double)(((unsigned long)value) % tmpulong);
+       else {
+           tmplong = (long)value;
+           value = (double)(tmpulong - ((-tmplong - 1) % tmpulong)) - 1;
+       }
 #endif
        goto donumset;
     case O_ADD:
@@ -916,7 +940,7 @@ register int sp;
        }
        break;
     case O_SELECT:
-       stab_fullname(str,defoutstab);
+       stab_efullname(str,defoutstab);
        if (maxarg > 0) {
            if ((arg[1].arg_type & A_MASK) == A_WORD)
                defoutstab = arg[1].arg_ptr.arg_stab;
@@ -989,7 +1013,8 @@ register int sp;
 #endif
     case O_DBMCLOSE:
 #ifdef SOME_DBM
-       if ((arg[1].arg_type & A_MASK) == A_WORD)
+       anum = arg[1].arg_type & A_MASK;
+       if (anum == A_WORD || anum == A_STAB)
            stab = arg[1].arg_ptr.arg_stab;
        else
            stab = stabent(str_get(st[1]),TRUE);
@@ -1074,7 +1099,7 @@ register int sp;
        tmps = str_get(st[2]);
        str = hdelete(stab_hash(tmpstab),tmps,st[2]->str_cur);
        if (tmpstab == envstab)
-           setenv(tmps,Nullch);
+           my_setenv(tmps,Nullch);
        if (!str)
            goto say_undef;
        break;
@@ -1656,7 +1681,7 @@ register int sp;
        if (maxarg < 1)
            (void)time(&when);
        else
-           when = (long)str_gnum(st[1]);
+           when = (time_t)str_gnum(st[1]);
        sp = do_time(str,localtime(&when),
          gimme,arglast);
        goto array_return;
@@ -1664,7 +1689,7 @@ register int sp;
        if (maxarg < 1)
            (void)time(&when);
        else
-           when = (long)str_gnum(st[1]);
+           when = (time_t)str_gnum(st[1]);
        sp = do_time(str,gmtime(&when),
          gimme,arglast);
        goto array_return;
@@ -1869,17 +1894,23 @@ register int sp;
          last_in_stab && (int)str_gnum(st[1]) == stab_io(last_in_stab)->lines
          :
          str_true(st[1]) ) {
-           str_numset(str,0.0);
-           anum = 2;
-           arg->arg_type = optype = O_FLOP;
            arg[2].arg_type &= ~A_DONT;
            arg[1].arg_type |= A_DONT;
-           argflags = arg[2].arg_flags;
-           argtype = arg[2].arg_type & A_MASK;
-           argptr = arg[2].arg_ptr;
-           sp = arglast[0];
-           st -= sp++;
-           goto re_eval;
+           arg->arg_type = optype = O_FLOP;
+           if (arg->arg_flags & AF_COMMON) {
+               str_numset(str,0.0);
+               anum = 2;
+               argflags = arg[2].arg_flags;
+               argtype = arg[2].arg_type & A_MASK;
+               argptr = arg[2].arg_ptr;
+               sp = arglast[0];
+               st -= sp++;
+               goto re_eval;
+           }
+           else {
+               str_numset(str,1.0);
+               break;
+           }
        }
        str_set(str,"");
        break;
@@ -2862,8 +2893,18 @@ donumset:
            stab = stabent(str_get(st[1]),TRUE);
        if (!stab || !(stio = stab_io(stab)) || !(fp = stio->ifp))
            goto say_undef;
-#ifdef MSDOS
+#ifdef DOSISH
+#ifdef atarist
+       if(fflush(fp))
+          str_set(str, No);
+       else
+       {
+           fp->_flag |= _IOBIN;
+           str_set(str, Yes);
+       }
+#else
        str_set(str, (setmode(fileno(fp), O_BINARY) != -1) ? Yes : No);
+#endif
 #else
        str_set(str, Yes);
 #endif
@@ -2938,7 +2979,7 @@ donumset:
     case O_SYSCALL:
        value = (double)do_syscall(arglast);
        goto donumset;
-    case O_PIPE:
+    case O_PIPE_OP:
 #ifdef HAS_PIPE
        if ((arg[1].arg_type & A_MASK) == A_WORD)
            stab = arg[1].arg_ptr.arg_stab;
index b853d12..8dab054 100644 (file)
@@ -48,6 +48,7 @@ sub find {
            unless (($dir,$_) = $topdir =~ m#^(.*/)(.*)$#) {
                ($dir,$_) = ('.', $topdir);
            }
+           $name = $topdir;
            chdir $dir && &wanted;
        }
        chdir $cwd;
@@ -61,7 +62,7 @@ sub finddir {
 
     # Get the list of files in the current directory.
 
-    opendir(DIR,'.') || warn "Can't open $dir: $!\n";
+    opendir(DIR,'.') || (warn "Can't open $dir: $!\n", return);
     local(@filenames) = readdir(DIR);
     closedir(DIR);
 
index 6590918..a0818d1 100644 (file)
@@ -18,6 +18,7 @@ sub Getopts {
            if($args[$pos+1] eq ':') {
                shift(@ARGV);
                if($rest eq '') {
+                   ++$errs unless @ARGV;
                    $rest = shift(@ARGV);
                }
                eval "\$opt_$first = \$rest;";
index f198d8a..10c8c21 100644 (file)
@@ -1 +1 @@
-#define PATCHLEVEL 24
+#define PATCHLEVEL 25
index 032db6b..7e49cd0 100644 (file)
@@ -6,7 +6,7 @@ case $CONFIG in
        ln ../../../config.sh . || \
        (echo "Can't find config.sh."; exit 1)
     fi
-    . config.sh
+    . ./config.sh
     ;;
 esac
 : This forces SH files to create target in same directory as SH file.
@@ -19,9 +19,13 @@ echo "Extracting find2perl (with variable substitutions)"
 : Move anything that needs config subs from !NO!SUBS! section to !GROK!THIS!.
 : Protect any dollar signs and backticks that you do not want interpreted
 : by putting a backslash in front.  You may delete these comments.
+rm -f find2perl
 $spitshell >find2perl <<!GROK!THIS!
 #!$bin/perl
 
+eval 'exec $bin/perl -S \$0 \${1+"\$@"}'
+       if \$running_under_some_shell;
+
 \$bin = "$bin";
 
 !GROK!THIS!
@@ -232,6 +236,9 @@ while (@ARGV) {
 print <<"END";
 #!$bin/perl
 
+eval 'exec $bin/perl -S \$0 \${1+"\$@"}'
+       if \$running_under_some_shell;
+
 END
 
 if ($initls) {
@@ -544,7 +551,7 @@ sub tab {
 
     $tabstring = "\t" x ($indent / 2) . ' ' x ($indent % 2 * 4);
     if (!$statdone) {
-       if ($_ =~ /^(name|print)/) {
+       if ($_ =~ /^(name|print|prune|exec|ok|\(|\))/) {
            $delayedstat++;
        }
        else {