perl 3.0 patch #30 patch #29, continued
[p5sagit/p5-mst-13.2.git] / array.c
diff --git a/array.c b/array.c
index 156b783..aff66ca 100644 (file)
--- a/array.c
+++ b/array.c
@@ -1,25 +1,56 @@
-/* $Header: array.c,v 1.0 87/12/18 13:04:42 root Exp $
+/* $Header: array.c,v 3.0.1.3 90/10/15 14:56:17 lwall Locked $
+ *
+ *    Copyright (c) 1989, 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.
  *
  * $Log:       array.c,v $
- * Revision 1.0  87/12/18  13:04:42  root
- * Initial revision
+ * Revision 3.0.1.3  90/10/15  14:56:17  lwall
+ * patch29: non-existent array values no longer cause core dumps
+ * 
+ * Revision 3.0.1.2  90/08/13  21:52:20  lwall
+ * patch28: defined(@array) and defined(%array) didn't work right
+ * 
+ * Revision 3.0.1.1  89/11/17  15:02:52  lwall
+ * patch5: nested foreach on same array didn't work
+ * 
+ * Revision 3.0  89/10/18  15:08:33  lwall
+ * 3.0 baseline
  * 
  */
 
-#include <stdio.h>
 #include "EXTERN.h"
-#include "handy.h"
-#include "util.h"
-#include "search.h"
 #include "perl.h"
 
 STR *
-afetch(ar,key)
+afetch(ar,key,lval)
 register ARRAY *ar;
 int key;
+int lval;
 {
-    if (key < 0 || key > ar->ary_max)
-       return Nullstr;
+    STR *str;
+
+    if (key < 0 || key > ar->ary_fill) {
+       if (lval && key >= 0) {
+           if (ar->ary_flags & ARF_REAL)
+               str = Str_new(5,0);
+           else
+               str = str_static(&str_undef);
+           (void)astore(ar,key,str);
+           return str;
+       }
+       else
+           return &str_undef;
+    }
+    if (!ar->ary_array[key]) {
+       if (lval) {
+           str = Str_new(6,0);
+           (void)astore(ar,key,str);
+           return str;
+       }
+       return &str_undef;
+    }
     return ar->ary_array[key];
 }
 
@@ -29,56 +60,108 @@ register ARRAY *ar;
 int key;
 STR *val;
 {
-    bool retval;
+    int retval;
 
     if (key < 0)
        return FALSE;
     if (key > ar->ary_max) {
-       int newmax = key + ar->ary_max / 5;
+       int newmax;
 
-       ar->ary_array = (STR**)saferealloc((char*)ar->ary_array,
-           (newmax+1) * sizeof(STR*));
-       bzero((char*)&ar->ary_array[ar->ary_max+1],
-           (newmax - ar->ary_max) * sizeof(STR*));
-       ar->ary_max = newmax;
+       if (ar->ary_alloc != ar->ary_array) {
+           retval = ar->ary_array - ar->ary_alloc;
+           Copy(ar->ary_array, ar->ary_alloc, ar->ary_max+1, STR*);
+           Zero(ar->ary_alloc+ar->ary_max+1, retval, STR*);
+           ar->ary_max += retval;
+           ar->ary_array -= retval;
+           if (key > ar->ary_max - 10) {
+               newmax = key + ar->ary_max;
+               goto resize;
+           }
+       }
+       else {
+           if (ar->ary_alloc) {
+               newmax = key + ar->ary_max / 5;
+             resize:
+               Renew(ar->ary_alloc,newmax+1, STR*);
+               Zero(&ar->ary_alloc[ar->ary_max+1], newmax - ar->ary_max, STR*);
+           }
+           else {
+               newmax = key < 4 ? 4 : key;
+               Newz(2,ar->ary_alloc, newmax+1, STR*);
+           }
+           ar->ary_array = ar->ary_alloc;
+           ar->ary_max = newmax;
+       }
+    }
+    if ((ar->ary_flags & ARF_REAL) && ar->ary_fill < key) {
+       while (++ar->ary_fill < key) {
+           if (ar->ary_array[ar->ary_fill] != Nullstr) {
+               str_free(ar->ary_array[ar->ary_fill]);
+               ar->ary_array[ar->ary_fill] = Nullstr;
+           }
+       }
     }
-    if (key > ar->ary_fill)
-       ar->ary_fill = key;
     retval = (ar->ary_array[key] != Nullstr);
-    if (retval)
+    if (retval && (ar->ary_flags & ARF_REAL))
        str_free(ar->ary_array[key]);
     ar->ary_array[key] = val;
     return retval;
 }
 
-bool
-adelete(ar,key)
-register ARRAY *ar;
-int key;
+ARRAY *
+anew(stab)
+STAB *stab;
 {
-    if (key < 0 || key > ar->ary_max)
-       return FALSE;
-    if (ar->ary_array[key]) {
-       str_free(ar->ary_array[key]);
-       ar->ary_array[key] = Nullstr;
-       return TRUE;
-    }
-    return FALSE;
+    register ARRAY *ar;
+
+    New(1,ar,1,ARRAY);
+    ar->ary_magic = Str_new(7,0);
+    ar->ary_alloc = ar->ary_array = 0;
+    str_magic(ar->ary_magic, stab, '#', Nullch, 0);
+    ar->ary_max = ar->ary_fill = -1;
+    ar->ary_flags = ARF_REAL;
+    return ar;
 }
 
 ARRAY *
