]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - array.c
fix for SIGINT in sourced script
[thirdparty/bash.git] / array.c
diff --git a/array.c b/array.c
index a8c7766e1e81c4d1006e5f5830a75f7d3e059c1d..6a6db77637b2321b2d02279893ca3508537f5f1e 100644 (file)
--- a/array.c
+++ b/array.c
 
 static char *array_to_string_internal __P((ARRAY_ELEMENT *, ARRAY_ELEMENT *, char *, int));
 
+/* lastref should be moved into the array structure so each array can be
+   optimized separately */
+
+static ARRAY *lastarray = 0;
+static ARRAY_ELEMENT *lastref = 0;
+
+#define IS_LASTREF(a)  (lastarray && (a) == lastarray)
+
+#define LASTREF_START(a, i) \
+       (IS_LASTREF(a) && i >= element_index(lastref)) ? lastref \
+                                                      : element_forw(a->head)
+
+#define INVALIDATE_LASTREF(a) \
+do { \
+       if ((a) == lastarray) { \
+               lastarray = 0; \
+               lastref = 0; \
+       } \
+} while (0)
+
+#define SET_LASTREF(a, e) \
+do { \
+       lastarray = (a); \
+       lastref = (e); \
+} while (0)
+
+#define UNSET_LASTREF() \
+do { \
+       lastarray = 0; \
+       lastref = 0; \
+} while (0)
+
 ARRAY *
 array_create()
 {
@@ -87,6 +119,7 @@ ARRAY        *a;
        a->head->next = a->head->prev = a->head;
        a->max_index = -1;
        a->num_elements = 0;
+       INVALIDATE_LASTREF(a);
 }
 
 void
@@ -185,6 +218,7 @@ int n, flags;
        if (a == 0 || array_empty(a) || n <= 0)
                return ((ARRAY_ELEMENT *)NULL);
 
+       INVALIDATE_LASTREF(a);
        for (i = 0, ret = ae = element_forw(a->head); ae != a->head && i < n; ae = element_forw(ae), i++)
                ;
        if (ae == a->head) {
@@ -214,7 +248,7 @@ int n, flags;
                element_index(ae) -= n; /* renumber retained indices */
 
        a->num_elements -= n;           /* modify bookkeeping information */
-       a->max_index -= n;
+       a->max_index = element_index(a->head->prev);
 
        if (flags & AS_DISPOSE) {
                for (ae = ret; ae; ) {
@@ -251,8 +285,10 @@ char       *s;
                new = array_create_element(0, s);
                ADD_BEFORE(ae, new);
                a->num_elements++;
-               if (array_num_elements(a) == 1)         /* array was empty */
+               if (array_num_elements(a) == 1) {       /* array was empty */
+                       a->max_index = 0;
                        return 1;
+               }
        }
 
        /*
@@ -263,6 +299,7 @@ char        *s;
 
        a->max_index = element_index(a->head->prev);
 
+       INVALIDATE_LASTREF(a);
        return (a->num_elements);
 }
 
@@ -580,7 +617,7 @@ ARRAY       *a;
 arrayind_t     i;
 char   *v;
 {
-       register ARRAY_ELEMENT *new, *ae;
+       register ARRAY_ELEMENT *new, *ae, *start;
 
        if (a == 0)
                return(-1);
@@ -594,12 +631,20 @@ char      *v;
                ADD_BEFORE(a->head, new);
                a->max_index = i;
                a->num_elements++;
+               SET_LASTREF(a, new);
                return(0);
        }
+#if OPTIMIZE_SEQUENTIAL_ARRAY_ASSIGNMENT
        /*
-        * Otherwise we search for the spot to insert it.
+        * Otherwise we search for the spot to insert it.  The lastref
+        * handle optimizes the case of sequential or almost-sequential
+        * assignments that are not at the end of the array.
         */
-       for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) {
+       start = LASTREF_START(a, i);
+#else
+       start = element_forw(ae->head);
+#endif
+       for (ae = start; ae != a->head; ae = element_forw(ae)) {
                if (element_index(ae) == i) {
                        /*
                         * Replacing an existing element.
@@ -607,13 +652,17 @@ char      *v;
                        array_dispose_element(new);
                        free(element_value(ae));
                        ae->value = v ? savestring(v) : (char *)NULL;
+                       SET_LASTREF(a, ae);
                        return(0);
                } else if (element_index(ae) > i) {
                        ADD_BEFORE(ae, new);
                        a->num_elements++;
+                       SET_LASTREF(a, new);
                        return(0);
                }
        }
+       array_dispose_element(new);
+       INVALIDATE_LASTREF(a);
        return (-1);            /* problem */
 }
 
@@ -626,17 +675,28 @@ array_remove(a, i)
 ARRAY  *a;
 arrayind_t     i;
 {
-       register ARRAY_ELEMENT *ae;
+       register ARRAY_ELEMENT *ae, *start;
 
        if (a == 0 || array_empty(a))
                return((ARRAY_ELEMENT *) NULL);
-       for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae))
+       start = LASTREF_START(a, i);
+       for (ae = start; ae != a->head; ae = element_forw(ae))
                if (element_index(ae) == i) {
                        ae->next->prev = ae->prev;
                        ae->prev->next = ae->next;
                        a->num_elements--;
                        if (i == array_max_index(a))
                                a->max_index = element_index(ae->prev);
+#if 0
+                       INVALIDATE_LASTREF(a);
+#else
+                       if (ae->next != a->head)
+                               SET_LASTREF(a, ae->next);
+                       else if (ae->prev != a->head)
+                               SET_LASTREF(a, ae->prev);
+                       else
+                               INVALIDATE_LASTREF(a);
+#endif
                        return(ae);
                }
        return((ARRAY_ELEMENT *) NULL);
@@ -650,13 +710,19 @@ array_reference(a, i)
 ARRAY  *a;
 arrayind_t     i;
 {
-       register ARRAY_ELEMENT *ae;
+       register ARRAY_ELEMENT *ae, *start;
 
        if (a == 0 || array_empty(a))
                return((char *) NULL);
-       for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae))
-               if (element_index(ae) == i)
+       if (i > array_max_index(a))
+               return((char *)NULL);   /* Keep roving pointer into array to optimize sequential access */
+       start = LASTREF_START(a, i);
+       for (ae = start; ae != a->head; ae = element_forw(ae))
+               if (element_index(ae) == i) {
+                       SET_LASTREF(a, ae);
                        return(element_value(ae));
+               }
+       UNSET_LASTREF();                /* XXX SET_LASTREF(a, start) ? */
        return((char *) NULL);
 }
 
@@ -771,7 +837,7 @@ int quoted;
                                                rsize, rsize);
                        strcpy(result + rlen, t);
                        rlen += reg;
-                       if (quoted && t)
+                       if (quoted)
                                free(t);
                        /*
                         * Add a separator only after non-null elements.
@@ -806,7 +872,10 @@ int        quoted;
 
        for (ae = element_forw(a->head); ae != a->head; ae = element_forw(ae)) {
                is = inttostr (element_index(ae), indstr, sizeof(indstr));
-               valstr = element_value (ae) ? sh_double_quote (element_value(ae))
+               valstr = element_value (ae) ?
+                               (ansic_shouldquote (element_value (ae)) ?
+                                  ansic_quote (element_value(ae), 0, (int *)0) :
+                                  sh_double_quote (element_value (ae)))
                                            : (char *)NULL;
                elen = STRLEN (is) + 8 + STRLEN (valstr);
                RESIZE_MALLOCED_BUFFER (result, rlen, (elen + 1), rsize, rsize);