perl 3.0 patch #21 patch #19, continued
[p5sagit/p5-mst-13.2.git] / doarg.c
diff --git a/doarg.c b/doarg.c
index 43d945f..48b614e 100644 (file)
--- a/doarg.c
+++ b/doarg.c
@@ -1,4 +1,4 @@
-/* $Header: doarg.c,v 3.0.1.3 90/02/28 16:56:58 lwall Locked $
+/* $Header: doarg.c,v 3.0.1.6 90/08/09 02:48:38 lwall Locked $
  *
  *    Copyright (c) 1989, Larry Wall
  *
@@ -6,6 +6,24 @@
  *    as specified in the README file that comes with the perl 3.0 kit.
  *
  * $Log:       doarg.c,v $
+ * Revision 3.0.1.6  90/08/09  02:48:38  lwall
+ * patch19: fixed double include of <signal.h>
+ * patch19: pack/unpack can now do native float and double
+ * patch19: pack/unpack can now have absolute and negative positioning
+ * patch19: pack/unpack can now have use * to specify all the rest of input
+ * patch19: unpack can do checksumming
+ * patch19: $< and $> better supported on machines without setreuid
+ * patch19: Added support for linked-in C subroutines
+ * 
+ * Revision 3.0.1.5  90/03/27  15:39:03  lwall
+ * patch16: MSDOS support
+ * patch16: support for machines that can't cast negative floats to unsigned ints
+ * patch16: sprintf($s,...,$s,...) didn't work
+ * 
+ * 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
 #include "EXTERN.h"
 #include "perl.h"
 
+#ifndef NSIG
 #include <signal.h>
+#endif
 
 extern unsigned char fold[];
 
 int wantarray;
 
+#ifdef BUGGY_MSC
+ #pragma function(memcmp)
+#endif /* BUGGY_MSC */
+
 int
 do_subst(str,arg,sp)
 STR *str;
@@ -70,7 +94,7 @@ int sp;
        if (spat->spat_regexp)
            regfree(spat->spat_regexp);
        spat->spat_regexp = regcomp(m,m+dstr->str_cur,
-           spat->spat_flags & SPAT_FOLD,1);
+           spat->spat_flags & SPAT_FOLD);
        if (spat->spat_flags & SPAT_KEEP) {
            arg_free(spat->spat_runtime);       /* it won't change, so */
            spat->spat_runtime = Nullarg;       /* no point compiling again */
@@ -285,6 +309,9 @@ nope:
     stack->ary_array[++sp] = arg->arg_ptr.arg_str;
     return sp;
 }
+#ifdef BUGGY_MSC
+ #pragma intrinsic(memcmp)
+#endif /* BUGGY_MSC */
 
 int
 do_trans(str,arg)
@@ -365,6 +392,8 @@ int *arglast;
     long along;
     unsigned long aulong;
     char *aptr;
+    float afloat;
+    double adouble;
 
     items = arglast[2] - sp;
     st += ++sp;