-anew()
+afake(stab,size,strp)
+STAB *stab;
+int size;
+STR **strp;
 {
-    register ARRAY *ar = (ARRAY*)safemalloc(sizeof(ARRAY));
+    register ARRAY *ar;
 
-    ar->ary_array = (STR**) safemalloc(5 * sizeof(STR*));
-    ar->ary_fill = -1;
-    ar->ary_max = 4;
-    bzero((char*)ar->ary_array, 5 * sizeof(STR*));
+    New(3,ar,1,ARRAY);
+    New(4,ar->ary_alloc,size+1,STR*);
+    Copy(strp,ar->ary_alloc,size,STR*);
+    ar->ary_array = ar->ary_alloc;
+    ar->ary_magic = Str_new(8,0);
+    str_magic(ar->ary_magic, stab, '#', Nullch, 0);
+    ar->ary_fill = size - 1;
+    ar->ary_max = size - 1;
+    ar->ary_flags = 0;
     return ar;
 }
 
 void
+aclear(ar)
+register ARRAY *ar;
+{
+    register int key;
+
+    if (!ar || !(ar->ary_flags & ARF_REAL) || ar->ary_max < 0)
+       return;
+    if (key = ar->ary_array - ar->ary_alloc) {
+       ar->ary_max += key;
+       ar->ary_array -= key;
+    }
+    for (key = 0; key <= ar->ary_max; key++)
+       str_free(ar->ary_array[key]);
+    ar->ary_fill = -1;
+    Zero(ar->ary_array, ar->ary_max+1, STR*);
+}
+
+void
 afree(ar)
 register ARRAY *ar;
 {
@@ -86,10 +169,17 @@ register ARRAY *ar;
 
     if (!ar)
        return;
-    for (key = 0; key <= ar->ary_fill; key++)
-       str_free(ar->ary_array[key]);
-    safefree((char*)ar->ary_array);
-    safefree((char*)ar);
+    if (key = ar->ary_array - ar->ary_alloc) {
+       ar->ary_max += key;
+       ar->ary_array -= key;
+    }
+    if (ar->ary_flags & ARF_REAL) {
+       for (key = 0; key <= ar->ary_max; key++)
+           str_free(ar->ary_array[key]);
+    }
+    str_free(ar->ary_magic);
+    Safefree(ar->ary_alloc);
+    Safefree(ar);
 }
 
 bool
@@ -122,13 +212,21 @@ register int num;
 
     if (num <= 0)
        return;
-    astore(ar,ar->ary_fill+num,(STR*)0);       /* maybe extend array */
-    sstr = ar->ary_array + ar->ary_fill;
-    dstr = sstr + num;
-    for (i = ar->ary_fill; i >= 0; i--) {
-       *dstr-- = *sstr--;
+    if (ar->ary_array - ar->ary_alloc >= num) {
+       ar->ary_max += num;
+       ar->ary_fill += num;
+       while (num--)
+           *--ar->ary_array = Nullstr;
+    }
+    else {
+       (void)astore(ar,ar->ary_fill+num,(STR*)0);      /* maybe extend array */
+       dstr = ar->ary_array + ar->ary_fill;
+       sstr = dstr - num;
+       for (i = ar->ary_fill; i >= 0; i--) {
+           *dstr-- = *sstr--;
+       }
+       Zero(ar->ary_array, num, STR*);
     }
-    bzero((char*)(ar->ary_array), num * sizeof(STR*));
 }
 
 STR *
@@ -139,44 +237,28 @@ register ARRAY *ar;
 
     if (ar->ary_fill < 0)
        return Nullstr;
-    retval = ar->ary_array[0];
-    bcopy((char*)(ar->ary_array+1),(char*)ar->ary_array,
-      ar->ary_fill * sizeof(STR*));
-    ar->ary_array[ar->ary_fill--] = Nullstr;
+    retval = *ar->ary_array;
+    *(ar->ary_array++) = Nullstr;
+    ar->ary_max--;
+    ar->ary_fill--;
     return retval;
 }
 
-long
+int
 alen(ar)
 register ARRAY *ar;
 {
-    return (long)ar->ary_fill;
+    return ar->ary_fill;
 }
 
-void
-ajoin(ar,delim,str)
+afill(ar, fill)
 register ARRAY *ar;
-char *delim;
-register STR *str;
+int fill;
 {
-    register int i;
-    register int len;
-    register int dlen;
-
-    if (ar->ary_fill < 0) {
-       str_set(str,"");
-       STABSET(str);
-       return;
-    }
-    dlen = strlen(delim);
-    len = ar->ary_fill * dlen;         /* account for delimiters */
-    for (i = ar->ary_fill; i >= 0; i--)
-       len += str_len(ar->ary_array[i]);
-    str_grow(str,len);                 /* preallocate for efficiency */
-    str_sset(str,ar->ary_array[0]);
-    for (i = 1; i <= ar->ary_fill; i++) {
-       str_ncat(str,delim,dlen);
-       str_scat(str,ar->ary_array[i]);
-    }
-    STABSET(str);
+    if (fill < 0)
+       fill = -1;
+    if (fill <= ar->ary_max)
+       ar->ary_fill = fill;
+    else
+       (void)astore(ar,fill,Nullstr);
 }