perl 3.0 patch #16 (combined patch)
[p5sagit/p5-mst-13.2.git] / doarg.c
diff --git a/doarg.c b/doarg.c
index 7ff4d4d..c13b17c 100644 (file)
--- a/doarg.c
+++ b/doarg.c
@@ -1,4 +1,4 @@
-/* $Header: doarg.c,v 3.0 89/10/18 15:10:41 lwall Locked $
+/* $Header: doarg.c,v 3.0.1.4 90/03/12 16:28:42 lwall Locked $
  *
  *    Copyright (c) 1989, Larry Wall
  *
@@ -6,6 +6,27 @@
  *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       doarg.c,v $
+ * Revision 3.0.1.4  90/03/12  16:28:42  lwall
+ * patch13: pack of ascii strings could call str_ncat() with negative length
+ * patch13: printf("%s", *foo) was busted
+ * 
+ * Revision 3.0.1.3  90/02/28  16:56:58  lwall
+ * patch9: split now can split into more than 10000 elements
+ * patch9: sped up pack and unpack
+ * patch9: pack of unsigned ints and longs blew up some places
+ * patch9: sun3 can't cast negative float to unsigned int or long
+ * patch9: local($.) didn't work
+ * patch9: grep(s/foo/bar/, @abc = @xyz) modified @xyz rather than @abc
+ * patch9: syscall returned stack size rather than value of system call
+ * 
+ * Revision 3.0.1.2  89/12/21  19:52:15  lwall
+ * patch7: a pattern wouldn't match a null string before the first character
+ * patch7: certain patterns didn't match correctly at end of string
+ * 
+ * Revision 3.0.1.1  89/11/11  04:17:20  lwall
+ * patch2: printf %c, %D, %X and %O didn't work right
+ * patch2: printf of unsigned vs signed needed separate casts on some machines
+ * 
  * Revision 3.0  89/10/18  15:10:41  lwall
  * 3.0 baseline
  * 
@@ -36,6 +57,7 @@ int sp;
     register char *d;
     int clen;
     int iters = 0;
+    int maxiters = (strend - s) + 10;
     register int i;
     bool once;
     char *orig;
@@ -123,7 +145,7 @@ int sp;
        clen = dstr->str_cur;
        if (clen <= spat->spat_slen + spat->spat_regexp->regback) {
                                        /* can do inplace substitution */
