1 /* $Header: dolist.c,v 3.0.1.12 91/01/11 17:54:58 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.12 91/01/11 17:54:58 lwall
10 * patch42: added binary and hex pack/unpack options
11 * patch42: sort subroutines didn't allow copying $a or $b to other variables.
12 * patch42: caller() coredumped when called outside the debugger.
14 * Revision 3.0.1.11 90/11/10 01:29:49 lwall
15 * patch38: temp string values are now copied less often
16 * patch38: sort parameters are now in the right package
18 * Revision 3.0.1.10 90/10/15 16:19:48 lwall
19 * patch29: added caller
20 * patch29: added scalar reverse
21 * patch29: sort undefined_subroutine @array is now a fatal error
23 * Revision 3.0.1.9 90/08/13 22:15:35 lwall
24 * patch28: defined(@array) and defined(%array) didn't work right
26 * Revision 3.0.1.8 90/08/09 03:15:56 lwall
27 * patch19: certain kinds of matching cause "panic: hint"
28 * patch19: $' broke on embedded nulls
29 * patch19: split on /\s+/, /^/ and ' ' is now special cased for speed
30 * patch19: split on /x/i didn't work
31 * patch19: couldn't unpack an 'A' or 'a' field in a scalar context
32 * patch19: unpack called bcopy on each character of a C/c field
33 * patch19: pack/unpack know about uudecode lines
34 * patch19: fixed sort on undefined strings and sped up slightly
35 * patch19: each and keys returned garbage on null key in DBM file
37 * Revision 3.0.1.7 90/03/27 15:48:42 lwall
38 * patch16: MSDOS support
39 * patch16: use of $`, $& or $' sometimes causes memory leakage
40 * patch16: splice(@array,0,$n) case cause duplicate free
41 * patch16: grep blows up on undefined array values
42 * patch16: .. now works using magical string increment
44 * Revision 3.0.1.6 90/03/12 16:33:02 lwall
45 * patch13: added list slice operator (LIST)[LIST]
46 * patch13: added splice operator: @oldelems = splice(@array,$offset,$len,LIST)
47 * patch13: made split('') act like split(//) rather than split(' ')
49 * Revision 3.0.1.5 90/02/28 17:09:44 lwall
50 * patch9: split now can split into more than 10000 elements
51 * patch9: @_ clobbered by ($foo,$bar) = split
52 * patch9: sped up pack and unpack
53 * patch9: unpack of single item now works in a scalar context
54 * patch9: slices ignored value of $[
55 * patch9: grep now returns number of items matched in scalar context
56 * patch9: grep iterations no longer in the regexp context of previous iteration
58 * Revision 3.0.1.4 89/12/21 19:58:46 lwall
59 * patch7: grep(1,@array) didn't work
60 * patch7: /$pat/; //; wrongly freed runtime pattern twice
62 * Revision 3.0.1.3 89/11/17 15:14:45 lwall
63 * patch5: grep() occasionally loses arguments or dumps core
65 * Revision 3.0.1.2 89/11/11 04:28:17 lwall
66 * patch2: non-existent slice values are now undefined rather than null
68 * Revision 3.0.1.1 89/10/26 23:11:51 lwall
69 * patch1: split in a subroutine wrongly freed referenced arguments
70 * patch1: reverse didn't work
72 * Revision 3.0 89/10/18 15:11:02 lwall
82 #pragma function(memcmp)
83 #endif /* BUGGY_MSC */
86 do_match(str,arg,gimme,arglast)
92 register STR **st = stack->ary_array;
93 register SPAT *spat = arg[2].arg_ptr.arg_spat;
95 register int sp = arglast[0] + 1;
96 STR *srchstr = st[sp];
97 register char *s = str_get(st[sp]);
98 char *strend = s + st[sp]->str_cur;
104 if (gimme == G_ARRAY)
112 fatal("panic: do_match");
113 if (spat->spat_flags & SPAT_USED) {
116 deb("2.SPAT USED\n");
118 if (gimme == G_ARRAY)
126 if (spat->spat_runtime) {
128 sp = eval(spat->spat_runtime,G_SCALAR,sp);
129 st = stack->ary_array;
130 t = str_get(tmpstr = st[sp--]);
134 deb("2.SPAT /%s/\n",t);
136 if (spat->spat_regexp)
137 regfree(spat->spat_regexp);
138 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
139 spat->spat_flags & SPAT_FOLD);
140 if (!*spat->spat_regexp->precomp && lastspat)
142 if (spat->spat_flags & SPAT_KEEP) {
143 if (spat->spat_runtime)
144 arg_free(spat->spat_runtime); /* it won't change, so */
145 spat->spat_runtime = Nullarg; /* no point compiling again */
147 if (!spat->spat_regexp->nparens)
148 gimme = G_SCALAR; /* accidental array context? */
149 if (regexec(spat->spat_regexp, s, strend, s, 0,
150 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
152 if (spat->spat_regexp->subbase)
158 if (gimme == G_ARRAY)
160 str_sset(str,&str_no);
171 if (spat->spat_flags & SPAT_ONCE)
175 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
178 if (!*spat->spat_regexp->precomp && lastspat)
182 if (myhint < s || myhint > strend)
183 fatal("panic: hint in do_match");
185 if (spat->spat_regexp->regback >= 0) {
186 s -= spat->spat_regexp->regback;
193 else if (spat->spat_short) {
194 if (spat->spat_flags & SPAT_SCANFIRST) {
195 if (srchstr->str_pok & SP_STUDIED) {
196 if (screamfirst[spat->spat_short->str_rare] < 0)
198 else if (!(s = screaminstr(srchstr,spat->spat_short)))
200 else if (spat->spat_flags & SPAT_ALL)
204 else if (!(s = fbminstr((unsigned char*)s,
205 (unsigned char*)strend, spat->spat_short)))
208 else if (spat->spat_flags & SPAT_ALL)
210 if (s && spat->spat_regexp->regback >= 0) {
211 ++spat->spat_short->str_u.str_useful;
212 s -= spat->spat_regexp->regback;
219 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
220 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
222 if (--spat->spat_short->str_u.str_useful < 0) {
223 str_free(spat->spat_short);
224 spat->spat_short = Nullstr; /* opt is being useless */
227 if (!spat->spat_regexp->nparens)
228 gimme = G_SCALAR; /* accidental array context? */
229 if (regexec(spat->spat_regexp, s, strend, t, 0,
230 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
232 if (spat->spat_regexp->subbase)
235 if (spat->spat_flags & SPAT_ONCE)
236 spat->spat_flags |= SPAT_USED;
240 if (gimme == G_ARRAY)
242 str_sset(str,&str_no);
251 if (gimme == G_ARRAY) {
254 iters = spat->spat_regexp->nparens;
255 if (sp + iters >= stack->ary_max) {
256 astore(stack,sp + iters, Nullstr);
257 st = stack->ary_array; /* possibly realloced */
260 for (i = 1; i <= iters; i++) {
261 st[++sp] = str_static(&str_no);
262 if (s = spat->spat_regexp->startp[i]) {
263 len = spat->spat_regexp->endp[i] - s;
265 str_nset(st[sp],s,len);
271 str_sset(str,&str_yes);
278 ++spat->spat_short->str_u.str_useful;
280 if (spat->spat_flags & SPAT_ONCE)
281 spat->spat_flags |= SPAT_USED;
285 if (spat->spat_regexp->subbase)
286 Safefree(spat->spat_regexp->subbase);
287 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
288 spat->spat_regexp->subend = tmps + (strend-t);
289 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
290 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
293 str_sset(str,&str_yes);
299 ++spat->spat_short->str_u.str_useful;
300 if (gimme == G_ARRAY)
302 str_sset(str,&str_no);
309 #pragma intrinsic(memcmp)
310 #endif /* BUGGY_MSC */
313 do_split(str,spat,limit,gimme,arglast)
320 register ARRAY *ary = stack;
321 STR **st = ary->ary_array;
322 register int sp = arglast[0] + 1;
323 register char *s = str_get(st[sp]);
324 char *strend = s + st[sp--]->str_cur;
328 int maxiters = (strend - s) + 10;
331 int origlimit = limit;
335 fatal("panic: do_split");
336 else if (spat->spat_runtime) {
338 sp = eval(spat->spat_runtime,G_SCALAR,sp);
339 st = stack->ary_array;
340 m = str_get(dstr = st[sp--]);
342 if (*m == ' ' && dstr->str_cur == 1) {
343 str_set(dstr,"\\s+");
345 spat->spat_flags |= SPAT_SKIPWHITE;
347 if (spat->spat_regexp)
348 regfree(spat->spat_regexp);
349 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
350 spat->spat_flags & SPAT_FOLD);
351 if (spat->spat_flags & SPAT_KEEP ||
352 (spat->spat_runtime->arg_type == O_ITEM &&
353 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
354 arg_free(spat->spat_runtime); /* it won't change, so */
355 spat->spat_runtime = Nullarg; /* no point compiling again */
360 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
363 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
364 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
366 if (!(ary->ary_flags & ARF_REAL)) {
367 ary->ary_flags |= ARF_REAL;
368 for (i = ary->ary_fill; i >= 0; i--)
369 ary->ary_array[i] = Nullstr; /* don't free mere refs */
372 sp = -1; /* temporarily switch stacks */
377 if (spat->spat_flags & SPAT_SKIPWHITE) {
382 limit = maxiters + 2;
383 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
385 for (m = s; m < strend && !isspace(*m); m++) ;
388 dstr = Str_new(30,m-s);
389 str_nset(dstr,s,m-s);
392 (void)astore(ary, ++sp, dstr);
393 for (s = m + 1; s < strend && isspace(*s); s++) ;
396 else if (strEQ("^",spat->spat_regexp->precomp)) {
398 for (m = s; m < strend && *m != '\n'; m++) ;
402 dstr = Str_new(30,m-s);
403 str_nset(dstr,s,m-s);
406 (void)astore(ary, ++sp, dstr);
410 else if (spat->spat_short) {
411 i = spat->spat_short->str_cur;
413 int fold = (spat->spat_flags & SPAT_FOLD);
415 i = *spat->spat_short->str_ptr;
416 if (fold && isupper(i))
421 m < strend && *m != i &&
422 (!isupper(*m) || tolower(*m) != i);
427 for (m = s; m < strend && *m != i; m++) ;
430 dstr = Str_new(30,m-s);
431 str_nset(dstr,s,m-s);
434 (void)astore(ary, ++sp, dstr);
440 while (s < strend && --limit &&
441 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
445 dstr = Str_new(31,m-s);
446 str_nset(dstr,s,m-s);
449 (void)astore(ary, ++sp, dstr);
455 maxiters += (strend - s) * spat->spat_regexp->nparens;
456 while (s < strend && --limit &&
457 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
458 if (spat->spat_regexp->subbase
459 && spat->spat_regexp->subbase != orig) {
462 orig = spat->spat_regexp->subbase;
464 strend = s + (strend - m);
466 m = spat->spat_regexp->startp[0];
467 dstr = Str_new(32,m-s);
468 str_nset(dstr,s,m-s);
471 (void)astore(ary, ++sp, dstr);
472 if (spat->spat_regexp->nparens) {
473 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
474 s = spat->spat_regexp->startp[i];
475 m = spat->spat_regexp->endp[i];
476 dstr = Str_new(33,m-s);
477 str_nset(dstr,s,m-s);
480 (void)astore(ary, ++sp, dstr);
483 s = spat->spat_regexp->endp[0];
489 iters = sp - arglast[0];
490 if (iters > maxiters)
492 if (s < strend || origlimit) { /* keep field after final delim? */
493 dstr = Str_new(34,strend-s);
494 str_nset(dstr,s,strend-s);
497 (void)astore(ary, ++sp, dstr);
502 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
509 zaps = str_get(afetch(ary,sp,FALSE));
513 while (iters > 0 && (!zapb)) {
516 zaps = str_get(afetch(ary,iters-1,FALSE));
524 if (gimme == G_ARRAY) {
526 astore(stack, arglast[0] + 1 + sp, Nullstr);
527 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
528 return arglast[0] + sp;
532 if (gimme == G_ARRAY)
536 str_numset(str,(double)iters);
543 do_unpack(str,gimme,arglast)
548 STR **st = stack->ary_array;
549 register int sp = arglast[0] + 1;
550 register char *pat = str_get(st[sp++]);
551 register char *s = str_get(st[sp]);
552 char *strend = s + st[sp--]->str_cur;
554 register char *patend = pat + st[sp]->str_cur;
558 static char hexchar[] = "0123456789abcdef";
560 /* These must not be in registers: */
564 unsigned short aushort;
566 unsigned long aulong;
571 unsigned long culong;
574 if (gimme != G_ARRAY) { /* arrange to do first one only */
575 for (patend = pat; !isalpha(*patend); patend++);
576 if (index("aAbBhH", *patend) || *pat == '%') {
578 while (isdigit(*patend) || *patend == '*')
585 while (pat < patend) {
590 else if (*pat == '*') {
591 len = strend - strbeg; /* long enough */
594 else if (isdigit(*pat)) {
596 while (isdigit(*pat))
597 len = (len * 10) + (*pat++ - '0');
600 len = (datumtype != '@');
605 if (len == 1 && pat[-1] != '1')
614 if (len > strend - s)
615 fatal("@ outside of string");
619 if (len > s - strbeg)
620 fatal("X outside of string");
624 if (len > strend - s)
625 fatal("x outside of string");
630 if (len > strend - s)
634 str = Str_new(35,len);
637 if (datumtype == 'A') {
638 aptr = s; /* borrow register */
639 s = str->str_ptr + len - 1;
640 while (s >= str->str_ptr && (!*s || isspace(*s)))
643 str->str_cur = s - str->str_ptr;
644 s = aptr; /* unborrow register */
646 (void)astore(stack, ++sp, str_2static(str));
650 if (pat[-1] == '*' || len > (strend - s) * 8)
651 len = (strend - s) * 8;
652 str = Str_new(35, len + 1);
655 aptr = pat; /* borrow register */
657 if (datumtype == 'b') {
659 for (len = 0; len < aint; len++) {
664 *pat++ = '0' + (bits & 1);
669 for (len = 0; len < aint; len++) {
674 *pat++ = '0' + ((bits & 128) != 0);
678 pat = aptr; /* unborrow register */
679 (void)astore(stack, ++sp, str_2static(str));
683 if (pat[-1] == '*' || len > (strend - s) * 2)
684 len = (strend - s) * 2;
685 str = Str_new(35, len);
688 aptr = pat; /* borrow register */
690 if (datumtype == 'h') {
692 for (len = 0; len < aint; len++) {
697 *pat++ = hexchar[bits & 15];
702 for (len = 0; len < aint; len++) {
707 *pat++ = hexchar[(bits >> 4) & 15];
711 pat = aptr; /* unborrow register */
712 (void)astore(stack, ++sp, str_2static(str));
715 if (len > strend - s)
720 if (aint >= 128) /* fake up signed chars */
728 if (aint >= 128) /* fake up signed chars */
731 str_numset(str,(double)aint);
732 (void)astore(stack, ++sp, str_2static(str));
737 if (len > strend - s)
750 str_numset(str,(double)auint);
751 (void)astore(stack, ++sp, str_2static(str));
756 along = (strend - s) / sizeof(short);
761 bcopy(s,(char*)&ashort,sizeof(short));
768 bcopy(s,(char*)&ashort,sizeof(short));
771 str_numset(str,(double)ashort);
772 (void)astore(stack, ++sp, str_2static(str));
778 along = (strend - s) / sizeof(unsigned short);
783 bcopy(s,(char*)&aushort,sizeof(unsigned short));
784 s += sizeof(unsigned short);
786 if (datumtype == 'n')
787 aushort = ntohs(aushort);
794 bcopy(s,(char*)&aushort,sizeof(unsigned short));
795 s += sizeof(unsigned short);
798 if (datumtype == 'n')
799 aushort = ntohs(aushort);
801 str_numset(str,(double)aushort);
802 (void)astore(stack, ++sp, str_2static(str));
807 along = (strend - s) / sizeof(int);
812 bcopy(s,(char*)&aint,sizeof(int));
815 cdouble += (double)aint;
822 bcopy(s,(char*)&aint,sizeof(int));
825 str_numset(str,(double)aint);
826 (void)astore(stack, ++sp, str_2static(str));
831 along = (strend - s) / sizeof(unsigned int);
836 bcopy(s,(char*)&auint,sizeof(unsigned int));
837 s += sizeof(unsigned int);
839 cdouble += (double)auint;
846 bcopy(s,(char*)&auint,sizeof(unsigned int));
847 s += sizeof(unsigned int);
849 str_numset(str,(double)auint);
850 (void)astore(stack, ++sp, str_2static(str));
855 along = (strend - s) / sizeof(long);
860 bcopy(s,(char*)&along,sizeof(long));
863 cdouble += (double)along;
870 bcopy(s,(char*)&along,sizeof(long));
873 str_numset(str,(double)along);
874 (void)astore(stack, ++sp, str_2static(str));
880 along = (strend - s) / sizeof(unsigned long);
885 bcopy(s,(char*)&aulong,sizeof(unsigned long));
886 s += sizeof(unsigned long);
888 if (datumtype == 'N')
889 aulong = ntohl(aulong);
892 cdouble += (double)aulong;
899 bcopy(s,(char*)&aulong,sizeof(unsigned long));
900 s += sizeof(unsigned long);
903 if (datumtype == 'N')
904 aulong = ntohl(aulong);
906 str_numset(str,(double)aulong);
907 (void)astore(stack, ++sp, str_2static(str));
912 along = (strend - s) / sizeof(char*);
916 if (sizeof(char*) > strend - s)
919 bcopy(s,(char*)&aptr,sizeof(char*));
925 (void)astore(stack, ++sp, str_2static(str));
928 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
931 along = (strend - s) / sizeof(float);
936 bcopy(s, (char *)&afloat, sizeof(float));
943 bcopy(s, (char *)&afloat, sizeof(float));
945 str = Str_new(47, 0);
946 str_numset(str, (double)afloat);
947 (void)astore(stack, ++sp, str_2static(str));
953 along = (strend - s) / sizeof(double);
958 bcopy(s, (char *)&adouble, sizeof(double));
965 bcopy(s, (char *)&adouble, sizeof(double));
967 str = Str_new(48, 0);
968 str_numset(str, (double)adouble);
969 (void)astore(stack, ++sp, str_2static(str));
974 along = (strend - s) * 3 / 4;
975 str = Str_new(42,along);
976 while (s < strend && *s > ' ' && *s < 'a') {
981 len = (*s++ - ' ') & 077;
983 if (s < strend && *s >= ' ')
984 a = (*s++ - ' ') & 077;
987 if (s < strend && *s >= ' ')
988 b = (*s++ - ' ') & 077;
991 if (s < strend && *s >= ' ')
992 c = (*s++ - ' ') & 077;
995 if (s < strend && *s >= ' ')
996 d = (*s++ - ' ') & 077;
999 hunk[0] = a << 2 | b >> 4;
1000 hunk[1] = b << 4 | c >> 2;
1001 hunk[2] = c << 6 | d;
1002 str_ncat(str,hunk, len > 3 ? 3 : len);
1007 else if (s[1] == '\n') /* possible checksum byte */
1010 (void)astore(stack, ++sp, str_2static(str));
1014 str = Str_new(42,0);
1015 if (index("fFdD", datumtype) ||
1016 (checksum > 32 && index("iIlLN", datumtype)) ) {
1021 while (checksum >= 16) {
1025 while (checksum >= 4) {
1031 along = (1 << checksum) - 1;
1032 while (cdouble < 0.0)
1034 cdouble = modf(cdouble / adouble, &trouble) * adouble;
1035 str_numset(str,cdouble);
1038 along = (1 << checksum) - 1;
1039 culong &= (unsigned long)along;
1040 str_numset(str,(double)culong);
1042 (void)astore(stack, ++sp, str_2static(str));
1050 do_slice(stab,str,numarray,lval,gimme,arglast)
1058 register STR **st = stack->ary_array;
1059 register int sp = arglast[1];
1060 register int max = arglast[2];
1061 register char *tmps;
1063 register int magic = 0;
1064 register ARRAY *ary;
1065 register HASH *hash;
1066 int oldarybase = arybase;
1069 if (numarray == 2) { /* a slice of a LIST */
1071 ary->ary_fill = arglast[3];
1073 st[sp] = str; /* make stack size available */
1074 str_numset(str,(double)(sp - 1));
1077 ary = stab_array(stab); /* a slice of an array */
1081 if (stab == envstab)
1083 else if (stab == sigstab)
1086 else if (stab_hash(stab)->tbl_dbm)
1088 #endif /* SOME_DBM */
1090 hash = stab_hash(stab); /* a slice of an associative array */
1093 if (gimme == G_ARRAY) {
1097 st[sp-1] = afetch(ary,
1098 ((int)str_gnum(st[sp])) - arybase, lval);
1101 st[sp-1] = &str_undef;
1107 tmps = str_get(st[sp]);
1108 len = st[sp]->str_cur;
1109 st[sp-1] = hfetch(hash,tmps,len, lval);
1111 str_magic(st[sp-1],stab,magic,tmps,len);
1114 st[sp-1] = &str_undef;
1122 st[sp] = afetch(ary,
1123 ((int)str_gnum(st[max])) - arybase, lval);
1125 st[sp] = &str_undef;
1129 tmps = str_get(st[max]);
1130 len = st[max]->str_cur;
1131 st[sp] = hfetch(hash,tmps,len, lval);
1133 str_magic(st[sp],stab,magic,tmps,len);
1136 st[sp] = &str_undef;
1139 arybase = oldarybase;
1144 do_splice(ary,gimme,arglast)
1145 register ARRAY *ary;
1149 register STR **st = stack->ary_array;
1150 register int sp = arglast[1];
1151 int max = arglast[2] + 1;
1155 register int offset;
1156 register int length;
1163 offset = ((int)str_gnum(st[sp])) - arybase;
1165 offset += ary->ary_fill + 1;
1167 length = (int)str_gnum(st[sp++]);
1172 length = ary->ary_max; /* close enough to infinity */
1176 length = ary->ary_max;
1184 if (offset > ary->ary_fill + 1)
1185 offset = ary->ary_fill + 1;
1186 after = ary->ary_fill + 1 - (offset + length);
1187 if (after < 0) { /* not that much array */
1188 length += after; /* offset+length now in array */
1190 if (!ary->ary_alloc) {
1196 /* At this point, sp .. max-1 is our new LIST */
1199 diff = newlen - length;
1201 if (diff < 0) { /* shrinking the area */
1203 New(451, tmparyval, newlen, STR*); /* so remember insertion */
1204 Copy(st+sp, tmparyval, newlen, STR*);
1207 sp = arglast[0] + 1;
1208 if (gimme == G_ARRAY) { /* copy return vals to stack */
1209 if (sp + length >= stack->ary_max) {
1210 astore(stack,sp + length, Nullstr);
1211 st = stack->ary_array;
1213 Copy(ary->ary_array+offset, st+sp, length, STR*);
1214 if (ary->ary_flags & ARF_REAL) {
1215 for (i = length, dst = st+sp; i; i--)
1216 str_2static(*dst++); /* free them eventualy */
1221 st[sp] = ary->ary_array[offset+length-1];
1222 if (ary->ary_flags & ARF_REAL)
1223 str_2static(st[sp]);
1225 ary->ary_fill += diff;
1227 /* pull up or down? */
1229 if (offset < after) { /* easier to pull up */
1230 if (offset) { /* esp. if nothing to pull */
1231 src = &ary->ary_array[offset-1];
1232 dst = src - diff; /* diff is negative */
1233 for (i = offset; i > 0; i--) /* can't trust Copy */
1236 Zero(ary->ary_array, -diff, STR*);
1237 ary->ary_array -= diff; /* diff is negative */
1238 ary->ary_max += diff;
1241 if (after) { /* anything to pull down? */
1242 src = ary->ary_array + offset + length;
1243 dst = src + diff; /* diff is negative */
1244 Copy(src, dst, after, STR*);
1246 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
1247 /* avoid later double free */
1250 for (src = tmparyval, dst = ary->ary_array + offset;
1252 *dst = Str_new(46,0);
1253 str_sset(*dst++,*src++);
1255 Safefree(tmparyval);
1258 else { /* no, expanding (or same) */
1260 New(452, tmparyval, length, STR*); /* so remember deletion */
1261 Copy(ary->ary_array+offset, tmparyval, length, STR*);
1264 if (diff > 0) { /* expanding */
1266 /* push up or down? */
1268 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
1270 src = ary->ary_array;
1272 Copy(src, dst, offset, STR*);
1274 ary->ary_array -= diff; /* diff is positive */
1275 ary->ary_max += diff;
1276 ary->ary_fill += diff;
1279 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
1280 astore(ary, ary->ary_fill + diff, Nullstr);
1282 ary->ary_fill += diff;
1284 dst = ary->ary_array + ary->ary_fill;
1286 for (i = after; i; i--) {
1287 if (*dst) /* str was hanging around */
1288 str_free(*dst); /* after $#foo */
1296 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
1297 *dst = Str_new(46,0);
1298 str_sset(*dst++,*src++);
1300 sp = arglast[0] + 1;
1301 if (gimme == G_ARRAY) { /* copy return vals to stack */
1303 Copy(tmparyval, st+sp, length, STR*);
1304 if (ary->ary_flags & ARF_REAL) {
1305 for (i = length, dst = st+sp; i; i--)
1306 str_2static(*dst++); /* free them eventualy */
1308 Safefree(tmparyval);
1313 st[sp] = tmparyval[length-1];
1314 if (ary->ary_flags & ARF_REAL)
1315 str_2static(st[sp]);
1316 Safefree(tmparyval);
1319 st[sp] = &str_undef;
1325 do_grep(arg,str,gimme,arglast)
1331 STR **st = stack->ary_array;
1332 register int dst = arglast[1];
1333 register int src = dst + 1;
1334 register int sp = arglast[2];
1335 register int i = sp - arglast[1];
1336 int oldsave = savestack->ary_fill;
1337 SPAT *oldspat = curspat;
1338 int oldtmps_base = tmps_base;
1340 savesptr(&stab_val(defstab));
1341 tmps_base = tmps_max;
1342 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
1343 arg[1].arg_type &= A_MASK;
1345 arg[1].arg_type |= A_DONT;
1347 arg = arg[1].arg_ptr.arg_arg;
1350 stab_val(defstab) = st[src];
1352 stab_val(defstab) = str_static(&str_undef);
1353 (void)eval(arg,G_SCALAR,sp);
1354 st = stack->ary_array;
1355 if (str_true(st[sp+1]))
1356 st[dst++] = st[src];
1360 restorelist(oldsave);
1361 tmps_base = oldtmps_base;
1362 if (gimme != G_ARRAY) {
1363 str_numset(str,(double)(dst - arglast[1]));
1365 st[arglast[0]+1] = str;
1366 return arglast[0]+1;
1368 return arglast[0] + (dst - arglast[1]);
1375 STR **st = stack->ary_array;
1376 register STR **up = &st[arglast[1]];
1377 register STR **down = &st[arglast[2]];
1378 register int i = arglast[2] - arglast[1];
1385 i = arglast[2] - arglast[1];
1386 Copy(down+1,up,i/2,STR*);
1387 return arglast[2] - 1;
1391 do_sreverse(str,arglast)
1395 STR **st = stack->ary_array;
1397 register char *down;
1400 str_sset(str,st[arglast[2]]);
1402 if (str->str_cur > 1) {
1403 down = str->str_ptr + str->str_cur - 1;
1411 st[arglast[0]+1] = str;
1412 return arglast[0]+1;
1415 static CMD *sortcmd;
1416 static HASH *sortstash = Null(HASH*);
1417 static STAB *firststab = Nullstab;
1418 static STAB *secondstab = Nullstab;
1421 do_sort(str,stab,gimme,arglast)
1427 register STR **st = stack->ary_array;
1428 int sp = arglast[1];
1430 register int max = arglast[2] - sp;
1437 static ARRAY *sortstack = Null(ARRAY*);
1439 if (gimme != G_ARRAY) {
1440 str_sset(str,&str_undef);
1446 st += sp; /* temporarily make st point to args */
1447 for (i = 1; i <= max; i++) {
1449 if (!(*up)->str_pok)
1450 (void)str_2ptr(*up);
1452 (*up)->str_pok &= ~SP_TEMP;
1461 int oldtmps_base = tmps_base;
1463 if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd))
1464 fatal("Undefined subroutine \"%s\" in sort", stab_name(stab));
1466 sortstack = anew(Nullstab);
1467 astore(sortstack, 0, Nullstr);
1469 sortstack->ary_flags = 0;
1473 tmps_base = tmps_max;
1474 if (sortstash != stab_stash(stab)) {
1475 firststab = stabent("a",TRUE);
1476 secondstab = stabent("b",TRUE);
1477 sortstash = stab_stash(stab);
1479 oldfirst = stab_val(firststab);
1480 oldsecond = stab_val(secondstab);
1482 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1484 qsort(Nullch,max,sizeof(STR*),sortsub);
1486 stab_val(firststab) = oldfirst;
1487 stab_val(secondstab) = oldsecond;
1488 tmps_base = oldtmps_base;
1493 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1504 stab_val(firststab) = *str1;
1505 stab_val(secondstab) = *str2;
1506 cmd_exec(sortcmd,G_SCALAR,-1);
1507 return (int)str_gnum(*stack->ary_array);
1510 sortcmp(strp1,strp2)
1514 register STR *str1 = *strp1;
1515 register STR *str2 = *strp2;
1518 if (str1->str_cur < str2->str_cur) {
1519 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1524 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1526 else if (str1->str_cur == str2->str_cur)
1533 do_range(gimme,arglast)
1537 STR **st = stack->ary_array;
1538 register int sp = arglast[0];
1540 register ARRAY *ary = stack;
1544 if (gimme != G_ARRAY)
1545 fatal("panic: do_range");
1547 if (st[sp+1]->str_nok ||
1548 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1549 i = (int)str_gnum(st[sp+1]);
1550 max = (int)str_gnum(st[sp+2]);
1552 (void)astore(ary, ++sp, str = str_static(&str_no));
1553 str_numset(str,(double)i++);
1557 STR *final = str_static(st[sp+2]);
1558 char *tmps = str_get(final);
1560 str = str_static(st[sp+1]);
1561 while (!str->str_nok && str->str_cur <= final->str_cur &&
1562 strNE(str->str_ptr,tmps) ) {
1563 (void)astore(ary, ++sp, str);
1564 str = str_2static(str_smake(str));
1567 if (strEQ(str->str_ptr,tmps))
1568 (void)astore(ary, ++sp, str);
1574 do_caller(arg,maxarg,gimme,arglast)
1580 STR **st = stack->ary_array;
1581 register int sp = arglast[0];
1582 register CSV *csv = curcsv;
1587 fatal("There is no caller");
1589 count = (int) str_gnum(st[sp+1]);
1593 if (DBsub && csv->curcsv && csv->curcsv->sub == stab_sub(DBsub))
1599 if (gimme != G_ARRAY) {
1600 STR *str = arg->arg_ptr.arg_str;
1601 str_set(str,csv->curcmd->c_stash->tbl_name);
1608 (void)astore(stack,++sp,
1609 str_2static(str_make(csv->curcmd->c_stash->tbl_name,0)) );
1610 (void)astore(stack,++sp,
1611 str_2static(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) );
1612 (void)astore(stack,++sp,
1613 str_2static(str_nmake((double)csv->curcmd->c_line)) );
1616 str = Str_new(49,0);
1617 stab_fullname(str, csv->stab);
1618 (void)astore(stack,++sp, str_2static(str));
1619 (void)astore(stack,++sp,
1620 str_2static(str_nmake((double)csv->hasargs)) );
1621 (void)astore(stack,++sp,
1622 str_2static(str_nmake((double)csv->wantarray)) );
1624 ARRAY *ary = csv->argarray;
1626 if (dbargs->ary_max < ary->ary_fill)
1627 astore(dbargs,ary->ary_fill,Nullstr);
1628 Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*);
1629 dbargs->ary_fill = ary->ary_fill;
1632 (void)astore(stack,++sp,
1633 str_2static(str_make("",0)));
1639 do_tms(str,gimme,arglast)
1647 STR **st = stack->ary_array;
1648 register int sp = arglast[0];
1650 if (gimme != G_ARRAY) {
1651 str_sset(str,&str_undef);
1656 (void)times(×buf);
1663 (void)astore(stack,++sp,
1664 str_2static(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1665 (void)astore(stack,++sp,
1666 str_2static(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1667 (void)astore(stack,++sp,
1668 str_2static(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1669 (void)astore(stack,++sp,
1670 str_2static(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1672 (void)astore(stack,++sp,
1673 str_2static(str_nmake(0.0)));
1680 do_time(str,tmbuf,gimme,arglast)
1686 register ARRAY *ary = stack;
1687 STR **st = ary->ary_array;
1688 register int sp = arglast[0];
1690 if (!tmbuf || gimme != G_ARRAY) {
1691 str_sset(str,&str_undef);
1696 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_sec)));
1697 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_min)));
1698 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_hour)));
1699 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mday)));
1700 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mon)));
1701 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_year)));
1702 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_wday)));
1703 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_yday)));
1704 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_isdst)));
1709 do_kv(str,hash,kv,gimme,arglast)
1716 register ARRAY *ary = stack;
1717 STR **st = ary->ary_array;
1718 register int sp = arglast[0];
1720 register HENT *entry;
1723 int dokeys = (kv == O_KEYS || kv == O_HASH);
1724 int dovalues = (kv == O_VALUES || kv == O_HASH);
1726 if (gimme != G_ARRAY) {
1727 str_sset(str,&str_undef);
1732 (void)hiterinit(hash);
1733 while (entry = hiternext(hash)) {
1735 tmps = hiterkey(entry,&i);
1738 (void)astore(ary,++sp,str_2static(str_make(tmps,i)));
1741 tmpstr = Str_new(45,0);
1744 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1745 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1746 str_set(tmpstr,buf);
1750 str_sset(tmpstr,hiterval(hash,entry));
1751 (void)astore(ary,++sp,str_2static(tmpstr));
1758 do_each(str,hash,gimme,arglast)
1764 STR **st = stack->ary_array;
1765 register int sp = arglast[0];
1766 static STR *mystrk = Nullstr;
1767 HENT *entry = hiternext(hash);
1777 if (gimme == G_ARRAY) {
1778 tmps = hiterkey(entry, &i);
1781 st[++sp] = mystrk = str_make(tmps,i);
1784 str_sset(str,hiterval(hash,entry));