@@ -372,7 +401,11 @@ int *arglast;
     while (pat < patend) {
 #define NEXTFROM (items-- > 0 ? *st++ : &str_no)
        datumtype = *pat++;
-       if (isdigit(*pat)) {
+       if (*pat == '*') {
+           len = index("@Xxu",datumtype) ? 0 : items;
+           pat++;
+       }
+       else if (isdigit(*pat)) {
            len = *pat++ - '0';
            while (isdigit(*pat))
                len = (len * 10) + (*pat++ - '0');
@@ -382,7 +415,25 @@ int *arglast;
        switch(datumtype) {
        default:
            break;
+       case '%':
+           fatal("% may only be used in unpack");
+       case '@':
+           len -= str->str_cur;
+           if (len > 0)
+               goto grow;
+           len = -len;
+           if (len > 0)
+               goto shrink;
+           break;
+       case 'X':
+         shrink:
+           str->str_cur -= len;
+           if (str->str_cur < 0)
+               fatal("X outside of string");
+           str->str_ptr[str->str_cur] = '\0';
+           break;
        case 'x':
+         grow:
            while (len >= 10) {
                str_ncat(str,null10,10);
                len -= 10;
@@ -393,24 +444,27 @@ int *arglast;
        case 'a':
            fromstr = NEXTFROM;
            aptr = str_get(fromstr);
+           if (pat[-1] == '*')
+               len = fromstr->str_cur;
            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':
@@ -422,6 +476,23 @@ int *arglast;
                str_ncat(str,&achar,sizeof(char));
            }
            break;
+       /* Float and double added by gnb@melba.bby.oz.au  22/11/89 */
+       case 'f':
+       case 'F':
+           while (len-- > 0) {
+               fromstr = NEXTFROM;
+               afloat = (float)str_gnum(fromstr);
+               str_ncat(str, (char *)&afloat, sizeof (float));
+           }
+           break;
+       case 'd':
+       case 'D':
+           while (len-- > 0) {
+               fromstr = NEXTFROM;
+               adouble = (double)str_gnum(fromstr);
+               str_ncat(str, (char *)&adouble, sizeof (double));
+           }
+           break;
        case 'n':
            while (len-- > 0) {
                fromstr = NEXTFROM;
@@ -443,7 +514,7 @@ int *arglast;
        case 'I':
            while (len-- > 0) {
                fromstr = NEXTFROM;
-               auint = (unsigned int)str_gnum(fromstr);
+               auint = U_I(str_gnum(fromstr));
                str_ncat(str,(char*)&auint,sizeof(unsigned int));
            }
            break;
@@ -467,7 +538,7 @@ int *arglast;
        case 'L':
            while (len-- > 0) {
                fromstr = NEXTFROM;
-               aulong = (unsigned long)str_gnum(fromstr);
+               aulong = U_L(str_gnum(fromstr));
                str_ncat(str,(char*)&aulong,sizeof(unsigned long));
            }
            break;
@@ -485,12 +556,55 @@ int *arglast;
                str_ncat(str,(char*)&aptr,sizeof(char*));
            }
            break;
+       case 'u':
+           fromstr = NEXTFROM;
+           aptr = str_get(fromstr);
+           aint = fromstr->str_cur;
+           STR_GROW(str,aint * 4 / 3);
+           if (len <= 1)
+               len = 45;
+           else
+               len = len / 3 * 3;
+           while (aint > 0) {
+               int todo;
+
+               if (aint > len)
+                   todo = len;
+               else
+                   todo = aint;
+               doencodes(str, aptr, todo);
+               aint -= todo;
+               aptr += todo;
+           }
+           break;
        }
     }
     STABSET(str);
 }
 #undef NEXTFROM
 
+doencodes(str, s, len)
+register STR *str;
+register char *s;
+register int len;
+{
+    char hunk[5];
+
+    *hunk = len + ' ';
+    str_ncat(str, hunk, 1);
+    hunk[4] = '\0';
+    while (len > 0) {
+       hunk[0] = ' ' + (077 & (*s >> 2));
+       hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017));
+       hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03));
+       hunk[3] = ' ' + (077 & (s[2] & 077));
+       str_ncat(str, hunk, 4);
+       s += 3;
+       len -= 3;
+    }
+    str_ncat(str, "\n", 1);
+}
+
 void
 do_sprintf(str,len,sarg)
 register STR *str;
@@ -506,10 +620,11 @@ register STR **sarg;
     char *xs;
     int xlen;
     double value;
+    char *origs;
 
     str_set(str,"");
     len--;                     /* don't count pattern string */
-    s = str_get(*sarg);
+    origs = s = str_get(*sarg);
     send = s + (*sarg)->str_cur;
     sarg++;
     for ( ; s < send; len--) {
@@ -573,19 +688,10 @@ register STR **sarg;
                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);
+                   (void)sprintf(buf,s,U_L(value));
                else
-                   (void)sprintf(buf,s,(unsigned int)value);
+                   (void)sprintf(buf,s,U_I(value));
                s = t;
                *(t--) = ch;
                break;
@@ -601,7 +707,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 */
@@ -611,10 +717,17 @@ register STR **sarg;
                if (strEQ(t-2,"%s")) {  /* some printfs fail on >128 chars */
                    *buf = '\0';
                    str_ncat(str,s,t - s - 2);
+                   *t = ch;
                    str_ncat(str,xs,xlen);  /* so handle simple case */
                }
