1 /*------------------------------------------------------------*
2 | array.c |
3 | copyright 1999, Andrew Sumner (andrewsumner@yahoo.com) |
4 | |
5 | This is a source file for the awka package, a translator |
6 | of the AWK programming language to ANSI C. |
7 | |
8 | This library is free software; you can redistribute it |
9 | and/or modify it under the terms of the GNU General |
10 | Public License (GPL). |
11 | |
12 | This library is distributed in the hope that it will be |
13 | useful, but WITHOUT ANY WARRANTY; without even the implied |
14 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
15 | PURPOSE. |
16 *------------------------------------------------------------*/
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <limits.h>
23
24 #define _ARRAY_C
25 char _awka_setdol0_len = 0;
26 char _awka_setdoln = 0;
27 char _dol0_only = 0;
28 char _rebuild0 = 0, _rebuildn = 0, _rebuild0_now = 0;
29 char fs_or_fw = 0;
30
31 #define _IN_LIBRARY
32 #include "libawka.h"
33 #include "array_priv.h"
34 #include "number.h"
35 #include "garbage.h"
36
37 char _a_space[256], *nullstr = "";
38 int _awka_dol0_len = 0;
39 extern int _split_max;
40
41 int *fw_loc, fw_allc = 0, fw_used = 0;
42 int *sw_loc, sw_allc = 0, sw_used = 0;
43
44 static a_HSHNode * _awka_hshfindint( _a_HSHarray *, unsigned int, char, char );
45
46 static INLINE int
_awka_isanint(char * s)47 _awka_isanint( char *s )
48 {
49 register char *p = s;
50
51 if (!*p || (*p == '0' && *(p+1) != '\0')) return FALSE;
52 while (*p)
53 if (!isdigit(*p++)) return FALSE;
54 return TRUE;
55 }
56
57
58 #define mix(a, b, c) \
59 { \
60 a -= b; a -= c; a ^= (c>>13); \
61 b -= c; b -= a; b ^= (a<<8); \
62 c -= a; c -= b; c ^= (b>>13); \
63 a -= b; a -= c; a ^= (c>>12); \
64 b -= c; b -= a; b ^= (a<<16); \
65 c -= a; c -= b; c ^= (b>>5); \
66 a -= b; a -= c; a ^= (c>>3); \
67 b -= c; b -= a; b ^= (a<<10); \
68 c -= a; c -= b; c ^= (b>>15); \
69 }
70
71 /*
72 * _awka_hashstr
73 * calculates a reasonably unique int value from a string.
74 * This is derived from public-domain code by Bob Jenkins.
75 */
76 unsigned int
_awka_hashstr(char * str,register int len)77 _awka_hashstr( char *str, register int len )
78 {
79 typedef unsigned long int ub4;
80 typedef unsigned char ub1;
81 register char *p = str;
82 register ub4 a,b,c,length=len;
83 static ub4 last_hash = 10949823;
84
85 if (len == 1) return *str;
86
87 if (len < 8)
88 {
89 c = *p;
90 for (a=1; a<len && *p; a++)
91 c += (c << 4) + *p++;
92 return (unsigned int) c;
93 }
94
95 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
96 c = (ub4) 9325281762; /* the previous hash value */
97
98 /*---------------------------------------- handle most of the key */
99 while (len >= 12)
100 {
101 a += (str[0] +((ub4)str[1]<<8) +((ub4)str[2]<<16) +((ub4)str[3]<<24));
102 b += (str[4] +((ub4)str[5]<<8) +((ub4)str[6]<<16) +((ub4)str[7]<<24));
103 c += (str[8] +((ub4)str[9]<<8) +((ub4)str[10]<<16)+((ub4)str[11]<<24));
104 mix(a,b,c);
105 str += 12; len -= 12;
106 }
107
108 /*------------------------------------- handle the last 11 bytes */
109 c += length;
110 switch(len) /* all the case statements fall through */
111 {
112 case 11: c+=((ub4)str[10]<<24);
113 case 10: c+=((ub4)str[9]<<16);
114 case 9 : c+=((ub4)str[8]<<8);
115 /* the first byte of c is reserved for the length */
116 case 8 : b+=((ub4)str[7]<<24);
117 case 7 : b+=((ub4)str[6]<<16);
118 case 6 : b+=((ub4)str[5]<<8);
119 case 5 : b+=str[4];
120 case 4 : a+=((ub4)str[3]<<24);
121 case 3 : a+=((ub4)str[2]<<16);
122 case 2 : a+=((ub4)str[1]<<8);
123 case 1 : a+=str[0];
124 /* case 0: nothing left to add */
125 }
126 mix(a,b,c);
127 /*-------------------------------------------- report the result */
128 return (unsigned int) c;
129 }
130
131 /*
132 * _awka_hshinitnode
133 * prepares a new a_HSHNode for life in the outside world
134 */
135 #define _awka_hshinitnode( node ) \
136 { \
137 (node)->next = NULL; \
138 (node)->key = NULL; \
139 (node)->hval = 0; \
140 (node)->var->ptr = NULL; \
141 (node)->var->dval = 0; \
142 (node)->var->slen = 0; \
143 (node)->var->allc = 0; \
144 (node)->var->type2 = 0; \
145 (node)->var->type = a_VARNUL; \
146 (node)->var->temp = 0; \
147 }
148
149 /*
150 * _awka_splitinitnode
151 * prepares a new a_HSHNode for life in the outside world
152 */
153 #define _awka_splitinitnode( node ) \
154 { \
155 (node)->next = NULL; \
156 (node)->hval = 0; \
157 (node)->var->dval = 0; \
158 (node)->var->slen = 0; \
159 (node)->var->type2 = 0; \
160 (node)->var->type = a_VARNUL; \
161 (node)->var->temp = 0; \
162 }
163
164 void
_awka_hshdouble(_a_HSHarray * array)165 _awka_hshdouble( _a_HSHarray *array )
166 {
167 a_HSHNode *node, *prevnode;
168 unsigned int old_hashmask = array->hashmask, highbit, i, newi;
169
170 array->hashmask = (array->hashmask * 2) + 1;
171 realloc( &array->slot, (array->hashmask+1) * sizeof(a_HSHNode *) );
172
173 memset(array->slot + old_hashmask + 1, 0, (old_hashmask + 1) * sizeof(a_HSHNode *));
174
175 /* find highest bit in new hashmask */
176 highbit = i = array->hashmask;
177 newi = 0;
178 while (i) {
179 highbit = i;
180 newi++;
181 i = i >> 1;
182 }
183 newi--;
184 highbit = highbit << newi;
185
186 /* loop through nodes, relocating those with new addresses */
187 for (i=0; i<=old_hashmask; i++)
188 {
189 if (!array->slot[i]) continue;
190 prevnode = NULL;
191 node = array->slot[i];
192 do
193 {
194 if (node->hval & highbit)
195 {
196 /* this wants to move */
197 if (!prevnode)
198 array->slot[i] = node->next;
199 else
200 prevnode->next = node->next;
201
202 newi = node->hval & array->hashmask;
203 if (newi <= old_hashmask)
204 awka_error("array: internal corruption detected.\n");
205
206 node->next = array->slot[newi];
207 array->slot[newi] = node;
208
209 if (!prevnode)
210 node = array->slot[i];
211 else
212 node = prevnode->next;
213 }
214 else
215 {
216 /* this wants to stay */
217 prevnode = node;
218 node = node->next;
219 }
220 } while (node);
221 }
222 }
223
224 static a_HSHNode *
_awka_hshfindstr(_a_HSHarray * array,char * key,int len,unsigned int hval,char create,char shadow)225 _awka_hshfindstr(
226 _a_HSHarray *array,
227 char *key,
228 int len,
229 unsigned int hval,
230 char create,
231 char shadow
232 )
233 {
234 register unsigned int idx;
235 a_HSHNode *node, *node2 = NULL, *prevnode = NULL;
236
237 idx = hval & array->hashmask;
238 node = array->slot[idx];
239
240 while (node)
241 {
242 if (node->type == _a_ARR_STR &&
243 hval == node->hval &&
244 *(node->key) == *key)
245 {
246 if (*key == '\0' || !strcmp(node->key, key))
247 {
248 /* got a match */
249 if (create != a_ARR_DELETE)
250 {
251 if (prevnode)
252 {
253 prevnode->next = node->next;
254 node->next = array->slot[idx];
255 }
256 array->last = array->slot[idx] = node;
257
258 return node;
259 }
260
261 if (array->flag & _a_ARR_INT && shadow == FALSE)
262 {
263 if (!isalpha(key[0]) && _awka_isanint(key))
264 _awka_hshfindint(array, atoi(key), a_ARR_DELETE, TRUE);
265 }
266 if (shadow == FALSE)
267 {
268 awka_killvar(node->var);
269 if (node->var)
270 free(node->var);
271 }
272 if (prevnode == NULL)
273 array->slot[idx] = node->next;
274 else
275 prevnode->next = node->next;
276 array->nodeno--;
277
278 if (node->key)
279 free(node->key);
280 free(node);
281 array->last = NULL;
282 return node; /* this return value won't be used - don't worry */
283 }
284 }
285
286 prevnode = node;
287 node = node->next;
288 }
289
290 /* node not at home */
291 if (create != a_ARR_CREATE)
292 return NULL;
293
294 malloc(&node, sizeof(a_HSHNode));
295 malloc(&node->key, len+1);
296 memcpy(node->key, key, len+1);
297 node->shadow = shadow;
298 node->hval = hval;
299 node->type = _a_ARR_STR;
300 array->last = node->next = array->slot[idx];
301 array->slot[idx] = node;
302 if (shadow == TRUE) return node;
303 array->nodeno++;
304
305 malloc( &node->var, sizeof(a_VAR));
306 node->var->ptr = NULL;
307 node->var->type2 = 0;
308 node->var->dval = 0.0;
309 node->var->type = a_VARNUL;
310 node->var->temp = 0;
311 node->var->allc = node->var->slen = 0;
312 if (array->flag & _a_ARR_INT)
313 {
314 if (!isalpha(key[0]) && _awka_isanint(key))
315 {
316 node2 = _awka_hshfindint(array, atoi(key), create, TRUE);
317 node2->var = node->var;
318 }
319 }
320
321 return node;
322 }
323
324 static a_HSHNode *
_awka_hshfindint(_a_HSHarray * array,unsigned int hval,char create,char shadow)325 _awka_hshfindint(
326 _a_HSHarray *array,
327 unsigned int hval,
328 char create,
329 char shadow
330 )
331 {
332 register unsigned int idx, i;
333 a_HSHNode *node, *node2 = NULL, *prevnode = NULL;
334 static char buf[20];
335
336 idx = hval & array->hashmask;
337 node = array->slot[idx];
338
339 while (node)
340 {
341 if (node->type == _a_ARR_INT && hval == node->hval)
342 {
343 /* got a match */
344 if (create != a_ARR_DELETE)
345 {
346 if (prevnode && node == array->last)
347 {
348 prevnode->next = node->next;
349 node->next = array->slot[idx];
350 array->slot[idx] = node;
351 }
352 array->last = node;
353
354 return node;
355 }
356
357 if (array->flag & _a_ARR_STR && shadow == FALSE)
358 {
359 sprintf(buf, "%d", hval);
360 i = strlen(buf);
361 _awka_hshfindstr(array, buf, strlen(buf), _awka_hashstr(buf, i), a_ARR_DELETE, TRUE);
362 }
363 if (shadow == FALSE)
364 {
365 awka_killvar(node->var);
366 if (node->var)
367 free(node->var);
368 }
369 if (prevnode == NULL)
370 array->slot[idx] = node->next;
371 else
372 prevnode->next = node->next;
373 array->nodeno--;
374
375 free(node);
376 array->last = NULL;
377 return node;
378 }
379
380 prevnode = node;
381 node = node->next;
382 }
383
384 /* node not at home */
385 if (create != a_ARR_CREATE)
386 return NULL;
387
388 malloc( &node, sizeof(a_HSHNode));
389 node->key = NULL;
390 node->shadow = shadow;
391 node->hval = hval;
392 node->type = _a_ARR_INT;
393 node->next = array->slot[idx];
394 array->last = array->slot[idx] = node;
395 if (shadow == TRUE)
396 return node;
397 array->nodeno++;
398
399 malloc( &node->var, sizeof(a_VAR));
400 node->var->ptr = NULL;
401 node->var->type2 = 0;
402 node->var->dval = 0.0;
403 node->var->type = a_VARNUL;
404 node->var->temp = 0;
405 node->var->allc = node->var->slen = 0;
406 if (array->flag & _a_ARR_STR)
407 {
408 sprintf(buf, "%d", hval);
409 i = strlen(buf);
410 node2 = _awka_hshfindstr(array, buf, strlen(buf), _awka_hashstr(buf, i), create, TRUE);
411 node2->var = node->var;
412 }
413
414 return node;
415 }
416
417 void
_awka_hashtoint(_a_HSHarray * array)418 _awka_hashtoint( _a_HSHarray *array )
419 {
420 a_HSHNode *node, *node2;
421 register int i;
422
423 if (array->nodeno > _a_HSH_MAXDEPTH)
424 _awka_hshdouble(array);
425
426 for (i=0; i<=array->hashmask; i++)
427 {
428 node = array->slot[i];
429 while (node)
430 {
431 if (node->shadow == TRUE || node->type != _a_ARR_STR)
432 {
433 node = node->next;
434 continue;
435 }
436 if (node->key[0] && !isalpha(node->key[0]) && _awka_isanint(node->key))
437 {
438 node2 = _awka_hshfindint(array, atoi(node->key), a_ARR_CREATE, TRUE);
439 node2->var = node->var;
440 }
441 node = node->next;
442 }
443 }
444 array->flag |= _a_ARR_INT;
445 }
446
447 void
_awka_hashtostr(_a_HSHarray * array)448 _awka_hashtostr( _a_HSHarray *array )
449 {
450 a_HSHNode *node, *node2;
451 register int i, j;
452 static char buf[20];
453
454 if (array->nodeno > _a_HSH_MAXDEPTH)
455 _awka_hshdouble(array);
456
457 for (i=0; i<=array->hashmask; i++)
458 {
459 node = array->slot[i];
460 while (node)
461 {
462 if (node->shadow == TRUE || node->type != _a_ARR_INT)
463 {
464 node = node->next;
465 continue;
466 }
467 sprintf(buf, "%d", node->hval);
468 j = strlen(buf);
469 node2 = _awka_hshfindstr(array, buf, j, _awka_hashstr(buf, j), a_ARR_CREATE, TRUE);
470 node2->var = node->var;
471 node = node->next;
472 }
473 }
474 array->flag |= _a_ARR_STR;
475 }
476
477 /*
478 * _awka_split2hsh
479 * Changes an array created by 'split' to a
480 * general-purpose HSH array.
481 */
482 _a_HSHarray *
_awka_split2hsh(_a_HSHarray * array)483 _awka_split2hsh( _a_HSHarray *array )
484 {
485 a_HSHNode *node;
486 _a_HSHarray *newarray;
487 int i;
488
489 if (array->type != a_ARR_TYPE_SPLIT)
490 return NULL;
491
492 malloc( &newarray, sizeof(_a_HSHarray));
493 newarray->hashmask = _a_HASHMASK;
494 malloc( &newarray->slot, (_a_HASHMASK+1) * sizeof(a_HSHNode *) );
495 newarray->type = a_ARR_TYPE_HSH;
496 newarray->splitstr = NULL;
497 newarray->splitallc = 0;
498 newarray->nodeno = 0;
499 newarray->flag = _a_ARR_INT;
500 newarray->subscript = array->subscript;
501
502 for (i=0; i<=_a_HASHMASK; i++)
503 newarray->slot[i] = NULL;
504
505 for (i=0; i<array->nodeno; i++)
506 {
507 node = _awka_hshfindint( newarray, i+array->base, a_ARR_CREATE, FALSE );
508 awka_varcpy(node->var, array->slot[i]->var);
509 if (array->slot[i]->key != _a_SPLT_BASESTR)
510 awka_killvar(array->slot[i]->var);
511 free( array->slot[i] );
512 }
513
514 if (array->slot) free(array->slot);
515 if (array->splitstr) free(array->splitstr);
516 free(array);
517
518 return newarray;
519 }
520
521 /*
522 * _a_HshDestroyTreeNode
523 * passed the address of a node, this will recursively
524 * free its children then itself. Calling this with the
525 * slot node of a array will free the entire array.
526 */
527 void
_awka_hshdestroyarray(_a_HSHarray * array)528 _awka_hshdestroyarray( _a_HSHarray *array )
529 {
530 a_HSHNode *node, *nextnode;
531 int i;
532
533 for (i=0; i<=array->hashmask; i++)
534 {
535 node = array->slot[i];
536
537 while (node)
538 {
539 if (!node->shadow)
540 {
541 awka_killvar(node->var);
542 if (node->var) free(node->var);
543 }
544 nextnode = node->next;
545 if (node->key) free(node->key);
546 free(node);
547 node = nextnode;
548 }
549 }
550 if (array->slot)
551 free(array->slot);
552 if (array->subscript)
553 free(array->subscript);
554
555 array->hashmask = array->nodeno = array->nodeallc = 0;
556 array->slot = NULL;
557 array->type = a_ARR_TYPE_NULL;
558 }
559
560
561 #define MERGE_STRING \
562 p = awka_gets(var); \
563 thislen = var->slen; \
564 len += thislen + slen; \
565 if (len >= s->alloc) \
566 { \
567 s->alloc += len + ((used-i-1) * 20) + 1; \
568 s->alloc = realloc( &s->str, s->alloc); \
569 op = (s->str + (oldlen > 0 ? oldlen : 1)) - 1; \
570 } \
571 if (i) { \
572 if (slen == 1) \
573 *op++ = *subsep; \
574 else \
575 { \
576 memcpy(op, subsep, slen); \
577 op += slen; \
578 } \
579 } \
580 if (thislen == 1) \
581 *op++ = *p; \
582 else \
583 { \
584 memcpy(op, p, thislen); \
585 op += thislen; \
586 } \
587 oldlen = len
588 /*
589 * _awka_arraymergesubscripts
590 * Given multiple array subscripts, this merges them into
591 * a single char * inserting SUBSEP between each.
592 */
593 char *
_awka_arraymergesubscripts(_a_Subscript * s,a_VARARG * va,int * thelen)594 _awka_arraymergesubscripts( _a_Subscript *s, a_VARARG *va, int *thelen )
595 {
596 register int i = 0, len = 0, oldlen = 0, slen = 0, thislen, used = va->used;
597 register char *p, *op = s->str, *subsep;
598 register char is_dbl = FALSE;
599 a_VAR *var = va->var[0];
600
601 if (used > s->dalloc)
602 {
603 if (!s->dalloc)
604 {
605 s->dalloc = va->used + 3;
606 malloc( &s->delem, s->dalloc * sizeof(double));
607 malloc( &s->pelem, s->dalloc * sizeof(char *));
608 malloc( &s->lelem, s->dalloc * sizeof(int));
609 malloc( &s->dset, s->dalloc);
610 s->elem = 0;
611 }
612 else
613 {
614 s->dalloc = va->used + 3;
615 realloc( &s->delem, s->dalloc * sizeof(double));
616 realloc( &s->pelem, s->dalloc * sizeof(char *));
617 realloc( &s->lelem, s->dalloc * sizeof(int));
618 realloc( &s->dset, s->dalloc);
619 }
620 }
621
622 if (!s->str)
623 {
624 s->alloc = malloc( &s->str, 20);
625 op = s->str;
626 }
627
628 subsep = awka_gets1(a_bivar[a_SUBSEP]);
629 slen = a_bivar[a_SUBSEP]->slen;
630
631 is_dbl = (var->type == a_VARDBL ||
632 (var->type == a_VARUNK && var->type2 == a_DBLSET));
633
634 if (s->str && is_dbl == TRUE)
635 {
636 for (; i<used; var = va->var[++i])
637 {
638 if (s->dset[i] == FALSE || i >= s->elem)
639 break;
640 is_dbl = (var->type == a_VARDBL ||
641 (var->type == a_VARUNK && var->type2 == a_DBLSET));
642
643 if (!is_dbl || s->delem[i] != var->dval)
644 break;
645
646 op = s->pelem[i];
647 oldlen = len = s->lelem[i];
648 }
649
650 if (i == used)
651 {
652 s->elem = i;
653 *thelen = len - 1;
654 return s->str;
655 }
656 }
657
658 if (is_dbl == TRUE)
659 {
660 for (; i<used; var = va->var[++i])
661 {
662 if (!(var->type == a_VARDBL ||
663 (var->type == a_VARUNK && var->type2 == a_DBLSET)))
664 break;
665
666 MERGE_STRING;
667 s->pelem[i] = op;
668 s->lelem[i] = len;
669 s->delem[i] = var->dval;
670 s->dset[i] = TRUE;
671 }
672
673 if (i == used)
674 {
675 s->elem = i;
676 *op = '\0';
677 *thelen = len - 1;
678 return s->str;
679 }
680 }
681
682 s->elem = i;
683
684 for (; i<used; var = va->var[++i])
685 {
686 MERGE_STRING;
687 }
688
689 if (op) *op = '\0';
690 *thelen = len - 1;
691
692 return s->str;
693 }
694
695
696 /*
697 * _awka_arrayinitargv
698 * This initialises the ARGV builtin-var with contents
699 * of *argv[]. Called by a_Init().
700 */
701 void
_awka_arrayinitargv(char ** ptr,int argc,char * argv[])702 _awka_arrayinitargv( char **ptr, int argc, char *argv[] )
703 {
704 int len, i;
705 _a_HSHarray *array;
706
707 malloc( &a_bivar[a_ARGV]->ptr, sizeof(_a_HSHarray) );
708 array = (_a_HSHarray *) a_bivar[a_ARGV]->ptr;
709 array->type = a_ARR_TYPE_SPLIT;
710 array->nodeno = array->nodeallc = argc;
711 malloc( &array->slot, argc * sizeof(a_HSHNode *));
712 array->splitstr = NULL;
713 array->splitallc = 0;
714
715 for (i=0; i<argc; i++)
716 {
717 malloc( &array->slot[i], sizeof(a_HSHNode));
718 array->slot[i]->next = NULL;
719 array->slot[i]->hval = 0;
720
721 malloc( &array->slot[i]->var, sizeof(a_VAR));
722 array->slot[i]->var->slen = array->slot[i]->var->allc = len = strlen(argv[i]);
723 malloc( &array->slot[i]->var->ptr, len+1);
724 memcpy(array->slot[i]->var->ptr, argv[i], len+1);
725 array->slot[i]->var->type = a_VARUNK;
726 if (_awka_isnumber(argv[i]) == TRUE)
727 {
728 array->slot[i]->var->type2 = a_DBLSET;
729 array->slot[i]->var->dval = strtod(argv[i], NULL);
730 }
731 else
732 array->slot[i]->var->type2 = -1;
733 array->slot[i]->key = _a_SPLT_LOCALSTR;
734 array->slot[i]->type = _a_ARR_INT;
735 }
736 }
737
738 /*
739 * _awka_arrayinitenviron
740 * This initialises the ENVIRON builtin-var.
741 * Called by a_Init().
742 */
743 void
_awka_arrayinitenviron(char ** ptr,int env_used)744 _awka_arrayinitenviron( char **ptr, int env_used )
745 {
746 extern char **environ;
747 register char *s, **p = environ, *q;
748 char *tmpstr;
749 int alloc;
750 a_VAR *tmp = NULL, *ret;
751
752 if (!env_used) return;
753 awka_varinit(tmp);
754 alloc = malloc( &tmpstr, 30 );
755 awka_arraycreate( a_bivar[a_ENVIRON], a_ARR_TYPE_HSH );
756
757 while ((q = *p))
758 {
759 if ((s = strchr(q, '=')))
760 {
761 if (s - q >= alloc)
762 alloc = realloc( &tmpstr, (s-q)+1 );
763 memcpy(tmpstr, q, (s - q));
764 tmpstr[s-q] = '\0';
765 awka_strcpy(tmp, tmpstr);
766 ret = awka_arraysearch1( a_bivar[a_ENVIRON], tmp, a_ARR_CREATE, 0);
767 awka_strcpy(ret, s+1);
768 ret->type = a_VARUNK;
769 if (_awka_isnumber(ret->ptr) == TRUE)
770 {
771 ret->type2 = a_DBLSET;
772 ret->dval = strtod(ret->ptr, NULL);
773 }
774 else
775 ret->type2 = -1;
776 }
777 p++;
778 }
779
780 free(tmpstr);
781 awka_killvar(tmp);
782 if (tmp) free(tmp);
783 }
784
785 _a_Subscript *
_awka_createsubscript()786 _awka_createsubscript()
787 {
788 _a_Subscript *subscript;
789
790 malloc( &subscript, sizeof(_a_Subscript) );
791 subscript->str = NULL;
792 subscript->delem = NULL;
793 subscript->pelem = NULL;
794 subscript->lelem = NULL;
795 subscript->dset = NULL;
796 subscript->alloc = subscript->dalloc = subscript->elem = 0;
797
798 return subscript;
799 }
800
801 /* PUBLIC INTERFACE FUNCTIONS BELOW */
802
803 /*
804 * awka_arraycreate
805 * creates a new, null array and makes var point to it.
806 */
807 void
awka_arraycreate(a_VAR * var,char type)808 awka_arraycreate( a_VAR *var, char type )
809 {
810 _a_HSHarray *array;
811
812 if (var->ptr) free(var->ptr);
813 var->type = a_VARARR;
814 malloc( &var->ptr, sizeof(_a_HSHarray) );
815 array = (_a_HSHarray *) var->ptr;
816
817 array->subscript = _awka_createsubscript();
818 array->last = NULL;
819
820 if (type == a_ARR_TYPE_HSH)
821 {
822 array->hashmask = _a_HASHMASK;
823 malloc( &array->slot, (_a_HASHMASK+1) * sizeof(a_HSHNode *) );
824 array->type = a_ARR_TYPE_HSH;
825 array->splitstr = NULL;
826 array->splitallc = 0;
827 memset(array->slot, 0, (_a_HASHMASK+1) * sizeof(a_HSHNode *) );
828 array->nodeno = array->base = array->nodeallc = 0;
829 }
830 else
831 {
832 array->hashmask = 0;
833 /* array->slot = NULL; */
834 array->type = a_ARR_TYPE_SPLIT;
835 array->splitstr = NULL;
836 array->splitallc = 0;
837 array->nodeno = array->base = 0;
838 array->nodeallc = 0;
839 malloc( &array->slot, 16 * sizeof(a_HSHNode *) );
840 }
841 array->flag = 0;
842 }
843
844 /*
845 * awka_arrayclear
846 * deletes memory held by a array and sets it to empty status.
847 * awk - 'delete(MyArr)'
848 */
849 void
awka_arrayclear(a_VAR * var)850 awka_arrayclear( a_VAR *var )
851 {
852 _a_HSHarray *array;
853 register int i;
854 a_HSHNode *node, *nextnode;
855
856 if (var->type == a_VARNUL || !var->ptr || (var->type == a_VARSTR && var->ptr[0] == '\0'))
857 awka_arraycreate( var, a_ARR_TYPE_HSH );
858
859 if (var->type != a_VARARR)
860 awka_error("runtime error: Scalar used as array in call to ArrayClear\n");
861
862 array = (_a_HSHarray *) var->ptr;
863
864 if (array->type == a_ARR_TYPE_NULL) return;
865
866 if (array->type == a_ARR_TYPE_SPLIT)
867 {
868 for (i=0; i<array->nodeallc; i++)
869 {
870 if (array->slot[i])
871 {
872 if (array->slot[i]->key == _a_SPLT_LOCALSTR)
873 awka_killvar(array->slot[i]->var);
874 free(array->slot[i]->var);
875 free(array->slot[i]);
876 }
877 }
878
879 if (array->splitstr)
880 free(array->splitstr);
881 if (array->slot)
882 free(array->slot);
883 }
884 else
885 {
886 for (i=0; i<=array->hashmask; i++)
887 {
888 node = array->slot[i];
889 while (node)
890 {
891 if (node->shadow == FALSE)
892 {
893 awka_killvar(node->var);
894 free(node->var);
895 }
896 if (node->key) free(node->key);
897 nextnode = node->next;
898 free(node);
899 node = nextnode;
900 }
901 }
902 if (array->slot)
903 free(array->slot);
904 }
905
906 if (array->subscript)
907 {
908 if (array->subscript->str) free(array->subscript->str);
909 if (array->subscript->delem) free(array->subscript->delem);
910 if (array->subscript->pelem) free(array->subscript->pelem);
911 if (array->subscript->lelem) free(array->subscript->lelem);
912 if (array->subscript->dset) free(array->subscript->dset);
913 free(array->subscript);
914 }
915
916 array->hashmask = array->nodeno = array->nodeallc = array->splitallc = 0;
917 array->slot = NULL;
918 array->subscript = NULL;
919 array->type = a_ARR_TYPE_NULL;
920 array->splitstr = NULL;
921 }
922
923 static INLINE a_VAR *
_awka_arraynullvar()924 _awka_arraynullvar()
925 {
926 a_VAR *pv;
927
928 _awka_tmpvar(pv);
929
930 if (pv->ptr)
931 awka_killvar(pv);
932
933 pv->slen = (unsigned) -1;
934 pv->allc = 0;
935 pv->type = a_VARDBL;
936 pv->dval = 0.0;
937 pv->temp = pv->type2 = 0;
938 return pv;
939 }
940
941 static INLINE a_VAR *
_awka_arrayfoundvar()942 _awka_arrayfoundvar()
943 {
944 a_VAR *pv;
945
946 _awka_tmpvar(pv);
947
948 if (pv->ptr)
949 awka_killvar(pv);
950
951 pv->slen = (unsigned) 0;
952 pv->allc = 0;
953 pv->type = a_VARDBL;
954 pv->dval = 1.0;
955 pv->temp = pv->type2 = 0;
956 return pv;
957 }
958
959 void
_awka_growarray(_a_HSHarray * array,int i)960 _awka_growarray(_a_HSHarray *array, int i)
961 {
962 int j;
963 a_HSHNode *node;
964
965 realloc( &array->slot, (i+16) * sizeof(a_HSHNode *));
966 for (j=i+1; j<(i+16); j++)
967 array->slot[j] = NULL;
968
969 for (j=array->nodeallc; j<=i; j++)
970 {
971 malloc( &node, sizeof(a_HSHNode) );
972 array->slot[j] = node;
973 malloc( &node->var, sizeof(a_VAR));
974 node->var->ptr = NULL;
975 node->key = _a_SPLT_LOCALSTR;
976 node->var->type = a_VARNUL;
977 _awka_splitinitnode(node);
978 node->var->slen = node->var->allc = 0;
979 node->var->dval = 0;
980 node->var->type2 = 0;
981 array->slot[j]->var->ptr = NULL;
982 }
983 array->nodeallc = i+16;
984 }
985
986 /*
987 * _awka_arraysearchsplit
988 * performs a search for a key on a 'split' array.
989 */
990 a_VAR *
_awka_arraysearchsplit(_a_HSHarray * array,int i,char create,int set)991 _awka_arraysearchsplit(_a_HSHarray *array, int i, char create, int set)
992 {
993 char *x;
994 register int j;
995
996 /* split array - is v->type a double? */
997 if (i >= array->nodeno)
998 {
999 if (create == a_ARR_QUERY)
1000 return _awka_arraynullvar();
1001 if (i >= array->nodeallc)
1002 _awka_growarray(array, i);
1003 else
1004 {
1005 for (j=array->nodeno; j<=i; j++)
1006 {
1007 if (!array->slot[j])
1008 {
1009 malloc( &array->slot[j], sizeof(a_HSHNode));
1010 malloc( &array->slot[j]->var, sizeof(a_VAR));
1011 array->slot[j]->key = _a_SPLT_LOCALSTR;
1012 array->slot[j]->var->allc = 0;
1013 _awka_splitinitnode(array->slot[j]);
1014 array->slot[j]->var->type = a_VARNUL;
1015 array->slot[j]->var->ptr = NULL;
1016 }
1017 else
1018 {
1019 if (array->slot[j]->key == _a_SPLT_LOCALSTR &&
1020 array->slot[j]->var->ptr)
1021 awka_killvar(array->slot[j]->var);
1022
1023 array->slot[j]->key = _a_SPLT_LOCALSTR;
1024 array->slot[j]->var->allc = 0;
1025 _awka_splitinitnode(array->slot[j]);
1026 array->slot[j]->var->type = a_VARNUL;
1027 array->slot[j]->var->ptr = NULL;
1028 }
1029 }
1030 }
1031 array->nodeno = i+1;
1032 }
1033 if (set == 0 ||
1034 (array->slot[i]->key == _a_SPLT_LOCALSTR &&
1035 array->slot[i]->var->type2 == a_DBLSET))
1036 return array->slot[i]->var;
1037
1038 if (array->slot[i]->key == _a_SPLT_BASESTR)
1039 {
1040 if (array->slot[i]->var->type == a_VARUNK ||
1041 array->slot[i]->var->type == a_VARSTR)
1042 {
1043 array->slot[i]->var->allc = malloc( &x, array->slot[i]->var->slen + 1);
1044 strcpy(x, array->slot[i]->var->ptr);
1045 array->slot[i]->var->ptr = x;
1046 }
1047 else
1048 array->slot[i]->var->ptr = NULL;
1049 array->slot[i]->key = _a_SPLT_LOCALSTR;
1050 }
1051 return array->slot[i]->var;
1052 }
1053
1054 /*
1055 * For '1-based' split arrays, this is called if
1056 * the array is searched using element zero. It
1057 * adjusts the true base of the array to zero by
1058 * shifting all elements up by one.
1059 */
1060 void
_awka_lowerbase(_a_HSHarray * array)1061 _awka_lowerbase( _a_HSHarray *array )
1062 {
1063 register int i;
1064
1065 if (array->nodeallc == array->nodeno)
1066 {
1067 array->nodeallc += 10;
1068 realloc(&array->slot, array->nodeallc * sizeof(a_HSHNode *));
1069 for (i=array->nodeno; i<array->nodeallc; i++)
1070 array->slot[i] = NULL;
1071 }
1072
1073 for (i=array->nodeno; i>0; i--)
1074 array->slot[i] = array->slot[i-1];
1075
1076 malloc( &array->slot[0], sizeof(a_HSHNode));
1077 malloc( &array->slot[0]->var, sizeof(a_VAR));
1078 array->slot[0]->key = _a_SPLT_LOCALSTR;
1079 array->slot[0]->var->allc = 0;
1080 array->slot[0]->var->ptr = NULL;
1081 _awka_splitinitnode(array->slot[0]);
1082 array->slot[0]->var->type = a_VARNUL;
1083
1084 array->nodeno++;
1085 array->base = 0;
1086 }
1087
1088 /*
1089 * awka_arraysearch1
1090 * Interface for searching, inserting and deleting
1091 * elements in an array variable.
1092 */
1093 a_VAR *
awka_arraysearch1(a_VAR * v,a_VAR * element,char create,int set)1094 awka_arraysearch1( a_VAR *v, a_VAR *element, char create, int set )
1095 {
1096 int i = -1, j;
1097 register char *ptr = NULL, is_an_int = FALSE;
1098 unsigned int hval;
1099 a_HSHNode *node = NULL;
1100 _a_HSHarray *array;
1101 a_VAR *pv;
1102
1103 /* check our arguments */
1104 if (v->type != a_VARARR && v->type != a_VARNUL)
1105 awka_error("runtime error: Scalar used as array in call to ArraySearch\n");
1106
1107 if (!v->ptr)
1108 awka_arraycreate( v, a_ARR_TYPE_HSH );
1109
1110 array = (_a_HSHarray *) v->ptr;
1111 if (array->slot == NULL)
1112 {
1113 if (create != a_ARR_CREATE) return _awka_arraynullvar();
1114 awka_arraycreate( v, a_ARR_TYPE_HSH );
1115 array = (_a_HSHarray *) v->ptr;
1116 }
1117
1118 switch (array->type)
1119 {
1120 case a_ARR_TYPE_SPLIT:
1121 if (element->type == a_VARDBL ||
1122 (element->type == a_VARUNK && element->type2 == a_DBLSET))
1123 {
1124 i = (int) element->dval;
1125 if ((double) i == element->dval)
1126 is_an_int = TRUE;
1127 }
1128 else
1129 {
1130 ptr = awka_gets1(element);
1131 if ((is_an_int = _awka_isanint(ptr)) == TRUE)
1132 i = atoi(ptr);
1133 }
1134 if (create != a_ARR_DELETE && is_an_int == TRUE && i >= 0)
1135 {
1136 if (i == 0 && array->base)
1137 _awka_lowerbase(array);
1138 j = i - array->base; /* this makes all arrays zero based */
1139 if (j >= 0 && j < array->nodeno + 132)
1140 {
1141 pv = _awka_arraysearchsplit(array, j, create, set);
1142 if (pv)
1143 {
1144 if (pv->slen != -1 && create == a_ARR_QUERY)
1145 return _awka_arrayfoundvar();
1146 return pv;
1147 }
1148 if (create == a_ARR_QUERY) break;
1149 }
1150 }
1151 array = _awka_split2hsh(array);
1152 v->ptr = (char *) array;
1153
1154 case a_ARR_TYPE_HSH:
1155 if (element->type == a_VARDBL ||
1156 (element->type == a_VARUNK && element->type2 == a_DBLSET))
1157 {
1158 if (is_an_int == FALSE)
1159 {
1160 i = (int) element->dval;
1161 if ((double) i == element->dval)
1162 is_an_int = TRUE;
1163 }
1164 if (is_an_int == TRUE)
1165 {
1166 if (!(array->flag & _a_ARR_INT))
1167 {
1168 if (array->flag & _a_ARR_STR)
1169 _awka_hashtoint(array);
1170 array->flag |= _a_ARR_INT;
1171 }
1172 node = _awka_hshfindint(array, i, create, FALSE);
1173 break;
1174 }
1175 }
1176 if (!ptr)
1177 ptr = awka_gets(element);
1178 if (!(array->flag & _a_ARR_STR))
1179 {
1180 if (array->flag & _a_ARR_INT)
1181 _awka_hashtostr(array);
1182 array->flag |= _a_ARR_STR;
1183 }
1184 hval = _awka_hashstr(ptr, element->slen);
1185 node = _awka_hshfindstr(array, ptr, element->slen, hval, create, FALSE );
1186 }
1187
1188 if (node)
1189 {
1190 switch (create)
1191 {
1192 case a_ARR_CREATE:
1193 if (array->type == a_ARR_TYPE_HSH)
1194 {
1195 if (array->flag & _a_ARR_INT && array->flag & _a_ARR_STR)
1196 i = (array->nodeno / 2) / array->hashmask;
1197 else
1198 i = array->nodeno / array->hashmask;
1199 if (i > _a_HSH_MAXDEPTH)
1200 _awka_hshdouble(array);
1201 }
1202 return node->var;
1203
1204 case a_ARR_QUERY:
1205 return _awka_arrayfoundvar();
1206
1207 case a_ARR_DELETE:
1208 /* if array is now empty destroy it
1209 if (array->nodeno == 0)
1210 _awka_hshdestroyarray( array ); */
1211 return NULL;
1212 }
1213 }
1214
1215 return _awka_arraynullvar();
1216 }
1217
1218 /*
1219 * awka_arraysearch
1220 * Interface for searching, inserting and deleting
1221 * multiple-dimension elements in an array variable.
1222 */
1223 a_VAR *
awka_arraysearch(a_VAR * v,a_VARARG * va,char create)1224 awka_arraysearch( a_VAR *v, a_VARARG *va, char create )
1225 {
1226 int i, j;
1227 unsigned int hval;
1228 a_HSHNode *node = NULL;
1229 _a_HSHarray *array;
1230 char *s;
1231
1232 /* check our arguments */
1233 if (v->type != a_VARARR && v->type != a_VARNUL)
1234 awka_error("runtime error: Scalar used as array in call to ArraySearch\n");
1235
1236 if (!v->ptr)
1237 awka_arraycreate( v, a_ARR_TYPE_HSH );
1238
1239 array = (_a_HSHarray *) v->ptr;
1240 if (array->slot == NULL)
1241 {
1242 if (create != a_ARR_CREATE) return _awka_arraynullvar();
1243 awka_arraycreate( v, a_ARR_TYPE_HSH );
1244 array = (_a_HSHarray *) v->ptr;
1245 }
1246
1247 if (array->type == a_ARR_TYPE_SPLIT)
1248 {
1249 /* convert array to hash so we can do a hash search */
1250 array = _awka_split2hsh(array);
1251 v->ptr = (char *) array;
1252 }
1253
1254 if (!(array->flag & _a_ARR_STR))
1255 {
1256 if (array->flag & _a_ARR_INT)
1257 _awka_hashtostr(array);
1258 array->flag |= _a_ARR_STR;
1259 }
1260 if (!array->subscript)
1261 array->subscript = _awka_createsubscript();
1262 s = _awka_arraymergesubscripts( array->subscript, va, &j );
1263 hval = _awka_hashstr(s, j);
1264 node = _awka_hshfindstr(array, s, j, hval, create, FALSE );
1265
1266 if (node)
1267 {
1268 switch (create)
1269 {
1270 case a_ARR_CREATE:
1271 if (array->type == a_ARR_TYPE_HSH)
1272 {
1273 if (array->flag & _a_ARR_INT && array->flag & _a_ARR_STR)
1274 i = (array->nodeno / 2) / array->hashmask;
1275 else
1276 i = array->nodeno / array->hashmask;
1277 if (i > _a_HSH_MAXDEPTH)
1278 _awka_hshdouble(array);
1279 }
1280 return node->var;
1281
1282 case a_ARR_QUERY:
1283 return _awka_arrayfoundvar();
1284
1285 case a_ARR_DELETE:
1286 /* if array is now empty destroy it
1287 if (array->nodeno == 0)
1288 _awka_hshdestroyarray( array ); */
1289 return NULL;
1290 }
1291 }
1292
1293 return _awka_arraynullvar();
1294 }
1295
1296 int
_awka_splitre(_a_HSHarray * array,a_VAR * fs,int max,int oldnodeno)1297 _awka_splitre( _a_HSHarray *array, a_VAR *fs, int max, int oldnodeno )
1298 {
1299 awka_regexp *r = (awka_regexp *) fs->ptr;
1300 a_HSHNode *node;
1301 register int i = 0, alloc = 20, len, j;
1302 char *start, *end, *s, *earlystart;
1303 static regmatch_t pmatch;
1304
1305 s = array->splitstr; earlystart = array->splitstr;
1306 if (!array->nodeallc || !array->slot)
1307 {
1308 malloc( &array->slot, alloc * sizeof(a_HSHNode *) );
1309 for (i=0; i<alloc; i++) array->slot[i] = NULL;
1310 i = 0;
1311 }
1312 else
1313 alloc = array->nodeallc;
1314
1315 if (array->splitstr[0] == '\0')
1316 {
1317 array->nodeno = 1;
1318 if (!array->slot[0])
1319 {
1320 malloc( &node, sizeof(a_HSHNode));
1321 array->slot[0] = node;
1322 malloc( &node->var, sizeof(a_VAR));
1323 node->var->ptr = node->key = NULL;
1324 _awka_splitinitnode(node);
1325 }
1326 else
1327 node = array->slot[0];
1328 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1329 awka_killvar(node->var);
1330 node->key = _a_SPLT_BASESTR;
1331 node->var->type = a_VARUNK;
1332 node->var->type2 = 0;
1333 node->var->slen = 0;
1334 node->var->allc = 0;
1335 node->var->dval = 0.0;
1336 node->var->ptr = nullstr;
1337 node->type = _a_ARR_INT;
1338 if (array->nodeallc == 0) array->nodeallc = alloc;
1339 return 1;
1340 }
1341
1342 if (r->fs != TRUE)
1343 {
1344 r = _awka_compile_regexp_SPLIT(r->origstr, r->strlen);
1345 fs->ptr = (char *) r;
1346 }
1347
1348 len = strlen(array->splitstr);
1349
1350 while (i < max && !awka_regexec(r, s, 1, &pmatch, REG_NEEDSTART))
1351 {
1352 start = s + pmatch.rm_so;
1353 end = s + pmatch.rm_eo;
1354
1355 if (!array->slot[i])
1356 {
1357 malloc( &node, sizeof(a_HSHNode));
1358 malloc( &node->var, sizeof(a_VAR));
1359 node->var->ptr = node->key = NULL;
1360 node->key = _a_SPLT_BASESTR;
1361 array->slot[i++] = node;
1362 _awka_splitinitnode(node);
1363 }
1364 else
1365 node = array->slot[i++];
1366 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1367 awka_killvar(node->var);
1368 node->var->type = a_VARUNK;
1369 node->type = _a_ARR_INT;
1370 node->var->type2 = 0;
1371 if (node->key == _a_SPLT_BASESTR)
1372 node->var->ptr = s;
1373 else
1374 {
1375 if (!node->var->ptr)
1376 node->var->allc = malloc( &node->var->ptr, (start - s) + 1 );
1377 else if (node->var->allc < (start - s) + 1)
1378 node->var->allc = realloc( &node->var->ptr, (start - s) + 1 );
1379 memcpy(node->var->ptr, s, start - s);
1380 }
1381 node->var->slen = (start - s);
1382 *(node->var->ptr + (start - s)) = '\0';
1383
1384 if (i >= alloc)
1385 {
1386 j = alloc;
1387 alloc += 20;
1388 realloc( &array->slot, alloc * sizeof(a_HSHNode *));
1389 for (; j<alloc; j++) array->slot[j] = NULL;
1390 }
1391
1392 s = earlystart = end;
1393 if (!*s) break;
1394 }
1395
1396 if (i < max && *earlystart)
1397 {
1398 /* got a trailing field */
1399 s = array->splitstr + len;
1400 if (!array->slot[i])
1401 {
1402 malloc( &node, sizeof(a_HSHNode));
1403 malloc( &node->var, sizeof(a_VAR));
1404 node->var->ptr = node->key = NULL;
1405 node->key = _a_SPLT_BASESTR;
1406 array->slot[i++] = node;
1407 _awka_splitinitnode(node);
1408 }
1409 else
1410 node = array->slot[i++];
1411 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1412 awka_killvar(node->var);
1413 node->var->type = a_VARUNK;
1414 node->type = _a_ARR_INT;
1415 node->var->type2 = 0;
1416 if (node->key == _a_SPLT_BASESTR)
1417 node->var->ptr = earlystart;
1418 else
1419 {
1420 if (!node->var->ptr)
1421 node->var->allc = malloc( &node->var->ptr, (s - earlystart) + 1 );
1422 else if (node->var->allc <= s - earlystart)
1423 node->var->allc = realloc( &node->var->ptr, (s - earlystart) + 1 );
1424 memcpy(node->var->ptr, earlystart, s - earlystart);
1425 }
1426 node->var->slen = (s - earlystart);
1427 *(node->var->ptr + (s - earlystart)) = '\0';
1428
1429 if (i >= alloc)
1430 {
1431 j = alloc;
1432 alloc = i + 1;
1433 realloc( &array->slot, alloc * sizeof(a_HSHNode *));
1434 for (; j<alloc; j++) array->slot[j] = NULL;
1435 }
1436 }
1437
1438 for (j=i; j<oldnodeno; j++)
1439 {
1440 array->slot[j]->var->slen = 0;
1441 array->slot[j]->var->dval = 0;
1442 if (array->slot[j]->key == _a_SPLT_BASESTR)
1443 array->slot[j]->var->ptr = nullstr;
1444 else
1445 {
1446 awka_killvar(array->slot[j]->var);
1447 array->slot[j]->key = _a_SPLT_BASESTR;
1448 }
1449 array->slot[j]->var->dval = 0;
1450 array->slot[j]->var->type2 = 0;
1451 array->slot[j]->var->type = a_VARNUL;
1452 }
1453 array->nodeno = i;
1454 array->nodeallc = (array->nodeallc < array->nodeno ? array->nodeno : array->nodeallc);
1455 return i;
1456 }
1457
1458 int
_awka_split_null(_a_HSHarray * array,int max,int oldnodeno)1459 _awka_split_null( _a_HSHarray *array, int max, int oldnodeno )
1460 {
1461 register int i = 0, alloc = 10, j;
1462 a_HSHNode *node;
1463
1464 /* NULL FS - split by character */
1465 alloc = strlen(array->splitstr);
1466 alloc = (alloc < max ? alloc : max);
1467 for (j=alloc; j<oldnodeno; j++)
1468 {
1469 array->slot[j]->var->slen = 0;
1470 array->slot[j]->var->dval = 0;
1471 if (array->slot[j]->key == _a_SPLT_BASESTR)
1472 array->slot[j]->var->ptr = NULL;
1473 else
1474 {
1475 awka_killvar(array->slot[j]->var);
1476 array->slot[j]->key = _a_SPLT_BASESTR;
1477 }
1478 array->slot[j]->var->dval = 0;
1479 array->slot[j]->var->type2 = 0;
1480 array->slot[j]->var->type = a_VARNUL;
1481 }
1482 array->nodeno = alloc;
1483 if (array->slot)
1484 {
1485 if (array->nodeallc < alloc)
1486 {
1487 realloc( &array->slot, alloc * sizeof(a_HSHNode *) );
1488 for (i=array->nodeallc; i<alloc; i++)
1489 array->slot[i] = NULL;
1490 array->nodeallc = alloc;
1491 }
1492 }
1493 else
1494 {
1495 malloc( &array->slot, array->nodeno * sizeof(a_HSHNode *) );
1496 for (i=0; i<array->nodeno; i++)
1497 array->slot[i] = NULL;
1498 array->nodeallc = alloc;
1499 }
1500
1501 for (i=0; i<array->nodeno; i++)
1502 {
1503 if (!array->slot[i])
1504 {
1505 malloc( &node, sizeof(a_HSHNode) );
1506 malloc( &node->var, sizeof(a_VAR));
1507 node->var->ptr = node->key = NULL;
1508 node->key = _a_SPLT_LOCALSTR;
1509 array->slot[i] = node;
1510 _awka_splitinitnode(node);
1511 }
1512 else
1513 node = array->slot[i];
1514 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1515 awka_killvar(node->var);
1516 node->var->type = a_VARUNK;
1517 node->type = _a_ARR_INT;
1518 node->var->type2 = 0;
1519 if (node->var->ptr == NULL)
1520 node->var->allc = malloc(&node->var->ptr, 2);
1521 node->var->ptr[0] = array->splitstr[i];
1522 node->var->ptr[1] = '\0';
1523 node->var->type2 = 0;
1524 if (isdigit(array->splitstr[i]))
1525 {
1526 node->var->type2 = a_DBLSET;
1527 node->var->dval = node->var->ptr[0] - '0';
1528 }
1529 node->var->slen = 1;
1530 }
1531
1532 array->nodeallc = (array->nodeallc < array->nodeno ? array->nodeno : array->nodeallc);
1533 return array->nodeno;
1534 }
1535
1536 #define SWALLOW_SPACE \
1537 while (_a_space[(unsigned char) *p]) p++
1538
1539 #define SWALLOW_WORD \
1540 while (*p && !_a_space[(unsigned char) *p]) p++
1541
1542 int
_awka_split_space(_a_HSHarray * array,int max,int oldnodeno)1543 _awka_split_space( _a_HSHarray *array, int max, int oldnodeno )
1544 {
1545 register int i = 0, alloc = 20, j;
1546 register char *p, *q;
1547 a_HSHNode *node;
1548
1549 /* whitespace separator */
1550 p = q = array->splitstr;
1551 if (!array->nodeallc)
1552 {
1553 malloc( &array->slot, alloc * sizeof(a_HSHNode *) );
1554 for (i=0; i<alloc; i++)
1555 array->slot[i] = NULL;
1556 i = 0;
1557 }
1558 else
1559 alloc = array->nodeallc;
1560
1561 do {
1562 /* walk up to next word */
1563 SWALLOW_SPACE;
1564 if (!*p) /* hit end of str */
1565 break;
1566
1567 if (i >= alloc)
1568 {
1569 j = alloc;
1570 alloc += 20;
1571 realloc( &array->slot, alloc * sizeof(a_HSHNode *));
1572 for (; j<alloc; j++) array->slot[j] = NULL;
1573 }
1574
1575 q = p;
1576 /* walk to space after end of word */
1577 SWALLOW_WORD;
1578
1579 /* copy this to a node */
1580 if (!array->slot[i])
1581 {
1582 malloc( &node, sizeof(a_HSHNode) );
1583 malloc( &node->var, sizeof(a_VAR));
1584 node->var->ptr = NULL;
1585 node->key = _a_SPLT_BASESTR;
1586 array->slot[i++] = node;
1587 _awka_splitinitnode(node);
1588 }
1589 else
1590 node = array->slot[i++];
1591 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1592 awka_killvar(node->var);
1593
1594 node->var->type = a_VARUNK;
1595 node->type = _a_ARR_INT;
1596 node->var->type2 = 0;
1597 if (node->key == _a_SPLT_BASESTR)
1598 {
1599 node->var->ptr = q;
1600 node->var->slen = (p-q);
1601 if (!*p)
1602 {
1603 *(node->var->ptr + (p-q)) = '\0';
1604 break;
1605 }
1606 *(node->var->ptr + (p-q)) = '\0';
1607 q = ++p;
1608 continue;
1609 }
1610
1611 if (node->var->ptr == NULL)
1612 node->var->allc = malloc( &node->var->ptr, (p - q) + 1 );
1613 else if (node->var->allc <= (p-q))
1614 node->var->allc = realloc( &node->var->ptr, (p - q) + 1 );
1615 memcpy(node->var->ptr, q, p - q);
1616
1617 node->var->slen = (p - q);
1618 if (!*p)
1619 {
1620 *(node->var->ptr + (p-q)) = '\0';
1621 break;
1622 }
1623 *(node->var->ptr + (p-q)) = '\0';
1624 q = ++p;
1625
1626 } while (i < max && *p);
1627
1628 for (j=i; j<oldnodeno; j++)
1629 {
1630 array->slot[j]->var->slen = 0;
1631 if (array->slot[j]->key == _a_SPLT_BASESTR)
1632 array->slot[j]->var->ptr = nullstr;
1633 else
1634 {
1635 awka_killvar(array->slot[j]->var);
1636 array->slot[j]->key = _a_SPLT_BASESTR;
1637 }
1638 array->slot[j]->var->dval = 0;
1639 array->slot[j]->var->type2 = 0;
1640 array->slot[j]->var->type = a_VARNUL;
1641 }
1642 array->nodeno = i;
1643 array->nodeallc = (array->nodeallc < array->nodeno ? array->nodeno : array->nodeallc);
1644 return array->nodeno;
1645 }
1646
1647 int
_awka_split_single_char(_a_HSHarray * array,char fs,int max,int oldnodeno)1648 _awka_split_single_char( _a_HSHarray *array, char fs, int max, int oldnodeno )
1649 {
1650 register int i = 0, alloc = 40, j;
1651 register char *p, *q;
1652 a_HSHNode *node;
1653
1654 /* single character separator */
1655 p = q = array->splitstr;
1656 if (!array->nodeallc)
1657 {
1658 malloc( &array->slot, alloc * sizeof(a_HSHNode *) );
1659 for (j=0; j<alloc; j++)
1660 array->slot[j] = NULL;
1661 }
1662 else
1663 alloc = array->nodeallc;
1664
1665 while (i < max && *p)
1666 {
1667 if (i == alloc)
1668 {
1669 j = alloc;
1670 alloc += 40;
1671 realloc( &array->slot, alloc * sizeof(a_HSHNode *));
1672 for (; j<alloc; j++) array->slot[j] = NULL;
1673 }
1674
1675 /* walk to character after end of word */
1676 while (*p != fs && *p) p++;
1677
1678 /* copy this to a node */
1679 if (!array->slot[i])
1680 {
1681 malloc( &node, sizeof(a_HSHNode) );
1682 malloc( &node->var, sizeof(a_VAR));
1683 node->var->ptr = NULL;
1684 node->key = _a_SPLT_BASESTR;
1685 array->slot[i++] = node;
1686 _awka_splitinitnode(node);
1687 }
1688 else
1689 node = array->slot[i++];
1690 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1691 awka_killvar(node->var);
1692 node->var->type = a_VARUNK;
1693 node->type = _a_ARR_INT;
1694 node->var->type2 = 0;
1695 if (node->key == _a_SPLT_BASESTR)
1696 {
1697 node->var->ptr = q;
1698 node->var->slen = (p - q);
1699 if (!*p)
1700 {
1701 *(node->var->ptr + (p-q)) = '\0';
1702 break;
1703 }
1704 *(node->var->ptr + (p-q)) = '\0';
1705 if (*(p+1) != '\0')
1706 {
1707 q = ++p;
1708 continue;
1709 }
1710 }
1711 else
1712 {
1713 if (node->var->ptr == NULL)
1714 node->var->allc = malloc( &node->var->ptr, (p - q) + 1 );
1715 else if (node->var->allc <= (p - q))
1716 node->var->allc = malloc( &node->var->ptr, (p - q) + 1 );
1717 memcpy(node->var->ptr, q, p - q);
1718 node->var->slen = (p - q);
1719 if (!*p)
1720 {
1721 *(node->var->ptr + (p-q)) = '\0';
1722 break;
1723 }
1724 *(node->var->ptr + (p-q)) = '\0';
1725
1726 if (*(p+1) != '\0')
1727 {
1728 q = ++p;
1729 continue;
1730 }
1731 }
1732
1733 /* got a trailing null field */
1734 if (!array->slot[i])
1735 {
1736 malloc( &node, sizeof(a_HSHNode) );
1737 malloc( &node->var, sizeof(a_VAR));
1738 node->var->ptr = NULL;
1739 node->key = _a_SPLT_BASESTR;
1740 array->slot[i++] = node;
1741 _awka_splitinitnode(node);
1742 }
1743 else
1744 node = array->slot[i++];
1745
1746 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1747 awka_killvar(node->var);
1748 node->var->type = a_VARUNK;
1749 node->type = _a_ARR_INT;
1750 node->var->type2 = 0;
1751 if (node->key == _a_SPLT_BASESTR)
1752 node->var->ptr = p+1;
1753 else
1754 {
1755 if (node->var->ptr == NULL)
1756 node->var->allc = malloc( &node->var->ptr, 1);
1757 node->var->type2 = 0;
1758 node->var->ptr[0] = '\0';
1759 node->var->dval = 0;
1760 }
1761 node->var->slen = 0;
1762 if (i == alloc)
1763 {
1764 j = alloc;
1765 alloc += 40;
1766 realloc( &array->slot, alloc * sizeof(a_HSHNode *));
1767 for (; j<alloc; j++) array->slot[j] = NULL;
1768 }
1769 break;
1770 }
1771
1772 for (j=i; j<oldnodeno; j++)
1773 {
1774 array->slot[j]->var->slen = 0;
1775 if (array->slot[j]->key == _a_SPLT_BASESTR)
1776 array->slot[j]->var->ptr = nullstr;
1777 else
1778 {
1779 awka_killvar(array->slot[j]->var);
1780 array->slot[j]->key = _a_SPLT_BASESTR;
1781 }
1782 array->slot[j]->var->dval = 0;
1783 array->slot[j]->var->type2 = 0;
1784 array->slot[j]->var->type = a_VARNUL;
1785 }
1786 array->nodeno = i;
1787 array->nodeallc = (array->nodeallc < array->nodeno ? array->nodeno : array->nodeallc);
1788 return array->nodeno;
1789 }
1790
1791 /*
1792 * _awka_parse_width_format
1793 * splits a FIELDWIDTHS format string into an array of ints
1794 */
1795 void
_awka_parse_width_format(char * format,int fw)1796 _awka_parse_width_format( char *format, int fw )
1797 {
1798 register char *p1 = format, *p2;
1799 int i = 0, end = FALSE;
1800 int *loc, used, allc;
1801
1802 if (fw)
1803 {
1804 loc = fw_loc;
1805 used = fw_used = 0;
1806 allc = fw_allc;
1807 }
1808 else
1809 {
1810 loc = sw_loc;
1811 used = sw_used = 0;
1812 allc = sw_allc;
1813 }
1814
1815 if (!allc)
1816 {
1817 allc = 20;
1818 malloc( &loc, allc * sizeof(int) );
1819 }
1820
1821 while (*p1)
1822 {
1823 /* walk up to first word */
1824 while (isspace(*p1)) p1++;
1825 if (!*p1) break;
1826 if (!isdigit(*p1)) break;
1827 p2 = p1;
1828
1829 /* walk to end of word */
1830 while (isdigit(*p2)) p2++;
1831 if (*p2 && !isspace(*p2))
1832 {
1833 used = -1;
1834 break;
1835 }
1836
1837 if (!*p2)
1838 {
1839 i = atoi(p1);
1840 end = TRUE;
1841 }
1842 else
1843 {
1844 *p2 = '\0';
1845 i = atoi(p1);
1846 *p2 = ' ';
1847 }
1848
1849 if (i <= 0)
1850 {
1851 used = -1;
1852 break;
1853 }
1854 if (used+1 >= allc)
1855 {
1856 allc *= 2;
1857 realloc(&loc, allc * sizeof(int));
1858 }
1859 loc[used++] = i;
1860
1861 if (end) break;
1862 p1 = p2+1;
1863 }
1864
1865 if (fw)
1866 {
1867 fw_used = used;
1868 fw_loc = loc;
1869 fw_allc = allc;
1870 }
1871 else
1872 {
1873 sw_used = used;
1874 sw_loc = loc;
1875 sw_allc = allc;
1876 }
1877 }
1878
1879 /*
1880 * _awka_arraysplitwidth
1881 * splits an array using the format in FIELDWIDTHS
1882 */
1883 double
_awka_arraysplitwidth(char * str,a_VAR * v,int max)1884 _awka_arraysplitwidth( char *str, a_VAR *v, int max )
1885 {
1886 static char *format = NULL;
1887 static int format_allc = 0;
1888 int i, j, len = strlen(str), flen, curlen = 0, count = 0;
1889 _a_HSHarray *array;
1890 a_HSHNode *node;
1891
1892 awka_gets(a_bivar[a_FIELDWIDTHS]);
1893 if (!format)
1894 {
1895 format_allc = malloc(&format, a_bivar[a_FIELDWIDTHS]->slen+1);
1896 fw_allc = 20;
1897 malloc(&fw_loc, 20 * sizeof(int));
1898 strcpy(format, a_bivar[a_FIELDWIDTHS]->ptr);
1899 _awka_parse_width_format(format, TRUE);
1900 if (!fw_used) return -1;
1901 }
1902 else if (strcmp(format, a_bivar[a_FIELDWIDTHS]->ptr))
1903 {
1904 if (a_bivar[a_FIELDWIDTHS]->slen >= format_allc)
1905 format_allc = realloc( &format, a_bivar[a_FIELDWIDTHS]->slen+1 );
1906 strcpy(format, a_bivar[a_FIELDWIDTHS]->ptr);
1907 _awka_parse_width_format(format, TRUE);
1908 if (!fw_used) return -1;
1909 }
1910
1911 if (len && str[len-1] == '\n')
1912 str[--len] = '\0';
1913
1914 array = (_a_HSHarray *) v->ptr;
1915 if (!array->nodeallc)
1916 {
1917 malloc( &array->slot, fw_used * sizeof(a_HSHNode *) );
1918 for (j=0; j<fw_used; j++)
1919 array->slot[j] = NULL;
1920 array->nodeallc = fw_used;
1921 }
1922 else if (array->nodeallc < fw_used)
1923 {
1924 realloc( &array->slot, fw_used * sizeof(a_HSHNode *) );
1925 for (j=array->nodeallc; j<fw_used; j++)
1926 array->slot[j] = NULL;
1927 array->nodeallc = fw_used;
1928 }
1929
1930 for (i=0; i<fw_used; i++)
1931 {
1932 count++;
1933 if (i < fw_used)
1934 {
1935 flen = fw_loc[i];
1936 if (fw_loc[i] + curlen > len)
1937 flen = len - curlen;
1938 }
1939 else
1940 flen = len - curlen;
1941
1942 if (!array->slot[i])
1943 {
1944 malloc( &node, sizeof(a_HSHNode) );
1945 malloc( &node->var, sizeof(a_VAR));
1946 node->var->ptr = NULL;
1947 node->key = _a_SPLT_LOCALSTR;
1948 array->slot[i] = node;
1949 _awka_splitinitnode(node);
1950 }
1951 else
1952 node = array->slot[i];
1953
1954 if (node->var->type != a_VARUNK && node->var->type != a_VARNUL)
1955 awka_gets(node->var);
1956 node->var->type = a_VARUNK;
1957 node->type = _a_ARR_INT;
1958 node->var->type2 = 0;
1959 if (node->key == _a_SPLT_BASESTR || !node->var->ptr)
1960 node->var->allc = malloc( &node->var->ptr, flen+1 );
1961 else if (node->var->allc <= flen)
1962 node->var->allc = realloc( &node->var->ptr, flen+1 );
1963 memcpy(node->var->ptr, str + curlen, flen);
1964 *(node->var->ptr + flen) = '\0';
1965 node->var->slen = flen;
1966 curlen += flen;
1967 }
1968
1969 for (j=i; j<array->nodeno; j++)
1970 {
1971 array->slot[j]->var->slen = 0;
1972 if (array->slot[j]->key == _a_SPLT_BASESTR)
1973 array->slot[j]->var->ptr = nullstr;
1974 else
1975 {
1976 awka_gets(array->slot[j]->var);
1977 array->slot[j]->var->ptr[0] = '\0';
1978 array->slot[j]->var->slen = 0;
1979 }
1980 array->slot[j]->var->dval = 0;
1981 array->slot[j]->var->type2 = 0;
1982 array->slot[j]->var->type = a_VARNUL;
1983 }
1984 array->nodeno = count;
1985 return array->nodeno;
1986 }
1987
1988 /*
1989 * awka_arraysplitstr
1990 * awk builtin 'split' function, here because it is essentially
1991 * an array function. Given a string, splits it into smaller strings
1992 * using fs, then builds a 'split' array to hold them.
1993 */
1994 double
awka_arraysplitstr(char * str,a_VAR * v,a_VAR * fs,int max,char main_split)1995 awka_arraysplitstr( char *str, a_VAR *v, a_VAR *fs, int max, char main_split )
1996 {
1997 register char *ptr;
1998 _a_HSHarray *array;
1999 int i, oldnodeno;
2000 double ret;
2001
2002 /* check arguments */
2003 if (v->type != a_VARARR && v->type != a_VARNUL && !(v->type == a_VARSTR && v->ptr[0] == '\0'))
2004 awka_error("runtime error: Scalar used as array in call to ArraySplitStr\n");
2005
2006 /* Get array ready to populate */
2007 if (v->type == a_VARNUL || v->type == a_VARSTR ||
2008 (v->type == a_VARARR && v->ptr == NULL))
2009 awka_arraycreate( v, a_ARR_TYPE_SPLIT );
2010
2011 if (!fs)
2012 {
2013 if (fs_or_fw && main_split)
2014 {
2015 ret = _awka_arraysplitwidth( str, v, max );
2016 if (ret > -1)
2017 return ret;
2018 fs_or_fw = 0;
2019 }
2020 fs = a_bivar[a_FS];
2021 }
2022
2023 if (fs->type == a_VARARR)
2024 awka_error("runtime error: Array used as scalar in call to ArraySplitStr\n");
2025
2026 if (fs->type == a_VARNUL)
2027 {
2028 fs->allc = malloc( &fs->ptr, 1 );
2029 fs->ptr[0] = '\0';
2030 fs->slen = 0;
2031 fs->type = a_VARSTR;
2032 fs->type2 = 0;
2033 }
2034
2035 array = (_a_HSHarray *) v->ptr;
2036 oldnodeno = array->nodeno;
2037
2038 if (array->nodeno)
2039 {
2040 if (array->type == a_ARR_TYPE_HSH)
2041 {
2042 awka_arrayclear(v);
2043 oldnodeno = 0;
2044 }
2045 else
2046 array->nodeno = 0;
2047 }
2048 array->type = a_ARR_TYPE_SPLIT;
2049
2050 i = strlen(str);
2051 if (!array->splitstr)
2052 array->splitallc = malloc( &array->splitstr, i+1);
2053 else if (array->splitallc < i+1)
2054 array->splitallc = realloc( &array->splitstr, i+1);
2055 memcpy(array->splitstr, str, i+1);
2056
2057 array->type = a_ARR_TYPE_SPLIT;
2058 array->base = 1;
2059
2060 /* split the string */
2061 if (i && fs->type != a_VARREG)
2062 {
2063 ptr = awka_gets1(fs);
2064 if (fs->slen > 1)
2065 _awka_getreval(fs, __FILE__, __LINE__, _RE_SPLIT);
2066 }
2067
2068 if (i && fs->type != a_VARREG)
2069 {
2070 switch (ptr[0])
2071 {
2072 case '\0':
2073 return _awka_split_null(array, max, oldnodeno);
2074 case ' ':
2075 return _awka_split_space(array, max, oldnodeno);
2076 default:
2077 return _awka_split_single_char( array, ptr[0], max, oldnodeno );
2078 }
2079 }
2080 else if (i)
2081 return _awka_splitre( array, fs, max, oldnodeno );
2082 else
2083 return 0.0;
2084 }
2085
2086 a_VAR *
_awka_NF()2087 _awka_NF()
2088 {
2089 if (_rebuildn == TRUE)
2090 {
2091 awka_setd(a_bivar[a_NF]) = awka_arraysplitstr(awka_gets1(a_bivar[a_DOL0]), a_bivar[a_DOLN], a_bivar[a_FS], _split_max, TRUE);
2092 _rebuildn = FALSE;
2093 }
2094 return a_bivar[a_NF];
2095 }
2096
2097 /*
2098 * awka_dol0
2099 * this takes care of accessing & modifying awk $0 variable.
2100 * its here because awka_doln is here
2101 */
2102 a_VAR *
_awka_dol0(int set)2103 _awka_dol0(int set)
2104 {
2105 register int i, j, k, oldlen;
2106 register _a_HSHarray *array;
2107 register char *ptr, *op;
2108 extern int _split_req;
2109 a_HSHNode *node;
2110 register a_VAR *var, *ofs, *dol0;
2111 static char *sformat = NULL;
2112 static int s_allc = 0;
2113
2114 /* $0 accessed */
2115 dol0 = a_bivar[a_DOL0]; ofs = a_bivar[a_OFS];
2116
2117 switch (set)
2118 {
2119 case 1:
2120 if (_rebuild0)
2121 _rebuild0_now = TRUE;
2122 else
2123 _rebuildn = TRUE;
2124 _rebuild0 = FALSE;
2125 _awka_setdol0_len = _awka_setdoln = FALSE;
2126 dol0->type2 = 0;
2127 return dol0;
2128
2129 case 0:
2130 case -1:
2131 if (_rebuildn == TRUE && _split_req)
2132 {
2133 awka_setd(a_bivar[a_NF]) = awka_arraysplitstr(awka_gets1(dol0), a_bivar[a_DOLN], NULL, _split_max, TRUE);
2134 _rebuildn = FALSE;
2135 }
2136 /* fall thru */
2137 default:
2138 array = (_a_HSHarray *) a_bivar[a_DOLN]->ptr;
2139 /* if ((_awka_setdol0_len == TRUE || _rebuild0 || _rebuild0_now) && set != -1) // last seen in 0.5.8 */
2140 if ((_rebuild0 || _rebuild0_now) && set != -1)
2141 {
2142 if (awka_getd1(a_bivar[a_NF])) /* have to rebuild $0 from $n */
2143 {
2144 if (a_bivar[a_NF]->dval > array->nodeno)
2145 {
2146 /* Have to extend $n array to match NF */
2147 j = (int) a_bivar[a_NF]->dval;
2148 if (j > array->nodeallc)
2149 {
2150 if (!array->slot)
2151 malloc( &array->slot, j * sizeof(a_HSHNode *) );
2152 else
2153 realloc( &array->slot, j * sizeof(a_HSHNode *) );
2154 }
2155
2156 for (i=array->nodeno; i<j; i++)
2157 {
2158 if (i >= array->nodeallc)
2159 {
2160 malloc( &node, sizeof(a_HSHNode));
2161 malloc( &node->var, sizeof(a_VAR));
2162 array->slot[i] = node;
2163 _awka_hshinitnode(node);
2164 node->var->type = a_VARUNK;
2165 node->key = _a_SPLT_BASESTR;
2166 node->var->ptr = nullstr;
2167 }
2168 else if (array->slot[i]->key == _a_SPLT_LOCALSTR)
2169 {
2170 if (!array->slot[i]->var->ptr)
2171 {
2172 array->slot[i]->var->allc = malloc( &array->slot[i]->var->ptr, 1 );
2173 array->slot[i]->var->ptr[0] = '\0';
2174 }
2175 }
2176 else
2177 array->slot[i]->var->ptr = nullstr;
2178 array->slot[i]->var->type2 = 0;
2179 array->slot[i]->var->dval = 0.0;
2180 array->slot[i]->var->slen = 0;
2181 }
2182 array->nodeallc = (j > array->nodeallc ? j : array->nodeallc);
2183 array->nodeno = j;
2184 }
2185
2186 /* rebuild $0 */
2187 awka_forcestr(dol0);
2188 awka_forcestr(ofs);
2189 var = array->slot[0]->var;
2190 ptr = awka_gets1(var);
2191 k = (int) A_MIN(array->nodeno, a_bivar[a_NF]->dval);
2192 j = var->slen + (k * 50) + 1;
2193 if (j >= dol0->allc)
2194 {
2195 if (dol0->ptr)
2196 dol0->allc = realloc( &dol0->ptr, j+1 );
2197 else
2198 dol0->allc = malloc( &dol0->ptr, j+1 );
2199 }
2200 op = dol0->ptr;
2201
2202 if (!fs_or_fw || *(awka_gets(a_bivar[a_SAVEWIDTHS])) == '\0')
2203 {
2204 /* no SAVEWIDTHS - rebuild according to OFS */
2205 rebuild_normal:
2206 memcpy(dol0->ptr, ptr, var->slen+1);
2207 op += var->slen;
2208 oldlen = var->slen;
2209 for (i=1; i<k; i++)
2210 {
2211 var = array->slot[i]->var;
2212 if (array->slot[i]->key == _a_SPLT_BASESTR &&
2213 var->type != a_VARUNK && var->type != a_VARNUL)
2214 {
2215 array->slot[i]->key = _a_SPLT_LOCALSTR;
2216 }
2217 ptr = awka_gets1(var);
2218 j += var->slen + ofs->slen;
2219 if (j >= dol0->allc)
2220 {
2221 dol0->allc = realloc( &dol0->ptr, j+1 );
2222 op = dol0->ptr + oldlen;
2223 }
2224 memcpy(op, ofs->ptr, ofs->slen);
2225 op += ofs->slen;
2226 memcpy(op, ptr, var->slen+1);
2227 op += var->slen;
2228 oldlen += var->slen + ofs->slen;
2229 }
2230 dol0->slen = _awka_dol0_len = oldlen;
2231 dol0->type = a_VARUNK;
2232
2233 if (k <= 1 && j == 0)
2234 {
2235 dol0->ptr[0] = '\0';
2236 _awka_dol0_len = dol0->slen = 0;
2237 }
2238 }
2239 else
2240 {
2241 /* SAVEWIDTHS in operation */
2242 if (!sformat || strcmp(sformat, a_bivar[a_SAVEWIDTHS]->ptr))
2243 {
2244 if (!sformat)
2245 s_allc = malloc(&sformat, a_bivar[a_SAVEWIDTHS]->slen+1);
2246 else if (s_allc <= a_bivar[a_SAVEWIDTHS]->slen)
2247 s_allc = realloc(&sformat, a_bivar[a_SAVEWIDTHS]->slen+1);
2248 strcpy(sformat, a_bivar[a_SAVEWIDTHS]->ptr);
2249 _awka_parse_width_format(sformat, FALSE);
2250 }
2251 if (!sw_used) goto rebuild_normal; /* real men use gotos */
2252 j = (var->slen > sw_loc[0] ? sw_loc[0] : var->slen);
2253 if (j + ofs->slen >= dol0->allc)
2254 {
2255 dol0->allc = realloc( &dol0->ptr, j+ofs->slen+1 );
2256 op = dol0->ptr;
2257 }
2258 memcpy(dol0->ptr, ptr, j);
2259 op += j;
2260 if (sw_used && j < sw_loc[0])
2261 {
2262 memset(op, ' ', sw_loc[0] - j);
2263 op += sw_loc[0] - j;
2264 }
2265
2266 for (i=1; i<k; i++)
2267 {
2268 var = array->slot[i]->var;
2269 if (i >= sw_used)
2270 {
2271 memcpy(op, ofs->ptr, ofs->slen);
2272 op += ofs->slen;
2273 j = var->slen;
2274 }
2275 else
2276 j = (var->slen > sw_loc[i]) ? sw_loc[i] : var->slen;
2277 ptr = awka_gets1(var);
2278 oldlen = op - dol0->ptr;
2279
2280 if (j + ofs->slen + oldlen >= dol0->allc)
2281 {
2282 dol0->allc = realloc( &dol0->ptr, j + ofs->slen + oldlen + 1 );
2283 op = dol0->ptr + oldlen;
2284 }
2285
2286 memcpy(op, ptr, j);
2287 op += j;
2288 if (i < sw_used && j < sw_loc[i])
2289 {
2290 memset(op, ' ', sw_loc[i] - j);
2291 op += sw_loc[i] - j;
2292 }
2293 }
2294 *op = '\0';
2295 dol0->slen = op - dol0->ptr;
2296 }
2297 }
2298 else
2299 {
2300 awka_forcestr(dol0);
2301 dol0->ptr[0] = '\0';
2302 dol0->type = a_VARUNK;
2303 _awka_dol0_len = dol0->slen = 0;
2304 }
2305
2306 _awka_setdol0_len = _awka_setdoln = _rebuild0 = _rebuild0_now = FALSE;
2307 }
2308
2309 if (set == 2)
2310 {
2311 _rebuild0 = _rebuild0_now = FALSE;
2312 _awka_setdol0_len = _awka_setdoln = FALSE;
2313 _rebuildn = TRUE;
2314 }
2315 return dol0;
2316 }
2317 }
2318
2319 /*
2320 * awka_doln
2321 * this takes care of accessing & modifying awk $n variables.
2322 * its here because the field array is an array.
2323 */
2324 a_VAR *
awka_doln(int idx,int set)2325 awka_doln(int idx, int set)
2326 {
2327 static char *x;
2328 register int i, j, nf = (int) awka_NFget()->dval;
2329 _a_HSHarray *array = (_a_HSHarray *) a_bivar[a_DOLN]->ptr;
2330 static a_VAR *nullvar = NULL;
2331 extern int _split_req;
2332 a_HSHNode *node;
2333
2334 if (!idx)
2335 return awka_dol0(set);
2336
2337 if (!nullvar)
2338 {
2339 malloc( &nullvar, sizeof(a_VAR) );
2340 nullvar->allc = malloc( &nullvar->ptr, 1 );
2341 nullvar->ptr[0] = '\0';
2342 nullvar->slen = 0;
2343 nullvar->type = a_VARUNK;
2344 nullvar->temp = nullvar->type2 = 0;
2345 nullvar->dval = 0.0;
2346 }
2347
2348 if (_rebuildn == TRUE)
2349 {
2350 awka_setd(a_bivar[a_NF]) = awka_arraysplitstr(awka_gets1(a_bivar[a_DOL0]), a_bivar[a_DOLN], a_bivar[a_FS], _split_max, TRUE);
2351 nf = (int) a_bivar[a_NF]->dval;
2352 array = (_a_HSHarray *) a_bivar[a_DOLN]->ptr;
2353 _rebuildn = FALSE;
2354 }
2355
2356 idx--;
2357 if (idx < 0)
2358 awka_error("awka_doln: field variable referenced with negative index.\n");
2359
2360 switch (set)
2361 {
2362 case 0:
2363 /* if (idx >= array->nodeno) */
2364 if (idx >= nf || idx >= array->nodeno)
2365 return nullvar;
2366 break;
2367
2368 default:
2369 _rebuild0 = TRUE;
2370 _awka_setdoln = TRUE;
2371
2372 /* if (idx >= array->nodeno) */
2373 if (idx >= nf || idx >= array->nodeno)
2374 {
2375 /* extend field array */
2376 array->nodeno = (array->nodeno > nf ? nf : array->nodeno);
2377 j = idx+1;
2378 if (j > array->nodeallc)
2379 {
2380 realloc( &array->slot, j * sizeof(a_HSHNode *) );
2381 array->nodeallc = j;
2382 }
2383
2384 for (i=array->nodeno; i<j; i++)
2385 {
2386 malloc( &node, sizeof(a_HSHNode));
2387 malloc( &node->var, sizeof(a_VAR));
2388 _awka_hshinitnode(node);
2389 node->key = _a_SPLT_LOCALSTR;
2390 node->var->type = a_VARUNK;
2391 node->var->type2 = 0;
2392 node->var->dval = 0.0;
2393 node->var->allc = malloc( &node->var->ptr, 1 );
2394 node->var->ptr[0] = '\0';
2395 node->var->slen = 0;
2396 array->slot[i] = node;
2397 }
2398 array->nodeno = j;
2399 awka_setd(a_bivar[a_NF]) = j;
2400 }
2401 break;
2402 }
2403
2404 if (set == 0 || array->slot[idx]->key == _a_SPLT_LOCALSTR)
2405 return array->slot[idx]->var;
2406
2407 if (array->slot[idx]->var->type == a_VARUNK ||
2408 array->slot[idx]->var->type == a_VARSTR)
2409 {
2410 array->slot[idx]->var->allc = malloc( &x, array->slot[idx]->var->slen + 1);
2411 strcpy(x, array->slot[idx]->var->ptr);
2412 array->slot[idx]->var->ptr = x;
2413 }
2414 else
2415 array->slot[idx]->var->ptr = NULL;
2416 array->slot[idx]->key = _a_SPLT_LOCALSTR;
2417 return array->slot[idx]->var;
2418 }
2419
2420 /*
2421 * awka_alistcmp
2422 * compares two nodes to see which is higher in sort order
2423 */
2424 static INLINE int
_awka_alistcmp(a_HSHNode * node1,a_HSHNode * node2,int sorttype)2425 _awka_alistcmp(a_HSHNode *node1, a_HSHNode *node2, int sorttype)
2426 {
2427 char tmp[96], tmp2[96];
2428
2429 if (sorttype & 2)
2430 {
2431 /* Numeric Sort */
2432 if (node1->type == _a_ARR_INT && node2->type == _a_ARR_STR)
2433 {
2434 if (node1->hval == atoi(node2->key)) return 0;
2435 if (sorttype & 4)
2436 return (node1->hval > atoi(node2->key) ? -1 : 1);
2437 return (node1->hval < atoi(node2->key) ? -1 : 1);
2438 }
2439
2440 if (node1->type == _a_ARR_STR && node2->type == _a_ARR_INT)
2441 {
2442 if (atoi(node1->key) == node2->hval) return 0;
2443 if (sorttype & 4)
2444 return (atoi(node1->key) > node2->hval ? -1 : 1);
2445 return (atoi(node1->key) < node2->hval ? -1 : 1);
2446 }
2447
2448 if (node1->type == _a_ARR_INT && node2->type == _a_ARR_INT)
2449 {
2450 if (node1->hval == node2->hval) return 0;
2451 if (sorttype & 4)
2452 return (node1->hval > node2->hval ? -1 : 1);
2453 return (node1->hval < node2->hval ? -1 : 1);
2454 }
2455
2456 if (sorttype & 4)
2457 return (atoi(node1->key) > atoi(node2->key) ? -1 : 1);
2458 return (atoi(node1->key) < atoi(node2->key) ? -1 : 1);
2459 }
2460 else
2461 {
2462 /* Alphabetical Sort */
2463 if (node1->type == _a_ARR_INT && node2->type == _a_ARR_STR)
2464 {
2465 sprintf(tmp, "%d", node1->hval);
2466 if (sorttype & 4)
2467 return strcmp(node2->key, tmp);
2468 return strcmp(tmp, node2->key);
2469 }
2470
2471 if (node1->type == _a_ARR_STR && node2->type == _a_ARR_INT)
2472 {
2473 sprintf(tmp, "%d", node2->hval);
2474 if (sorttype & 4)
2475 return strcmp(tmp, node1->key);
2476 return strcmp(node1->key, tmp);
2477 }
2478
2479 if (node1->type == _a_ARR_INT && node2->type == _a_ARR_INT)
2480 {
2481 if (node1->hval == node2->hval) return 0;
2482 sprintf(tmp, "%d", node1->hval);
2483 sprintf(tmp2, "%d", node2->hval);
2484 if (sorttype & 4)
2485 return strcmp(node2->key, node1->key);
2486 return strcmp(node1->key, node2->key);
2487 }
2488
2489 if (sorttype & 4)
2490 return strcmp(node2->key, node1->key);
2491 return strcmp(node1->key, node2->key);
2492 }
2493 }
2494
2495 #define QSWAP(a, b) \
2496 node = a; \
2497 a = b; \
2498 b = node
2499
2500 /*
2501 * awka_qsort
2502 * provides a sorted 'for (people in trains)' list
2503 */
2504 void
_awka_qsort(a_HSHNode ** nlist,int hi,int sorttype)2505 _awka_qsort(a_HSHNode **nlist, int hi, int sorttype)
2506 {
2507 unsigned i, j, ln, rn;
2508 a_HSHNode *node;
2509
2510 while (hi > 1)
2511 {
2512 QSWAP(nlist[0], nlist[hi/2]);
2513 for (i = 0, j = hi; ; )
2514 {
2515 do
2516 if (--j > hi) { j++; break; }
2517 while (_awka_alistcmp(nlist[j], nlist[0], sorttype) > 0);
2518
2519 do
2520 if (++i >= hi) { i--; break; }
2521 while (i < j && _awka_alistcmp(nlist[i], nlist[0], sorttype) < 0);
2522
2523 if (i >= j)
2524 break;
2525 QSWAP(nlist[i], nlist[j]);
2526 }
2527 QSWAP(nlist[j], nlist[0]);
2528 ln = j;
2529 rn = hi - ++j;
2530 if (ln < rn)
2531 {
2532 _awka_qsort(nlist, ln, sorttype);
2533 nlist += j;
2534 hi = rn;
2535 }
2536 else
2537 {
2538 _awka_qsort(nlist + j, rn, sorttype);
2539 hi = ln;
2540 }
2541 }
2542 }
2543
2544 /*
2545 * awka_arrayloop
2546 * for implementation of awk 'for (people in trains)' loops.
2547 * Calling function responsible for freeing returned array.
2548 */
2549 int
awka_arrayloop(a_ListHdr * ah,a_VAR * v,char asort)2550 awka_arrayloop( a_ListHdr *ah, a_VAR *v, char asort )
2551 {
2552 a_List *alist;
2553 int i=0, j, sorttype = 0;
2554 _a_HSHarray *array;
2555 a_HSHNode *node;
2556
2557 if (v->type != a_VARARR)
2558 awka_error("runtime error: Scalar used as array in call to ArrayLoop\n");
2559 array = (_a_HSHarray *) v->ptr;
2560
2561 sorttype = awka_getd(a_bivar[a_SORTTYPE]);
2562
2563 if (ah->used == ah->allc)
2564 {
2565 if (ah->allc == 0)
2566 malloc( &ah->list, 5 * sizeof(a_List));
2567 else
2568 realloc( &ah->list, (ah->allc + 5) * sizeof(a_List));
2569 ah->allc += 5;
2570 }
2571 alist = &(ah->list[ah->used++]);
2572
2573 if (!array)
2574 {
2575 malloc( &alist->node, sizeof(a_HSHNode *));
2576 alist->node[0] = 0;
2577 alist->type = a_ARR_TYPE_HSH;
2578 return 0;
2579 }
2580
2581 malloc( &alist->node, (array->nodeno+1) * sizeof(a_HSHNode *) );
2582 alist->type = array->type;
2583 alist->base = array->base;
2584 alist->nodeno = array->nodeno;
2585
2586 if (array->type == a_ARR_TYPE_HSH)
2587 {
2588 for (j=0, i=0; j<=array->hashmask; j++)
2589 {
2590 node = array->slot[j];
2591 while (node)
2592 {
2593 if (node->shadow == FALSE)
2594 alist->node[i++] = node;
2595 node = node->next;
2596 }
2597 }
2598
2599 if (sorttype && i > 1)
2600 _awka_qsort(alist->node, i, sorttype);
2601 else if (asort && i > 1)
2602 _awka_qsort(alist->node, i, 1);
2603 }
2604 else
2605 {
2606 /* split array */
2607 for (i=0; i<array->nodeno; i++)
2608 alist->node[i] = array->slot[i];
2609 }
2610
2611 alist->node[i] = NULL;
2612 return 0;
2613 }
2614
2615 /*
2616 * awka_arraynext
2617 * gets next node in a 'for (people in trains)' loops.
2618 */
2619 int
awka_arraynext(a_VAR * v,a_ListHdr * ah,int pos)2620 awka_arraynext( a_VAR *v, a_ListHdr *ah, int pos )
2621 {
2622 a_List *alist = &(ah->list[ah->used-1]);
2623
2624 switch (alist->type)
2625 {
2626 case a_ARR_TYPE_HSH:
2627 if (pos >= alist->nodeno || alist->node[pos] == NULL)
2628 return 0;
2629
2630 if (v->type == a_VARARR)
2631 awka_error("runtime error: Array used as scalar in call to ArrayNext.\n");
2632
2633 if (alist->node[pos]->type == _a_ARR_INT)
2634 awka_setd(v) = (double) ((int) alist->node[pos]->hval);
2635 else
2636 awka_strcpy(v, alist->node[pos]->key);
2637 break;
2638
2639 case a_ARR_TYPE_SPLIT:
2640 if (pos >= alist->nodeno || alist->node[pos] == NULL)
2641 return 0;
2642
2643 if (v->type != a_VARDBL)
2644 _awka_setdval(v, __FILE__, __LINE__);
2645
2646 v->dval = pos + alist->base;
2647 break;
2648
2649 default:
2650 return 0;
2651 }
2652
2653 return pos+1;
2654 }
2655
2656 void
awka_alistfree(a_ListHdr * ah)2657 awka_alistfree( a_ListHdr *ah )
2658 {
2659 a_List *alist;
2660 alist = &(ah->list[--ah->used]);
2661
2662 if (alist->node)
2663 free(alist->node);
2664 }
2665
2666 void
awka_alistfreeall(a_ListHdr * ah)2667 awka_alistfreeall( a_ListHdr *ah )
2668 {
2669 int i;
2670
2671 if (ah->list)
2672 {
2673 for (i=0; i<ah->used; i++)
2674 if (ah->list[i].node)
2675 free(ah->list[i].node);
2676
2677 free(ah->list);
2678 }
2679 ah->used = ah->allc = 0;
2680 ah->list = NULL;
2681 }
2682
2683 /*
2684 * asort() - gawk 3.1.0 array sorting function
2685 * sorts src. If dest==NULL, overwrites src's indexes
2686 * with numbers indicating position in sort order starting
2687 * from 1. Otherwise copies src into dest with new index.
2688 * returns number of elements in src.
2689 */
2690 double
awka_asort(a_VAR * src,a_VAR * dest)2691 awka_asort( a_VAR *src, a_VAR *dest )
2692 {
2693 a_ListHdr listhdr;
2694 double ret = (double) ((_a_HSHarray *) src->ptr)->nodeno;
2695 _a_HSHarray *array;
2696 a_VAR *ivar = NULL, *newnode, *idxvar;
2697 int idx, nodest = 0;
2698
2699 listhdr.allc = listhdr.used = 0;
2700 listhdr.list = NULL;
2701 awka_varinit(ivar);
2702 awka_varinit(idxvar);
2703
2704 /* make a sorted list of pointers to array elements */
2705 awka_arrayloop( &listhdr, src, 1 );
2706
2707 /* make sure dest is ready to receive the new array */
2708 if (dest)
2709 awka_arrayclear( dest );
2710 else
2711 {
2712 awka_varinit( dest );
2713 dest->type = a_VARARR;
2714 nodest = 1;
2715 }
2716 array = (_a_HSHarray *) dest->ptr;
2717 if (array)
2718 array->type = a_ARR_TYPE_SPLIT;
2719 else
2720 awka_arraycreate( dest, a_ARR_TYPE_SPLIT );
2721
2722 /* kludgy hack. but easily coded and understood ;-)
2723 * this iterates through src and inserts each element
2724 * into dest, using the index in the sorted loop as
2725 * the array index */
2726 for ( idx=0; (idx = awka_arraynext(ivar, &listhdr, idx)) > 0; )
2727 {
2728 awka_vardblset( idxvar, (double) idx );
2729 newnode = awka_arraysearch1( dest, idxvar, a_ARR_CREATE, 0 );
2730 awka_varcpy( newnode, awka_arraysearch1( src, ivar, a_ARR_CREATE, 0 ) );
2731 }
2732 awka_alistfree( &listhdr );
2733
2734 if (nodest)
2735 {
2736 /* oops, dest not provided. We kill src and make it dest. */
2737 awka_killvar( src );
2738 src->dval = dest->dval;
2739 src->ptr = dest->ptr;
2740 src->slen = dest->slen;
2741 src->allc = dest->allc;
2742 src->type = dest->type;
2743 src->type2 = dest->type2;
2744 src->temp = dest->temp;
2745 }
2746
2747 return ret;
2748 }
2749
2750