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