-           if (regexec(spat->spat_regexp, s, strend, orig, 1,
+           if (regexec(spat->spat_regexp, s, strend, orig, 0,
              str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
                if (spat->spat_regexp->subbase) /* oops, no we can't */
                    goto long_way;
@@ -184,7 +206,7 @@ int sp;
                    /* NOTREACHED */
                }
                do {
-                   if (iters++ > 10000)
+                   if (iters++ > maxiters)
                        fatal("Substitution loop");
                    m = spat->spat_regexp->startp[0];
                    if (i = m - s) {
@@ -197,8 +219,8 @@ int sp;
                        d += clen;
                    }
                    s = spat->spat_regexp->endp[0];
-               } while (regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr,
-                   TRUE));
+               } while (regexec(spat->spat_regexp, s, strend, orig, s == m,
+                   Nullstr, TRUE));    /* (don't match same null twice) */
                if (s != d) {
                    i = strend - s;
                    str->str_cur = d - str->str_ptr + i;
@@ -216,7 +238,7 @@ int sp;
     }
     else
        c = Nullch;
-    if (regexec(spat->spat_regexp, s, strend, orig, 1,
+    if (regexec(spat->spat_regexp, s, strend, orig, 0,
       str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
     long_way:
        dstr = Str_new(25,str_len(str));
@@ -225,7 +247,7 @@ int sp;
            curspat = spat;
        lastspat = spat;
        do {
-           if (iters++ > 10000)
+           if (iters++ > maxiters)
                fatal("Substitution loop");
            if (spat->spat_regexp->subbase
              && spat->spat_regexp->subbase != orig) {
@@ -248,7 +270,7 @@ int sp;
            }
            if (once)
                break;
-       } while (regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr,
+       } while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr,
            safebase));
        str_ncat(dstr,s,strend - s);
        str_replace(str,dstr);
@@ -343,7 +365,9 @@ int *arglast;
     char achar;
     short ashort;
     int aint;
+    unsigned int auint;
     long along;
+    unsigned long aulong;
     char *aptr;
 
     items = arglast[2] - sp;
@@ -353,9 +377,9 @@ int *arglast;
 #define NEXTFROM (items-- > 0 ? *st++ : &str_no)
        datumtype = *pat++;
        if (isdigit(*pat)) {
-           len = atoi(pat);
+           len = *pat++ - '0';
            while (isdigit(*pat))
-               pat++;
+               len = (len * 10) + (*pat++ - '0');
        }
        else
            len = 1;
@@ -375,22 +399,23 @@ int *arglast;
            aptr = str_get(fromstr);
            if (fromstr->str_cur > len)
                str_ncat(str,aptr,len);
-           else
+           else {
                str_ncat(str,aptr,fromstr->str_cur);
-           len -= fromstr->str_cur;
-           if (datumtype == 'A') {
-               while (len >= 10) {
-                   str_ncat(str,space10,10);
-                   len -= 10;
+               len -= fromstr->str_cur;
+               if (datumtype == 'A') {
+                   while (len >= 10) {
+                       str_ncat(str,space10,10);
+                       len -= 10;
+                   }
+                   str_ncat(str,space10,len);
                }
-               str_ncat(str,space10,len);
-           }
-           else {
-               while (len >= 10) {
-                   str_ncat(str,null10,10);
-                   len -= 10;
+               else {
+                   while (len >= 10) {
+                       str_ncat(str,null10,10);
+                       len -= 10;
+                   }
+                   str_ncat(str,null10,len);
                }
-               str_ncat(str,null10,len);
            }
            break;
        case 'C':
@@ -421,6 +446,12 @@ int *arglast;
            }
            break;
        case 'I':
+           while (len-- > 0) {
+               fromstr = NEXTFROM;
+               auint = (unsigned int)str_gnum(fromstr);
+               str_ncat(str,(char*)&auint,sizeof(unsigned int));
+           }
+           break;
        case 'i':
            while (len-- > 0) {
                fromstr = NEXTFROM;
@@ -439,6 +470,12 @@ int *arglast;
            }
            break;
        case 'L':
+           while (len-- > 0) {
+               fromstr = NEXTFROM;
+               aulong = (unsigned long)str_gnum(fromstr);
+               str_ncat(str,(char*)&aulong,sizeof(unsigned long));
+           }
+           break;
        case 'l':
            while (len-- > 0) {
                fromstr = NEXTFROM;
@@ -473,6 +510,7 @@ register STR **sarg;
     register char *send;
     char *xs;
     int xlen;
+    double value;
 
     str_set(str,"");
     len--;                     /* don't count pattern string */
@@ -505,16 +543,25 @@ register STR **sarg;
            case 'l':
                dolong = TRUE;
                break;
-           case 'D': case 'X': case 'O':
-               dolong = TRUE;
-               /* FALL THROUGH */
            case 'c':
-               *buf = (int)str_gnum(*(sarg++));
-               str_ncat(str,buf,1);    /* force even if null */
-               *buf = '\0';
-               s = t+1;
+               ch = *(++t);
+               *t = '\0';
+               xlen = (int)str_gnum(*(sarg++));
+               if (strEQ(t-2,"%c")) {  /* some printfs fail on null chars */
+                   *buf = xlen;
+                   str_ncat(str,s,t - s - 2);
+                   str_ncat(str,buf,1);  /* so handle simple case */
+                   *buf = '\0';
+               }
+               else
+                   (void)sprintf(buf,s,xlen);
+               s = t;
+               *(t--) = ch;
                break;
-           case 'd': case 'x': case 'o': case 'u':
+           case 'D':
+               dolong = TRUE;
+               /* FALL THROUGH */
+           case 'd':
                ch = *(++t);
                *t = '\0';
                if (dolong)
@@ -524,6 +571,29 @@ register STR **sarg;
                s = t;
                *(t--) = ch;
                break;
+           case 'X': case 'O':
+               dolong = TRUE;
+               /* FALL THROUGH */
+           case 'x': case 'o': case 'u':
+               ch = *(++t);
+               *t = '\0';
+               value = str_gnum(*(sarg++));
+#if defined(sun) && !defined(sparc)
+               if (value < 0.0) {              /* sigh */
+                   if (dolong)
+                       (void)sprintf(buf,s,(long)value);
+                   else
+                       (void)sprintf(buf,s,(int)value);
+               }
+               else
+#endif
+               if (dolong)
+                   (void)sprintf(buf,s,(unsigned long)value);
+               else
+                   (void)sprintf(buf,s,(unsigned int)value);
+               s = t;
+               *(t--) = ch;
+               break;
            case 'E': case 'e': case 'f': case 'G': case 'g':
                ch = *(++t);
                *t = '\0';
@@ -536,7 +606,7 @@ register STR **sarg;
                *t = '\0';
                xs = str_get(*sarg);
                xlen = (*sarg)->str_cur;
-               if (*xs == 'S' && xs[1] == 't' && xs[2] == 'a' && xs[3] == 'b'
+               if (*xs == 'S' && xs[1] == 't' && xs[2] == 'B'
                  && xlen == sizeof(STBP) && strlen(xs) < xlen) {
                    xs = stab_name(((STAB*)(*sarg))); /* a stab value! */
                    sprintf(tokenbuf,"*%s",xs); /* reformat to non-binary */
@@ -768,6 +838,7 @@ int *arglast;
     int i;
 
     makelocal = (arg->arg_flags & AF_LOCAL);
+    localizing = makelocal;
     delaymagic = DM_DELAY;             /* catch simultaneous items */
 
     /* If there's a common identifier on both sides we have to take
@@ -798,9 +869,8 @@ int *arglast;
                while (relem <= lastrelem) {    /* gobble up all the rest */
                    str = Str_new(28,0);
                    if (*relem)
-                       str_sset(str,*(relem++));
-                   else
-                       relem++;
+                       str_sset(str,*relem);
+                   *(relem++) = str;
                    (void)astore(ary,i++,str);
                }
            }
@@ -822,9 +892,8 @@ int *arglast;
                    tmps = str_get(str);
                    tmpstr = Str_new(29,0);
                    if (*relem)
-                       str_sset(tmpstr,*(relem++));    /* value */
-                   else
-                       relem++;
+                       str_sset(tmpstr,*relem);        /* value */
+                   *(relem++) = tmpstr;
                    (void)hstore(hash,tmps,str->str_cur,tmpstr,0);
                }
            }
@@ -834,10 +903,26 @@ int *arglast;
        else {
            if (makelocal)
                saveitem(str);
-           if (relem <= lastrelem)
-               str_sset(str, *(relem++));
-           else
+           if (relem <= lastrelem) {
+               str_sset(str, *relem);
+               *(relem++) = str;
+           }
+           else {
                str_nset(str, "", 0);
+               if (gimme == G_ARRAY) {
+                   i = ++lastrelem - firstrelem;
+                   relem++;            /* tacky, I suppose */
+                   astore(stack,i,str);
+                   if (st != stack->ary_array) {
+                       st = stack->ary_array;
+                       firstrelem = st + arglast[1] + 1;
+                       firstlelem = st + arglast[0] + 1;
+                       lastlelem = st + arglast[1];
+                       lastrelem = st + i;
+                       relem = lastrelem + 1;
+                   }
+               }
+           }
            STABSET(str);
        }
     }
@@ -852,6 +937,7 @@ int *arglast;
 #endif
     }
     delaymagic = 0;
+    localizing = FALSE;
     if (gimme == G_ARRAY) {
        i = lastrelem - firstrelem + 1;
        if (ary || hash)
@@ -1253,9 +1339,7 @@ int *arglast;
          arg[7]);
        break;
     }
-    st[sp] = str_static(&str_undef);
-    str_numset(st[sp], (double)retval);
-    return sp;
+    return retval;
 #else
     fatal("syscall() unimplemented");
 #endif