#include "awk.h"Go to the source code of this file.
Defines | |
| #define | MAX_LEN 0 |
| #define | HASHC |
Typedefs | |
| typedef enum asort_how | ASORT_TYPE |
Enumerations | |
| enum | asort_how { VALUE, INDEX } |
Functions | |
| static NODE *assoc_find | P ((NODE *symbol, NODE *subs, int hash1)) |
| void | array_init () |
| NODE * | get_actual (NODE *symbol, int canfatal) |
| char * | array_vname (register const NODE *symbol) |
| NODE * | concat_exp (register NODE *tree) |
| void | assoc_clear (NODE *symbol) |
| static unsigned long | awk_hash (register const char *s, register size_t len, unsigned long hsize) |
| static NODE * | assoc_find (NODE *symbol, register NODE *subs, int hash1) |
| NODE * | in_array (NODE *symbol, NODE *subs) |
| NODE ** | assoc_lookup (NODE *symbol, NODE *subs, int reference) |
| void | do_delete (NODE *sym, NODE *tree) |
| void | do_delete_loop (NODE *symbol, NODE *tree) |
| static void | grow_table (NODE *symbol) |
| static void | pr_node (NODE *n) |
| NODE * | assoc_dump (NODE *symbol) |
| NODE * | do_adump (NODE *tree) |
| static void | dup_table (NODE *symbol, NODE *newsymb) |
| static NODE * | merge (NODE *left, NODE *right) |
| static NODE * | merge_sort (NODE *left, int size) |
| static void | assoc_from_list (NODE *symbol, NODE *list) |
| static NODE * | assoc_sort_inplace (NODE *symbol, ASORT_TYPE how) |
| static NODE * | asort_actual (NODE *tree, ASORT_TYPE how) |
| NODE * | do_asort (NODE *tree) |
| NODE * | do_asorti (NODE *tree) |
| static unsigned long | gst_hash_string (const char *str, size_t len, unsigned long hsize) |
| static unsigned long | scramble (unsigned long x) |
Variables | |
| static int | AVG_CHAIN_MAX = 2 |
|
|
Value: htmp = (h << 6); \
h = *s++ + htmp + (htmp << 10) - h
Referenced by awk_hash(). |
|
|
Definition at line 134 of file array.c. Referenced by array_vname(). |
|
|
|
|
|
Definition at line 999 of file array.c. 00999 { VALUE, INDEX } ASORT_TYPE;
|
|
|
Definition at line 57 of file array.c. References AVG_CHAIN_MAX, getenv, gst_hash_string(), ISDIGIT, and NULL. Referenced by main(). 00058 { 00059 const char *val; 00060 int newval; 00061 00062 if ((val = getenv("AVG_CHAIN_MAX")) != NULL && ISDIGIT(*val)) { 00063 for (newval = 0; *val && ISDIGIT(*val); val++) 00064 newval = (newval * 10) + *val - '0'; 00065 00066 AVG_CHAIN_MAX = newval; 00067 } 00068 00069 if ((val = getenv("AWK_HASH")) != NULL && strcmp(val, "gst") == 0) 00070 hash = gst_hash_string; 00071 }
|
|
|
Definition at line 137 of file array.c. References _, emalloc, erealloc, len, MAX_LEN, n, Node_array_ref, Node_param_list, Node_var_array, NULL, and stack_ptr. Referenced by assoc_lookup(), do_delete(), interpret(), r_get_lhs(), and r_tree_eval(). 00138 { 00139 if (symbol->type == Node_param_list) 00140 symbol = stack_ptr[symbol->param_cnt]; 00141 00142 if (symbol->type != Node_array_ref || symbol->orig_array->type != Node_var_array) 00143 return symbol->vname; 00144 else { 00145 static char *message = NULL; 00146 static size_t msglen = 0; 00147 char *s; 00148 size_t len; 00149 int n; 00150 const NODE *save_symbol = symbol; 00151 const char *from = _("from %s"); 00152 00153 #if (MAX_LEN <= 0) || !defined(HAVE_SNPRINTF) 00154 /* This is the default branch. */ 00155 00156 /* First, we have to compute the length of the string: */ 00157 len = strlen(symbol->vname) + 2; /* "%s (" */ 00158 n = 0; 00159 do { 00160 symbol = symbol->prev_array; 00161 len += strlen(symbol->vname); 00162 n++; 00163 } while (symbol->type == Node_array_ref); 00164 /* 00165 * Each node contributes by strlen(from) minus the length 00166 * of "%s" in the translation (which is at least 2) 00167 * plus 2 for ", " or ")\0"; this adds up to strlen(from). 00168 */ 00169 len += n * strlen(from); 00170 00171 /* (Re)allocate memory: */ 00172 if (message == NULL) { 00173 emalloc(message, char *, len, "array_vname"); 00174 msglen = len; 00175 } else if (len > msglen) { 00176 erealloc(message, char *, len, "array_vname"); 00177 msglen = len; 00178 } /* else 00179 current buffer can hold new name */ 00180 00181 /* We're ready to print: */ 00182 symbol = save_symbol; 00183 s = message; 00184 /* 00185 * Ancient systems have sprintf() returning char *, not int. 00186 * Thus, `s += sprintf(s, from, name);' is a no-no. 00187 */ 00188 sprintf(s, "%s (", symbol->vname); 00189 s += strlen(s); 00190 for (;;) { 00191 symbol = symbol->prev_array; 00192 sprintf(s, from, symbol->vname); 00193 s += strlen(s); 00194 if (symbol->type != Node_array_ref) 00195 break; 00196 sprintf(s, ", "); 00197 s += strlen(s); 00198 } 00199 sprintf(s, ")"); 00200 00201 #else /* MAX_LEN > 0 */ 00202 00203 /* 00204 * The following check fails only on 00205 * abnormally_long_variable_name. 00206 */ 00207 #define PRINT_CHECK \ 00208 if (n <= 0 || n >= len) \ 00209 return save_symbol->vname; \ 00210 s += n; len -= n 00211 #define PRINT(str) \ 00212 n = snprintf(s, len, str); \ 00213 PRINT_CHECK 00214 #define PRINT_vname(str) \ 00215 n = snprintf(s, len, str, symbol->vname); \ 00216 PRINT_CHECK 00217 00218 if (message == NULL) 00219 emalloc(message, char *, MAX_LEN, "array_vname"); 00220 00221 s = message; 00222 len = MAX_LEN; 00223 00224 /* First, print the vname of the node. */ 00225 PRINT_vname("%s ("); 00226 00227 for (;;) { 00228 symbol = symbol->prev_array; 00229 /* 00230 * When we don't have enough space and this is not 00231 * the last node, shorten the list. 00232 */ 00233 if (len < 40 && symbol->type == Node_array_ref) { 00234 PRINT("..., "); 00235 symbol = symbol->orig_array; 00236 } 00237 PRINT_vname(from); 00238 if (symbol->type != Node_array_ref) 00239 break; 00240 PRINT(", "); 00241 } 00242 PRINT(")"); 00243 00244 #undef PRINT_CHECK 00245 #undef PRINT 00246 #undef PRINT_vname 00247 #endif /* MAX_LEN <= 0 */ 00248 00249 return message; 00250 } 00251 }
|
|
||||||||||||
|
Definition at line 1099 of file array.c. References assoc_clear(), assoc_sort_inplace(), dup_table(), get_array, and NULL. Referenced by do_asort(), and do_asorti(). 01100 { 01101 NODE *array = get_array(tree->lnode); 01102 01103 if (tree->rnode != NULL) { /* 2nd optional arg */ 01104 NODE *dest = get_array(tree->rnode->lnode); 01105 01106 assoc_clear(dest); 01107 dup_table(array, dest); 01108 array = dest; 01109 } 01110 01111 return assoc_sort_inplace(array, how); 01112 }
|
|
|
Definition at line 303 of file array.c. References array_size, ARRAYMAXED, exp_node::flags, free(), i, NULL, and unref(). Referenced by asort_actual(), do_delete(), do_delete_loop(), do_match(), do_mkarray(), do_split(), do_stat(), pop_fcall(), and release_all_vars(). 00304 { 00305 int i; 00306 NODE *bucket, *next; 00307 00308 if (symbol->var_array == NULL) 00309 return; 00310 for (i = 0; i < symbol->array_size; i++) { 00311 for (bucket = symbol->var_array[i]; bucket != NULL; bucket = next) { 00312 next = bucket->ahnext; 00313 unref(bucket->ahvalue); 00314 unref(bucket); /* unref() will free the ahname_str */ 00315 } 00316 symbol->var_array[i] = NULL; 00317 } 00318 free(symbol->var_array); 00319 symbol->var_array = NULL; 00320 symbol->array_size = symbol->table_size = 0; 00321 symbol->flags &= ~ARRAYMAXED; 00322 }
|
|
|
Definition at line 763 of file array.c. References _, array_size, AWKNUM, i, NULL, pr_node(), and tmp_number. Referenced by do_adump(). 00764 { 00765 int i; 00766 NODE *bucket; 00767 00768 if (symbol->var_array == NULL) { 00769 printf(_("%s: empty (null)\n"), symbol->vname); 00770 return tmp_number((AWKNUM) 0); 00771 } 00772 00773 if (symbol->table_size == 0) { 00774 printf(_("%s: empty (zero)\n"), symbol->vname); 00775 return tmp_number((AWKNUM) 0); 00776 } 00777 00778 printf(_("%s: table_size = %d, array_size = %d\n"), symbol->vname, 00779 (int) symbol->table_size, (int) symbol->array_size); 00780 00781 for (i = 0; i < symbol->array_size; i++) { 00782 for (bucket = symbol->var_array[i]; bucket != NULL; 00783 bucket = bucket->ahnext) { 00784 printf("%s: I: [len %d <%.*s>] V: [", 00785 symbol->vname, 00786 (int) bucket->ahname_len, 00787 (int) bucket->ahname_len, 00788 bucket->ahname_str); 00789 pr_node(bucket->ahvalue); 00790 printf("]\n"); 00791 } 00792 } 00793 00794 return tmp_number((AWKNUM) 0); 00795 }
|
|
||||||||||||||||
|
Definition at line 414 of file array.c. Referenced by assoc_lookup(), and in_array(). 00415 { 00416 register NODE *bucket; 00417 const char *s1_str; 00418 size_t s1_len; 00419 NODE *s2; 00420 00421 for (bucket = symbol->var_array[hash1]; bucket != NULL; 00422 bucket = bucket->ahnext) { 00423 /* 00424 * This used to use cmp_nodes() here. That's wrong. 00425 * Array indexes are strings; compare as such, always! 00426 */ 00427 s1_str = bucket->ahname_str; 00428 s1_len = bucket->ahname_len; 00429 s2 = subs; 00430 00431 if (s1_len == s2->stlen) { 00432 if (s1_len == 0 /* "" is a valid index */ 00433 || STREQN(s1_str, s2->stptr, s1_len)) 00434 return bucket; 00435 } 00436 } 00437 return NULL; 00438 }
|
|
||||||||||||
|
Definition at line 965 of file array.c. References emalloc, i, and NULL. Referenced by assoc_sort_inplace(). 00966 { 00967 NODE *next; 00968 unsigned long i = 0; 00969 register int hash1; 00970 char buf[100]; 00971 00972 for (; list != NULL; list = next) { 00973 next = list->ahnext; 00974 00975 /* make an int out of i++ */ 00976 i++; 00977 sprintf(buf, "%lu", i); 00978 assert(list->ahname_str == NULL); 00979 assert(list->ahname_ref == 1); 00980 emalloc(list->ahname_str, char *, strlen(buf) + 2, "assoc_from_list"); 00981 list->ahname_len = strlen(buf); 00982 strcpy(list->ahname_str, buf); 00983 00984 /* find the bucket where it belongs */ 00985 hash1 = hash(list->ahname_str, list->ahname_len, 00986 symbol->array_size); 00987 00988 /* link the node into the chain at that bucket */ 00989 list->ahnext = symbol->var_array[hash1]; 00990 symbol->var_array[hash1] = list; 00991 } 00992 }
|
|
||||||||||||||||
|
Definition at line 479 of file array.c. References _, array_vname(), ARRAYMAXED, assoc_find(), AVG_CHAIN_MAX, do_lint, emalloc, exp_node::flags, force_string, free_temp, getnode, grow_table(), lintwarn, MALLOC, memcpy, Nnull_string, Node_ahash, Node_var_array, NULL, and exp_node::type. Referenced by do_fork(), do_match(), do_mkarray(), do_stat(), init_args(), load_environ(), load_procinfo(), nextfile(), r_get_lhs(), set_element(), and update_PROCINFO(). 00480 { 00481 register int hash1; 00482 register NODE *bucket; 00483 00484 assert(symbol->type == Node_var_array); 00485 00486 (void) force_string(subs); 00487 00488 if (symbol->var_array == NULL) { 00489 symbol->array_size = symbol->table_size = 0; /* sanity */ 00490 symbol->flags &= ~ARRAYMAXED; 00491 grow_table(symbol); 00492 hash1 = hash(subs->stptr, subs->stlen, 00493 (unsigned long) symbol->array_size); 00494 } else { 00495 hash1 = hash(subs->stptr, subs->stlen, 00496 (unsigned long) symbol->array_size); 00497 bucket = assoc_find(symbol, subs, hash1); 00498 if (bucket != NULL) { 00499 free_temp(subs); 00500 return &(bucket->ahvalue); 00501 } 00502 } 00503 00504 if (do_lint && reference) { 00505 subs->stptr[subs->stlen] = '\0'; 00506 lintwarn(_("reference to uninitialized element `%s[\"%s\"]'"), 00507 array_vname(symbol), subs->stptr); 00508 } 00509 00510 /* It's not there, install it. */ 00511 if (do_lint && subs->stlen == 0) 00512 lintwarn(_("subscript of array `%s' is null string"), 00513 array_vname(symbol)); 00514 00515 /* first see if we would need to grow the array, before installing */ 00516 symbol->table_size++; 00517 if ((symbol->flags & ARRAYMAXED) == 0 00518 && (symbol->table_size / symbol->array_size) > AVG_CHAIN_MAX) { 00519 grow_table(symbol); 00520 /* have to recompute hash value for new size */ 00521 hash1 = hash(subs->stptr, subs->stlen, 00522 (unsigned long) symbol->array_size); 00523 } 00524 00525 getnode(bucket); 00526 bucket->type = Node_ahash; 00527 00528 /* 00529 * Freeze this string value --- it must never 00530 * change, no matter what happens to the value 00531 * that created it or to CONVFMT, etc. 00532 * 00533 * One day: Use an atom table to track array indices, 00534 * and avoid the extra memory overhead. 00535 */ 00536 bucket->flags |= MALLOC; 00537 bucket->ahname_ref = 1; 00538 emalloc(bucket->ahname_str, char *, subs->stlen + 2, "assoc_lookup"); 00539 bucket->ahname_len = subs->stlen; 00540 00541 memcpy(bucket->ahname_str, subs->stptr, subs->stlen); 00542 bucket->ahname_str[bucket->ahname_len] = '\0'; 00543 00544 free_temp(subs); 00545 00546 bucket->ahvalue = Nnull_string; 00547 bucket->ahnext = symbol->var_array[hash1]; 00548 symbol->var_array[hash1] = bucket; 00549 return &(bucket->ahvalue); 00550 }
|
|
||||||||||||
|
Definition at line 1002 of file array.c. References ALREADY_MALLOCED, array_size, assoc_from_list(), AWKNUM, exp_node::flags, free(), getnode, i, make_str_node(), make_string, MALLOC, merge_sort(), NULL, tmp_number, unref(), and VALUE. Referenced by asort_actual(). 01003 { 01004 int i, num; 01005 NODE *bucket, *next, *list; 01006 01007 if (symbol->var_array == NULL 01008 || symbol->array_size <= 0 01009 || symbol->table_size <= 0) 01010 return tmp_number((AWKNUM) 0); 01011 01012 /* build a linked list out of all the entries in the table */ 01013 if (how == VALUE) { 01014 list = NULL; 01015 num = 0; 01016 for (i = 0; i < symbol->array_size; i++) { 01017 for (bucket = symbol->var_array[i]; bucket != NULL; bucket = next) { 01018 next = bucket->ahnext; 01019 if (bucket->ahname_ref == 1) { 01020 free(bucket->ahname_str); 01021 bucket->ahname_str = NULL; 01022 bucket->ahname_len = 0; 01023 } else { 01024 NODE *r; 01025 01026 getnode(r); 01027 *r = *bucket; 01028 unref(bucket); 01029 bucket = r; 01030 bucket->flags |= MALLOC; 01031 bucket->ahname_ref = 1; 01032 bucket->ahname_str = NULL; 01033 bucket->ahname_len = 0; 01034 } 01035 bucket->ahnext = list; 01036 list = bucket; 01037 num++; 01038 } 01039 symbol->var_array[i] = NULL; 01040 } 01041 } else { /* how == INDEX */ 01042 list = NULL; 01043 num = 0; 01044 for (i = 0; i < symbol->array_size; i++) { 01045 for (bucket = symbol->var_array[i]; bucket != NULL; bucket = next) { 01046 next = bucket->ahnext; 01047 01048 /* toss old value */ 01049 unref(bucket->ahvalue); 01050 01051 /* move index into value */ 01052 if (bucket->ahname_ref == 1) { 01053 bucket->ahvalue = make_str_node(bucket->ahname_str, 01054 bucket->ahname_len, ALREADY_MALLOCED); 01055 bucket->ahname_str = NULL; 01056 bucket->ahname_len = 0; 01057 } else { 01058 NODE *r; 01059 01060 bucket->ahvalue = make_string(bucket->ahname_str, bucket->ahname_len); 01061 getnode(r); 01062 *r = *bucket; 01063 unref(bucket); 01064 bucket = r; 01065 bucket->flags |= MALLOC; 01066 bucket->ahname_ref = 1; 01067 bucket->ahname_str = NULL; 01068 bucket->ahname_len = 0; 01069 } 01070 01071 bucket->ahnext = list; 01072 list = bucket; 01073 num++; 01074 } 01075 symbol->var_array[i] = NULL; 01076 } 01077 } 01078 01079 /* 01080 * Sort the linked list of NODEs. 01081 * (The especially nice thing about using a merge sort here is that 01082 * we require absolutely no additional storage. This is handy if the 01083 * array has grown to be very large.) 01084 */ 01085 list = merge_sort(list, num); 01086 01087 /* 01088 * now repopulate the original array, using increasing 01089 * integers as the key 01090 */ 01091 assoc_from_list(symbol, list); 01092 01093 return tmp_number((AWKNUM) num); 01094 }
|
|
||||||||||||||||
|
Definition at line 327 of file array.c. References HASHC. 00328 { 00329 register unsigned long h = 0; 00330 00331 /* 00332 * This is INCREDIBLY ugly, but fast. We break the string up into 00333 * 8 byte units. On the first time through the loop we get the 00334 * "leftover bytes" (strlen % 8). On every other iteration, we 00335 * perform 8 HASHC's so we handle all 8 bytes. Essentially, this 00336 * saves us 7 cmp & branch instructions. If this routine is 00337 * heavily used enough, it's worth the ugly coding. 00338 * 00339 * OZ's original sdbm hash, copied from Margo Seltzers db package. 00340 */ 00341 00342 /* 00343 * Even more speed: 00344 * #define HASHC h = *s++ + 65599 * h 00345 * Because 65599 = pow(2, 6) + pow(2, 16) - 1 we multiply by shifts 00346 */ 00347 #define HASHC htmp = (h << 6); \ 00348 h = *s++ + htmp + (htmp << 10) - h 00349 00350 unsigned long htmp; 00351 00352 h = 0; 00353 00354 #if defined(VAXC) 00355 /* 00356 * This was an implementation of "Duff's Device", but it has been 00357 * redone, separating the switch for extra iterations from the 00358 * loop. This is necessary because the DEC VAX-C compiler is 00359 * STOOPID. 00360 */ 00361 switch (len & (8 - 1)) { 00362 case 7: HASHC; 00363 case 6: HASHC; 00364 case 5: HASHC; 00365 case 4: HASHC; 00366 case 3: HASHC; 00367 case 2: HASHC; 00368 case 1: HASHC; 00369 default: break; 00370 } 00371 00372 if (len > (8 - 1)) { 00373 register size_t loop = len >> 3; 00374 do { 00375 HASHC; 00376 HASHC; 00377 HASHC; 00378 HASHC; 00379 HASHC; 00380 HASHC; 00381 HASHC; 00382 HASHC; 00383 } while (--loop); 00384 } 00385 #else /* ! VAXC */ 00386 /* "Duff's Device" for those who can handle it */ 00387 if (len > 0) { 00388 register size_t loop = (len + 8 - 1) >> 3; 00389 00390 switch (len & (8 - 1)) { 00391 case 0: 00392 do { /* All fall throughs */ 00393 HASHC; 00394 case 7: HASHC; 00395 case 6: HASHC; 00396 case 5: HASHC; 00397 case 4: HASHC; 00398 case 3: HASHC; 00399 case 2: HASHC; 00400 case 1: HASHC; 00401 } while (--loop); 00402 } 00403 } 00404 #endif /* ! VAXC */ 00405 00406 if (h >= hsize) 00407 h %= hsize; 00408 return h; 00409 }
|
|
|
Definition at line 257 of file array.c. References ALREADY_MALLOCED, emalloc, erealloc, exp_node::flags, force_string, free_temp, len, make_str_node(), memcpy, Node_expression_list, NULL, SUBSEP_node, TEMP, and tree_eval. Referenced by do_delete(), in_array(), and r_get_lhs(). 00258 { 00259 register NODE *r; 00260 char *str; 00261 char *s; 00262 size_t len; 00263 int offset; 00264 size_t subseplen; 00265 const char *subsep; 00266 00267 if (tree->type != Node_expression_list) 00268 return force_string(tree_eval(tree)); 00269 r = force_string(tree_eval(tree->lnode)); 00270 if (tree->rnode == NULL) 00271 return r; 00272 subseplen = SUBSEP_node->var_value->stlen; 00273 subsep = SUBSEP_node->var_value->stptr; 00274 len = r->stlen + subseplen + 2; 00275 emalloc(str, char *, len, "concat_exp"); 00276 memcpy(str, r->stptr, r->stlen+1); 00277 s = str + r->stlen; 00278 free_temp(r); 00279 for (tree = tree->rnode; tree != NULL; tree = tree->rnode) { 00280 if (subseplen == 1) 00281 *s++ = *subsep; 00282 else { 00283 memcpy(s, subsep, subseplen+1); 00284 s += subseplen; 00285 } 00286 r = force_string(tree_eval(tree->lnode)); 00287 len += r->stlen + subseplen; 00288 offset = s - str; 00289 erealloc(str, char *, len, "concat_exp"); 00290 s = str + offset; 00291 memcpy(s, r->stptr, r->stlen+1); 00292 s += r->stlen; 00293 free_temp(r); 00294 } 00295 r = make_str_node(str, s - str, ALREADY_MALLOCED); 00296 r->flags |= TEMP; 00297 return r; 00298 }
|
|
|
Definition at line 800 of file array.c. References _, assoc_dump(), Node_array_ref, Node_param_list, stack_ptr, and exp_node::type. 00801 { 00802 NODE *r, *a; 00803 00804 a = tree->lnode; 00805 00806 if (a->type == Node_param_list) { 00807 printf(_("%s: is parameter\n"), a->vname); 00808 a = stack_ptr[a->param_cnt]; 00809 } 00810 00811 if (a->type == Node_array_ref) { 00812 printf(_("%s: array_ref to %s\n"), a->vname, 00813 a->orig_array->vname); 00814 a = a->orig_array; 00815 } 00816 00817 r = assoc_dump(a); 00818 00819 return r; 00820 }
|
|
|
Definition at line 1117 of file array.c. References asort_actual(), and VALUE. 01118 { 01119 return asort_actual(tree, VALUE); 01120 }
|
|
|
Definition at line 1125 of file array.c. References asort_actual(), and INDEX. 01126 { 01127 return asort_actual(tree, INDEX); 01128 }
|
|
||||||||||||
|
Definition at line 560 of file array.c. References _, array_vname(), ARRAYMAXED, assoc_clear(), concat_exp(), do_lint, exp_node::flags, free(), free_temp, get_array, lintwarn, memset(), NULL, STREQN, and unref(). Referenced by interpret(). 00561 { 00562 register int hash1; 00563 register NODE *bucket, *last; 00564 NODE *subs; 00565 register NODE *symbol = get_array(sym); 00566 00567 if (tree == NULL) { /* delete array */ 00568 assoc_clear(symbol); 00569 return; 00570 } 00571 00572 last = NULL; /* shut up gcc -Wall */ 00573 hash1 = 0; /* ditto */ 00574 00575 /* 00576 * Always evaluate subscript, it could have side effects. 00577 */ 00578 subs = concat_exp(tree); /* concat_exp returns string node */ 00579 00580 if (symbol->var_array != NULL) { 00581 hash1 = hash(subs->stptr, subs->stlen, 00582 (unsigned long) symbol->array_size); 00583 last = NULL; 00584 for (bucket = symbol->var_array[hash1]; bucket != NULL; 00585 last = bucket, bucket = bucket->ahnext) { 00586 /* 00587 * This used to use cmp_nodes() here. That's wrong. 00588 * Array indexes are strings; compare as such, always! 00589 */ 00590 const char *s1_str; 00591 size_t s1_len; 00592 NODE *s2; 00593 00594 s1_str = bucket->ahname_str; 00595 s1_len = bucket->ahname_len; 00596 s2 = subs; 00597 00598 if (s1_len == s2->stlen) { 00599 if (s1_len == 0 /* "" is a valid index */ 00600 || STREQN(s1_str, s2->stptr, s1_len)) 00601 break; 00602 } 00603 } 00604 } else 00605 bucket = NULL; /* The array is empty. */ 00606 00607 if (bucket == NULL) { 00608 if (do_lint) 00609 lintwarn(_("delete: index `%s' not in array `%s'"), 00610 subs->stptr, array_vname(sym)); 00611 free_temp(subs); 00612 return; 00613 } 00614 00615 free_temp(subs); 00616 00617 if (last != NULL) 00618 last->ahnext = bucket->ahnext; 00619 else 00620 symbol->var_array[hash1] = bucket->ahnext; 00621 unref(bucket->ahvalue); 00622 unref(bucket); /* unref() will free the ahname_str */ 00623 symbol->table_size--; 00624 if (symbol->table_size <= 0) { 00625 memset(symbol->var_array, '\0', 00626 sizeof(NODE *) * symbol->array_size); 00627 symbol->table_size = symbol->array_size = 0; 00628 symbol->flags &= ~ARRAYMAXED; 00629 free((char *) symbol->var_array); 00630 symbol->var_array = NULL; 00631 } 00632 }
|
|
||||||||||||
|
Definition at line 643 of file array.c. References array_size, assoc_clear(), FALSE, get_array, get_lhs, i, make_string, NULL, and unref(). Referenced by interpret(). 00644 { 00645 size_t i; 00646 NODE **lhs; 00647 Func_ptr after_assign = NULL; 00648 00649 symbol = get_array(symbol); 00650 00651 if (symbol->var_array == NULL) 00652 return; 00653 00654 /* get first index value */ 00655 for (i = 0; i < symbol->array_size; i++) { 00656 if (symbol->var_array[i] != NULL) { 00657 lhs = get_lhs(tree->lnode, & after_assign, FALSE); 00658 unref(*lhs); 00659 *lhs = make_string(symbol->var_array[i]->ahname_str, 00660 symbol->var_array[i]->ahname_len); 00661 if (after_assign) 00662 (*after_assign)(); 00663 break; 00664 } 00665 } 00666 00667 /* blast the array in one shot */ 00668 assoc_clear(symbol); 00669 }
|
|
||||||||||||
|
Definition at line 831 of file array.c. References dupnode, emalloc, exp_node::flags, getnode, i, MALLOC, memcpy, memset(), Node_ahash, NULL, and exp_node::type. Referenced by asort_actual(). 00832 { 00833 NODE **old, **new, *chain, *bucket; 00834 int i; 00835 unsigned long cursize; 00836 00837 /* find the current hash size */ 00838 cursize = symbol->array_size; 00839 00840 new = NULL; 00841 00842 /* input is a brand new hash table, so there's nothing to copy */ 00843 if (symbol->var_array == NULL) 00844 newsymb->table_size = 0; 00845 else { 00846 /* old hash table there, dupnode stuff into a new table */ 00847 00848 /* allocate new table */ 00849 emalloc(new, NODE **, cursize * sizeof(NODE *), "dup_table"); 00850 memset(new, '\0', cursize * sizeof(NODE *)); 00851 00852 /* do the copying/dupnode'ing */ 00853 old = symbol->var_array; 00854 for (i = 0; i < cursize; i++) { 00855 if (old[i] != NULL) { 00856 for (chain = old[i]; chain != NULL; 00857 chain = chain->ahnext) { 00858 /* get a node for the linked list */ 00859 getnode(bucket); 00860 bucket->type = Node_ahash; 00861 bucket->flags |= MALLOC; 00862 bucket->ahname_ref = 1; 00863 00864 /* 00865 * copy the corresponding name and 00866 * value from the original input list 00867 */ 00868 emalloc(bucket->ahname_str, char *, chain->ahname_len + 2, "dup_table"); 00869 bucket->ahname_len = chain->ahname_len; 00870 00871 memcpy(bucket->ahname_str, chain->ahname_str, chain->ahname_len); 00872 bucket->ahname_str[bucket->ahname_len] = '\0'; 00873 00874 bucket->ahvalue = dupnode(chain->ahvalue); 00875 00876 /* 00877 * put the node on the corresponding 00878 * linked list in the new table 00879 */ 00880 bucket->ahnext = new[i]; 00881 new[i] = bucket; 00882 } 00883 } 00884 } 00885 newsymb->table_size = symbol->table_size; 00886 } 00887 00888 newsymb->var_array = new; 00889 newsymb->array_size = cursize; 00890 }
|
|
||||||||||||
|
Definition at line 81 of file array.c. References _, cant_happen, fatal, exp_node::flags, FUNC, Node_array_ref, Node_param_list, Node_var_array, Node_var_new, NULL, stack_ptr, and exp_node::type. 00082 { 00083 int isparam = (symbol->type == Node_param_list 00084 && (symbol->flags & FUNC) == 0); 00085 NODE *save_symbol = symbol; 00086 00087 if (isparam) { 00088 save_symbol = symbol = stack_ptr[symbol->param_cnt]; 00089 if (symbol->type == Node_array_ref) 00090 symbol = symbol->orig_array; 00091 } 00092 00093 switch (symbol->type) { 00094 case Node_var_new: 00095 symbol->type = Node_var_array; 00096 symbol->var_array = NULL; 00097 /* fall through */ 00098 case Node_var_array: 00099 break; 00100 00101 case Node_array_ref: 00102 case Node_param_list: 00103 if (canfatal) 00104 cant_happen(); 00105 /* else 00106 fall through */ 00107 00108 default: 00109 /* notably Node_var but catches also e.g. FS[1] = "x" */ 00110 if (canfatal) 00111 fatal(isparam ? 00112 _("attempt to use scalar parameter `%s' as an array") : 00113 _("attempt to use scalar `%s' as array"), 00114 save_symbol->vname); 00115 else 00116 break; 00117 } 00118 00119 return symbol; 00120 }
|
|
|
Definition at line 674 of file array.c. References ARRAYMAXED, emalloc, exp_node::flags, free(), i, memset(), and NULL. Referenced by assoc_lookup(). 00675 { 00676 NODE **old, **new, *chain, *next; 00677 int i, j; 00678 unsigned long hash1; 00679 unsigned long oldsize, newsize; 00680 /* 00681 * This is an array of primes. We grow the table by an order of 00682 * magnitude each time (not just doubling) so that growing is a 00683 * rare operation. We expect, on average, that it won't happen 00684 * more than twice. The final size is also chosen to be small 00685 * enough so that MS-DOG mallocs can handle it. When things are 00686 * very large (> 8K), we just double more or less, instead of 00687 * just jumping from 8K to 64K. 00688 */ 00689 static const long sizes[] = { 13, 127, 1021, 8191, 16381, 32749, 65497, 00690 #if ! defined(MSDOS) && ! defined(OS2) && ! defined(atarist) 00691 131101, 262147, 524309, 1048583, 2097169, 00692 4194319, 8388617, 16777259, 33554467, 00693 67108879, 134217757, 268435459, 536870923, 00694 1073741827 00695 #endif 00696 }; 00697 00698 /* find next biggest hash size */ 00699 newsize = oldsize = symbol->array_size; 00700 for (i = 0, j = sizeof(sizes)/sizeof(sizes[0]); i < j; i++) { 00701 if (oldsize < sizes[i]) { 00702 newsize = sizes[i]; 00703 break; 00704 } 00705 } 00706 00707 if (newsize == oldsize) { /* table already at max (!) */ 00708 symbol->flags |= |