-               else
+               else {
+                   if (origs == xs) {          /* sprintf($s,...$s...) */
+                       strcpy(tokenbuf+64,s);
+                       s = tokenbuf+64;
+                       *t = ch;
+                   }
                    (void)sprintf(buf,s,xs);
+               }
                sarg++;
                s = t;
                *(t--) = ch;
@@ -702,17 +815,23 @@ int *arglast;
     }
     if (!stab)
        fatal("Undefined subroutine called");
+    saveint(&wantarray);
+    wantarray = gimme;
     sub = stab_sub(stab);
     if (!sub)
        fatal("Undefined subroutine \"%s\" called", stab_name(stab));
+    if (sub->usersub) {
+       st[sp] = arg->arg_ptr.arg_str;
+       if ((arg[2].arg_type & A_MASK) == A_NULL)
+           items = 0;
+       return sub->usersub(sub->userindex,sp,items);
+    }
     if ((arg[2].arg_type & A_MASK) != A_NULL) {
        savearray = stab_xarray(defstab);
        stab_xarray(defstab) = afake(defstab, items, &st[sp+1]);
     }
     savelong(&sub->depth);
     sub->depth++;
-    saveint(&wantarray);
-    wantarray = gimme;
     if (sub->depth >= 2) {     /* save temporaries on recursion? */
        if (sub->depth == 100 && dowarn)
            warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
@@ -767,9 +886,8 @@ int *arglast;
     }
     if (!stab)
        fatal("Undefined subroutine called");
-    sub = stab_sub(stab);
-    if (!sub)
-       fatal("Undefined subroutine \"%s\" called", stab_name(stab));
+    saveint(&wantarray);
+    wantarray = gimme;
 /* begin differences */
     str = stab_val(DBsub);
     saveitem(str);
@@ -784,8 +902,6 @@ int *arglast;
     }
     savelong(&sub->depth);
     sub->depth++;
-    saveint(&wantarray);
-    wantarray = gimme;
     if (sub->depth >= 2) {     /* save temporaries on recursion? */
        if (sub->depth == 100 && dowarn)
            warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
@@ -922,14 +1038,22 @@ int *arglast;
        }
     }
     if (delaymagic > 1) {
+       if (delaymagic & DM_REUID) {
 #ifdef SETREUID
-       if (delaymagic & DM_REUID)
            setreuid(uid,euid);
+#else
+           if (uid != euid || setuid(uid) < 0)
+               fatal("No setreuid available");
 #endif
+       }
+       if (delaymagic & DM_REGID) {
 #ifdef SETREGID
-       if (delaymagic & DM_REGID)
            setregid(gid,egid);
+#else
+           if (gid != egid || setgid(gid) < 0)
+               fatal("No setregid available");
 #endif
+       }
     }
     delaymagic = 0;
     localizing = FALSE;
@@ -1041,12 +1165,12 @@ int *arglast;
        retval = stab_xarray(arg[1].arg_ptr.arg_stab) != 0;
     else if (type == O_HASH || type == O_LHASH)
        retval = stab_xhash(arg[1].arg_ptr.arg_stab) != 0;
-    else if (type == O_SUBR || type == O_DBSUBR)
-       retval = stab_sub(arg[1].arg_ptr.arg_stab) != 0;
     else if (type == O_ASLICE || type == O_LASLICE)
        retval = stab_xarray(arg[1].arg_ptr.arg_stab) != 0;
     else if (type == O_HSLICE || type == O_LHSLICE)
        retval = stab_xhash(arg[1].arg_ptr.arg_stab) != 0;
+    else if (type == O_SUBR || type == O_DBSUBR)
+       retval = stab_sub(arg[1].arg_ptr.arg_stab) != 0;
     else
        retval = FALSE;
     str_numset(str,(double)retval);
@@ -1160,7 +1284,7 @@ STR *str;
     register int offset;
     register int size;
     register unsigned char *s = (unsigned char*)mstr->str_ptr;
-    register unsigned long lval = (unsigned long)str_gnum(str);
+    register unsigned long lval = U_L(str_gnum(str));
     int mask;
 
     mstr->str_rare = 0;