This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 4.0 patch 18: patch #11, continued
[perl5.git] / eval.c
diff --git a/eval.c b/eval.c
index 51ffd0c..c8782e2 100644 (file)
--- a/eval.c
+++ b/eval.c
@@ -1,11 +1,34 @@
-/* $Header: eval.c,v 4.0 91/03/20 01:16:48 lwall Locked $
+/* $RCSfile: eval.c,v $$Revision: 4.0.1.3 $$Date: 91/11/05 17:15:21 $
  *
- *    Copyright (c) 1989, Larry Wall
+ *    Copyright (c) 1991, Larry Wall
  *
- *    You may distribute under the terms of the GNU General Public License
- *    as specified in the README file that comes with the perl 3.0 kit.
+ *    You may distribute under the terms of either the GNU General Public
+ *    License or the Artistic License, as specified in the README file.
  *
  * $Log:       eval.c,v $
+ * 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
+ * patch11: added sort {} LIST
+ * patch11: added eval {}
+ * patch11: sysread() in socket was substituting recv()
+ * patch11: a last statement outside any block caused occasional core dumps
+ * patch11: missing arguments caused core dump in -D8 code
+ * patch11: eval 'stuff' now optimized to eval {stuff}
+ * 
+ * Revision 4.0.1.2  91/06/07  11:07:23  lwall
+ * patch4: new copyright notice
+ * patch4: length($`), length($&), length($') now optimized to avoid string copy
+ * patch4: assignment wasn't correctly de-tainting the assigned variable.
+ * patch4: default top-of-form format is now FILEHANDLE_TOP
+ * patch4: added $^P variable to control calling of perldb routines
+ * patch4: taintchecks could improperly modify parent in vfork()
+ * patch4: many, many itty-bitty portability fixes
+ * 
+ * Revision 4.0.1.1  91/04/11  17:43:48  lwall
+ * patch1: fixed failed fork to return undef as documented
+ * patch1: reduced maximum branch distance in eval.c
+ * 
  * Revision 4.0  91/03/20  01:16:48  lwall
  * 4.0 baseline.
  * 
@@ -204,6 +227,16 @@ register int sp;
            }
 #endif
            break;
+       case A_LENSTAB:
+           str_numset(str, (double)STAB_LEN(argptr.arg_stab));
+           st[++sp] = str;
+#ifdef DEBUGGING
+           if (debug & 8) {
+               (void)sprintf(buf,"LENSTAB $%s",stab_name(argptr.arg_stab));
+               tmps = buf;
+           }
+#endif
+           break;
        case A_LEXPR:
 #ifdef DEBUGGING
            if (debug & 8) {
@@ -303,6 +336,7 @@ register int sp;
            if (fp) {
                if (gimme == G_SCALAR) {
                    while (str_gets(str,fp,str->str_cur) != Nullch)
+                       /*SUPPRESS 530*/
                        ;
                }
                else {
@@ -467,7 +501,7 @@ register int sp;
                    else
                        str->str_cur++;
                    for (tmps = str->str_ptr; *tmps; tmps++)
-                       if (!isalpha(*tmps) && !isdigit(*tmps) &&
+                       if (!isALPHA(*tmps) && !isDIGIT(*tmps) &&
                            index("$&*(){}[]'\";\\|?<>~`",*tmps))
                                break;
                    if (*tmps && stat(str->str_ptr,&statbuf) < 0)
@@ -615,6 +649,10 @@ register int sp;
        goto array_return;
     case O_SASSIGN:
       sassign:
+#ifdef TAINT
+       if (tainted && !st[2]->str_tainted)
+           tainted = 0;
+#endif
        STR_SSET(str, st[2]);
        STABSET(str);
        break;
@@ -667,7 +705,7 @@ register int sp;
     case O_DIVIDE:
        if ((value = str_gnum(st[2])) == 0.0)
            fatal("Illegal division by zero");
-#ifdef cray
+#ifdef SLOPPYDIVIDE
        /* insure that 20./5. == 4. */
        {
            double x;
@@ -857,7 +895,11 @@ register int sp;
        value = -str_gnum(st[1]);
        goto donumset;
     case O_NOT:
+#ifdef NOTNOT
+       { char xxx = str_true(st[1]); value = (double) !xxx; }
+#else
        value = (double) !str_true(st[1]);
+#endif
        goto donumset;
     case O_COMPLEMENT:
        if (!sawvec || st[1]->str_nok) {
@@ -923,7 +965,7 @@ register int sp;
            break;
        }
        format(&outrec,form,sp);
-       do_write(&outrec,stab_io(stab),sp);
+       do_write(&outrec,stab,sp);
        if (stab_io(stab)->flags & IOF_FLUSH)
            (void)fflush(fp);
        str_set(str, Yes);
@@ -1083,7 +1125,7 @@ register int sp;
        else if (stab_hash(tmpstab)->tbl_dbm)
            str_magic(str, tmpstab, 'D', tmps, anum);
 #endif
-       else if (perldb && tmpstab == DBline)
+       else if (tmpstab == DBline)
            str_magic(str, tmpstab, 'L', tmps, anum);
        break;
     case O_LSLICE:
@@ -1152,6 +1194,7 @@ register int sp;
     case O_SUBSTR:
        anum = ((int)str_gnum(st[2])) - arybase;        /* anum=where to start*/
        tmps = str_get(st[1]);          /* force conversion to string */
+       /*SUPPRESS 560*/
        if (argtype = (str == st[1]))
            str = arg->arg_ptr.arg_str;
        if (anum < 0)
@@ -1177,6 +1220,7 @@ register int sp;
        }
        break;
     case O_PACK:
+       /*SUPPRESS 701*/
        (void)do_pack(str,arglast);
        break;
     case O_GREP:
@@ -1226,11 +1270,7 @@ register int sp;
        st = stack->ary_array + arglast[0];             /* maybe realloced */
        goto array_return;
     case O_SORT:
-       if ((arg[1].arg_type & A_MASK) == A_WORD)
-           stab = arg[1].arg_ptr.arg_stab;
-       else
-           stab = stabent(str_get(st[1]),TRUE);
-       sp = do_sort(str,stab,
+       sp = do_sort(str,arg,
          gimme,arglast);
        goto array_return;
     case O_REVERSE:
@@ -1424,6 +1464,10 @@ register int sp;
            goto badsock;
 #endif
        STR_GROW(st[2], anum+maxarg+1), (tmps = str_get(st[2]));  /* sneaky */
+       if (optype == O_SYSREAD) {
+           anum = read(fileno(stab_io(stab)->ifp), tmps+maxarg, anum);
+       }
+       else
 #ifdef HAS_SOCKET
        if (stab_io(stab)->type == 's') {
            argtype = sizeof buf;
@@ -1432,10 +1476,6 @@ register int sp;
        }
        else
 #endif
-       if (optype == O_SYSREAD) {
-           anum = read(fileno(stab_io(stab)->ifp), tmps+maxarg, anum);
-       }
-       else
            anum = fread(tmps+maxarg, 1, anum, stab_io(stab)->ifp);
        if (anum < 0)
            goto say_undef;
@@ -1514,6 +1554,7 @@ register int sp;
     case O_REDO:
     case O_NEXT:
     case O_LAST:
+       tmps = Nullch;
        if (maxarg > 0) {
            tmps = str_get(arg[1].arg_ptr.arg_str);
          dopop:
@@ -1857,10 +1898,13 @@ register int sp;
     case O_FORK:
 #ifdef HAS_FORK
        anum = fork();
+       if (anum < 0)
+           goto say_undef;
        if (!anum) {
+           /*SUPPRESS 560*/
            if (tmpstab = stabent("$",allstabs))
                str_numset(STAB_STR(tmpstab),(double)getpid());
-           hclear(pidstatus);  /* no kids, so don't wait for 'em */
+           hclear(pidstatus, FALSE);   /* no kids, so don't wait for 'em */
        }
        value = (double)anum;
        goto donumset;
@@ -1955,6 +1999,11 @@ register int sp;
        else if (arglast[2] - arglast[1] != 1)
            value = (double)do_aexec(Nullstr,arglast);
        else {
+#ifdef TAINT
+           taintenv();
+           tainted |= st[2]->str_tainted;
+           taintproper("Insecure dependency in exec");
+#endif
            value = (double)do_exec(str_get(str_mortal(st[2])));
        }
        goto donumset;
@@ -1971,13 +2020,71 @@ register int sp;
            tmps = str_get(stab_val(defstab));
        else
            tmps = str_get(st[1]);
-       while (*tmps && isascii(*tmps) && (isspace(*tmps) || *tmps == '0'))
+       while (*tmps && (isSPACE(*tmps) || *tmps == '0'))
            tmps++;
        if (*tmps == 'x')
            value = (double)scanhex(++tmps, 99, &argtype);
        else
            value = (double)scanoct(tmps, 99, &argtype);
        goto donumset;
+
+/* These common exits are hidden here in the middle of the switches for the
+   benefit of those machines with limited branch addressing.  Sigh.  */
+
+array_return:
+#ifdef DEBUGGING
+    if (debug) {
+       dlevel--;
+       if (debug & 8) {
+           anum = sp - arglast[0];
+           switch (anum) {
+           case 0:
+               deb("%s RETURNS ()\n",opname[optype]);
+               break;
+           case 1:
+               deb("%s RETURNS (\"%s\")\n",opname[optype],
+                   st[1] ? str_get(st[1]) : "");
+               break;
+           default:
+               tmps = st[1] ? str_get(st[1]) : "";
+               deb("%s RETURNS %d ARGS (\"%s\",%s\"%s\")\n",opname[optype],
+                 anum,tmps,anum==2?"":"...,",
+                       st[anum] ? str_get(st[anum]) : "");
+               break;
+           }
+       }
+    }
+#endif
+    return sp;
+
+say_yes:
+    str = &str_yes;
+    goto normal_return;
+
+say_no:
+    str = &str_no;
+    goto normal_return;
+
+say_undef:
+    str = &str_undef;
+    goto normal_return;
+
+say_zero:
+    value = 0.0;
+    /* FALL THROUGH */
+
+donumset:
+    str_numset(str,value);
+    STABSET(str);
+    st[1] = str;
+#ifdef DEBUGGING
+    if (debug) {
+       dlevel--;
+       if (debug & 8)
+           deb("%s RETURNS \"%f\"\n",opname[optype],value);
+    }
+#endif
+    return arglast[0] + 1;
 #ifdef SMALLSWITCHES
     }
     else
@@ -2198,7 +2305,13 @@ register int sp;
            anum = 0;
        else
            anum = (int)str_gnum(st[1]);
+#ifdef _POSIX_SOURCE
+       if (anum != 0)
+           fatal("POSIX getpgrp can't take an argument");
+       value = (double)getpgrp();
+#else
        value = (double)getpgrp(anum);
+#endif
        goto donumset;
 #else
        fatal("The getpgrp() function is unimplemented on this machine");
@@ -2314,6 +2427,22 @@ register int sp;
        value = (double)(ary->ary_fill + 1);
        goto donumset;
 
+    case O_TRY:
+       sp = do_try(arg[1].arg_ptr.arg_cmd,
+           gimme,arglast);
+       goto array_return;
+
+    case O_EVALONCE:
+       sp = do_eval(st[1], O_EVAL, curcmd->c_stash, TRUE,
+           gimme,arglast);
+       if (eval_root) {
+           str_free(arg[1].arg_ptr.arg_str);
+           arg[1].arg_ptr.arg_cmd = eval_root;
+           arg[1].arg_type = (A_CMD|A_DONT);
+           arg[0].arg_type = O_TRY;
+       }
+       goto array_return;
+
     case O_REQUIRE:
     case O_DOFILE:
     case O_EVAL:
@@ -2326,7 +2455,7 @@ register int sp;
        tainted |= tmpstr->str_tainted;
        taintproper("Insecure dependency in eval");
 #endif
-       sp = do_eval(tmpstr, optype, curcmd->c_stash,
+       sp = do_eval(tmpstr, optype, curcmd->c_stash, FALSE,
            gimme,arglast);
        goto array_return;
 
@@ -2502,7 +2631,7 @@ register int sp;
            stab = stabent(tmps = str_get(st[1]),FALSE);
        if (stab && stab_io(stab) && stab_io(stab)->ifp)
            anum = fileno(stab_io(stab)->ifp);
-       else if (isdigit(*tmps))
+       else if (isDIGIT(*tmps))
            anum = atoi(tmps);
        else
            goto say_undef;
@@ -2790,7 +2919,7 @@ register int sp;
        fatal("Unsupported function getlogin");
 #endif
        break;
-    case O_OPENDIR:
+    case O_OPEN_DIR:
     case O_READDIR:
     case O_TELLDIR:
     case O_SEEKDIR:
@@ -2837,57 +2966,4 @@ register int sp;
     }
 #endif
     return arglast[0] + 1;
-
-array_return:
-#ifdef DEBUGGING
-    if (debug) {
-       dlevel--;
-       if (debug & 8) {
-           anum = sp - arglast[0];
-           switch (anum) {
-           case 0:
-               deb("%s RETURNS ()\n",opname[optype]);
-               break;
-           case 1:
-               deb("%s RETURNS (\"%s\")\n",opname[optype],str_get(st[1]));
-               break;
-           default:
-               tmps = str_get(st[1]);
-               deb("%s RETURNS %d ARGS (\"%s\",%s\"%s\")\n",opname[optype],
-                 anum,tmps,anum==2?"":"...,",str_get(st[anum]));
-               break;
-           }
-       }
-    }
-#endif
-    return sp;
-
-say_yes:
-    str = &str_yes;
-    goto normal_return;
-
-say_no:
-    str = &str_no;
-    goto normal_return;
-
-say_undef:
-    str = &str_undef;
-    goto normal_return;
-
-say_zero:
-    value = 0.0;
-    /* FALL THROUGH */
-
-donumset:
-    str_numset(str,value);
-    STABSET(str);
-    st[1] = str;
-#ifdef DEBUGGING
-    if (debug) {
-       dlevel--;
-       if (debug & 8)
-           deb("%s RETURNS \"%f\"\n",opname[optype],value);
-    }
-#endif
-    return arglast[0] + 1;
 }