1 /* $RCSfile: dolist.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 13:13:27 $
3 * Copyright (c) 1991, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
9 * Revision 4.0.1.5 92/06/08 13:13:27 lwall
10 * patch20: g pattern modifer sometimes returned extra values
11 * patch20: m/$pattern/g didn't work
12 * patch20: pattern modifiers i and o didn't interact right
13 * patch20: @ in unpack failed too often
14 * patch20: Perl now distinguishes overlapped copies from non-overlapped
15 * patch20: slice on null list in scalar context returned random value
16 * patch20: splice with negative offset didn't work with $[ = 1
17 * patch20: fixed some memory leaks in splice
18 * patch20: scalar keys %array now counts keys for you
20 * Revision 4.0.1.4 91/11/11 16:33:19 lwall
21 * patch19: added little-endian pack/unpack options
22 * patch19: sort $subname was busted by changes in 4.018
24 * Revision 4.0.1.3 91/11/05 17:07:02 lwall
25 * patch11: prepared for ctype implementations that don't define isascii()
26 * patch11: /$foo/o optimizer could access deallocated data
27 * patch11: certain optimizations of //g in array context returned too many values
28 * patch11: regexp with no parens in array context returned wacky $`, $& and $'
29 * patch11: $' not set right on some //g
30 * patch11: added some support for 64-bit integers
31 * patch11: grep of a split lost its values
32 * patch11: added sort {} LIST
33 * patch11: multiple reallocations now avoided in 1 .. 100000
35 * Revision 4.0.1.2 91/06/10 01:22:15 lwall
36 * patch10: //g only worked first time through
38 * Revision 4.0.1.1 91/06/07 10:58:28 lwall
39 * patch4: new copyright notice
40 * patch4: added global modifier for pattern matches
41 * patch4: // wouldn't use previous pattern if it started with a null character
42 * patch4: //o and s///o now optimize themselves fully at runtime
43 * patch4: $` was busted inside s///
44 * patch4: caller($arg) didn't work except under debugger
46 * Revision 4.0 91/03/20 01:08:03 lwall
58 #pragma function(memcmp)
59 #endif /* BUGGY_MSC */
62 do_match(str,arg,gimme,arglast)
68 register STR **st = stack->ary_array;
69 register SPAT *spat = arg[2].arg_ptr.arg_spat;
71 register int sp = arglast[0] + 1;
72 STR *srchstr = st[sp];
73 register char *s = str_get(st[sp]);
74 char *strend = s + st[sp]->str_cur;
80 register REGEXP *rx = spat->spat_regexp;
91 global = spat->spat_flags & SPAT_GLOBAL;
92 safebase = (gimme == G_ARRAY) || global;
94 fatal("panic: do_match");
95 if (spat->spat_flags & SPAT_USED) {
100 if (gimme == G_ARRAY)
108 if (spat->spat_runtime) {
110 sp = eval(spat->spat_runtime,G_SCALAR,sp);
111 st = stack->ary_array;
112 t = str_get(tmpstr = st[sp--]);
116 deb("2.SPAT /%s/\n",t);
120 spat->spat_regexp = Null(REGEXP*); /* crucial if regcomp aborts */
121 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
122 spat->spat_flags & SPAT_FOLD);
123 if (!spat->spat_regexp->prelen && lastspat)
125 if (spat->spat_flags & SPAT_KEEP) {
126 if (!(spat->spat_flags & SPAT_FOLD))
127 scanconst(spat,spat->spat_regexp->precomp,
128 spat->spat_regexp->prelen);
129 if (spat->spat_runtime)
130 arg_free(spat->spat_runtime); /* it won't change, so */
131 spat->spat_runtime = Nullarg; /* no point compiling again */
133 if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) {
134 curcmd->c_flags &= ~CF_OPTIMIZE;
135 opt_arg(curcmd, 1, curcmd->c_type == C_EXPR);
142 if (s == rx->startp[0])
146 rx = spat->spat_regexp;
153 else if (!spat->spat_regexp->nparens)
154 gimme = G_SCALAR; /* accidental array context? */
155 rx = spat->spat_regexp;
156 if (regexec(rx, s, strend, s, 0,
157 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
159 if (rx->subbase || global)
165 if (gimme == G_ARRAY)
167 str_sset(str,&str_no);
178 if (spat->spat_flags & SPAT_ONCE)
182 deb("2.SPAT %c%s%c\n",ch,rx->precomp,ch);
185 if (!rx->prelen && lastspat) {
187 rx = spat->spat_regexp;
191 if (global && rx->startp[0]) {
193 if (s == rx->startp[0])
199 if (myhint < s || myhint > strend)
200 fatal("panic: hint in do_match");
202 if (rx->regback >= 0) {
210 else if (spat->spat_short) {
211 if (spat->spat_flags & SPAT_SCANFIRST) {
212 if (srchstr->str_pok & SP_STUDIED) {
213 if (screamfirst[spat->spat_short->str_rare] < 0)
215 else if (!(s = screaminstr(srchstr,spat->spat_short)))
217 else if (spat->spat_flags & SPAT_ALL)
221 else if (!(s = fbminstr((unsigned char*)s,
222 (unsigned char*)strend, spat->spat_short)))
225 else if (spat->spat_flags & SPAT_ALL)
227 if (s && rx->regback >= 0) {
228 ++spat->spat_short->str_u.str_useful;
236 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
237 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
239 if (--spat->spat_short->str_u.str_useful < 0) {
240 str_free(spat->spat_short);
241 spat->spat_short = Nullstr; /* opt is being useless */
244 if (!rx->nparens && !global) {
245 gimme = G_SCALAR; /* accidental array context? */
248 if (regexec(rx, s, strend, truebase, 0,
249 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
251 if (rx->subbase || global)
254 if (spat->spat_flags & SPAT_ONCE)
255 spat->spat_flags |= SPAT_USED;
260 rx->startp[0] = Nullch;
261 if (gimme == G_ARRAY)
263 str_sset(str,&str_no);
272 if (gimme == G_ARRAY) {
276 if (global && !iters)
280 if (sp + iters + i >= stack->ary_max) {
281 astore(stack,sp + iters + i, Nullstr);
282 st = stack->ary_array; /* possibly realloced */
285 for (i = !i; i <= iters; i++) {
286 st[++sp] = str_mortal(&str_no);
288 if (s = rx->startp[i]) {
289 len = rx->endp[i] - s;
291 str_nset(st[sp],s,len);
295 truebase = rx->subbeg;
301 str_sset(str,&str_yes);
308 ++spat->spat_short->str_u.str_useful;
310 if (spat->spat_flags & SPAT_ONCE)
311 spat->spat_flags |= SPAT_USED;
316 rx->endp[0] = s + spat->spat_short->str_cur;
324 Safefree(rx->subbase);
325 tmps = rx->subbase = nsavestr(t,strend-t);
327 rx->subend = tmps + (strend-t);
328 tmps = rx->startp[0] = tmps + (s - t);
329 rx->endp[0] = tmps + spat->spat_short->str_cur;
332 str_sset(str,&str_yes);
338 rx->startp[0] = Nullch;
339 if (spat->spat_short)
340 ++spat->spat_short->str_u.str_useful;
341 if (gimme == G_ARRAY)
343 str_sset(str,&str_no);
350 #pragma intrinsic(memcmp)
351 #endif /* BUGGY_MSC */
354 do_split(str,spat,limit,gimme,arglast)
361 register ARRAY *ary = stack;
362 STR **st = ary->ary_array;
363 register int sp = arglast[0] + 1;
364 register char *s = str_get(st[sp]);
365 char *strend = s + st[sp--]->str_cur;
369 int maxiters = (strend - s) + 10;
372 int origlimit = limit;
376 fatal("panic: do_split");
377 else if (spat->spat_runtime) {
379 sp = eval(spat->spat_runtime,G_SCALAR,sp);
380 st = stack->ary_array;
381 m = str_get(dstr = st[sp--]);
383 if (*m == ' ' && dstr->str_cur == 1) {
384 str_set(dstr,"\\s+");
386 spat->spat_flags |= SPAT_SKIPWHITE;
388 if (spat->spat_regexp) {
389 regfree(spat->spat_regexp);
390 spat->spat_regexp = Null(REGEXP*); /* avoid possible double free */
392 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
393 spat->spat_flags & SPAT_FOLD);
394 if (spat->spat_flags & SPAT_KEEP ||
395 (spat->spat_runtime->arg_type == O_ITEM &&
396 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
397 arg_free(spat->spat_runtime); /* it won't change, so */
398 spat->spat_runtime = Nullarg; /* no point compiling again */
403 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
406 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
407 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
409 if (!(ary->ary_flags & ARF_REAL)) {
410 ary->ary_flags |= ARF_REAL;
411 for (i = ary->ary_fill; i >= 0; i--)
412 ary->ary_array[i] = Nullstr; /* don't free mere refs */
415 sp = -1; /* temporarily switch stacks */
420 if (spat->spat_flags & SPAT_SKIPWHITE) {
425 limit = maxiters + 2;
426 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
429 for (m = s; m < strend && !isSPACE(*m); m++) ;
432 dstr = Str_new(30,m-s);
433 str_nset(dstr,s,m-s);
436 (void)astore(ary, ++sp, dstr);
438 for (s = m + 1; s < strend && isSPACE(*s); s++) ;
441 else if (strEQ("^",spat->spat_regexp->precomp)) {
444 for (m = s; m < strend && *m != '\n'; m++) ;
448 dstr = Str_new(30,m-s);
449 str_nset(dstr,s,m-s);
452 (void)astore(ary, ++sp, dstr);
456 else if (spat->spat_short) {
457 i = spat->spat_short->str_cur;
459 int fold = (spat->spat_flags & SPAT_FOLD);
461 i = *spat->spat_short->str_ptr;
462 if (fold && isUPPER(i))
467 m < strend && *m != i &&
468 (!isUPPER(*m) || tolower(*m) != i);
469 m++) /*SUPPRESS 530*/
472 else /*SUPPRESS 530*/
473 for (m = s; m < strend && *m != i; m++) ;
476 dstr = Str_new(30,m-s);
477 str_nset(dstr,s,m-s);
480 (void)astore(ary, ++sp, dstr);
486 while (s < strend && --limit &&
487 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
491 dstr = Str_new(31,m-s);
492 str_nset(dstr,s,m-s);
495 (void)astore(ary, ++sp, dstr);
501 maxiters += (strend - s) * spat->spat_regexp->nparens;
502 while (s < strend && --limit &&
503 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
504 if (spat->spat_regexp->subbase
505 && spat->spat_regexp->subbase != orig) {
508 orig = spat->spat_regexp->subbase;
510 strend = s + (strend - m);
512 m = spat->spat_regexp->startp[0];
513 dstr = Str_new(32,m-s);
514 str_nset(dstr,s,m-s);
517 (void)astore(ary, ++sp, dstr);
518 if (spat->spat_regexp->nparens) {
519 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
520 s = spat->spat_regexp->startp[i];
521 m = spat->spat_regexp->endp[i];
522 dstr = Str_new(33,m-s);
523 str_nset(dstr,s,m-s);
526 (void)astore(ary, ++sp, dstr);
529 s = spat->spat_regexp->endp[0];
535 iters = sp - arglast[0];
536 if (iters > maxiters)
538 if (s < strend || origlimit) { /* keep field after final delim? */
539 dstr = Str_new(34,strend-s);
540 str_nset(dstr,s,strend-s);
543 (void)astore(ary, ++sp, dstr);
548 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
555 zaps = str_get(afetch(ary,sp,FALSE));
559 while (iters > 0 && (!zapb)) {
562 zaps = str_get(afetch(ary,iters-1,FALSE));
570 if (gimme == G_ARRAY) {
572 astore(stack, arglast[0] + 1 + sp, Nullstr);
573 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
574 return arglast[0] + sp;
578 if (gimme == G_ARRAY)
582 str_numset(str,(double)iters);
589 do_unpack(str,gimme,arglast)
594 STR **st = stack->ary_array;
595 register int sp = arglast[0] + 1;
596 register char *pat = str_get(st[sp++]);
597 register char *s = str_get(st[sp]);
598 char *strend = s + st[sp--]->str_cur;
600 register char *patend = pat + st[sp]->str_cur;
605 /* These must not be in registers: */
612 unsigned short aushort;
614 unsigned long aulong;
616 unsigned quad auquad;
622 unsigned long culong;
625 if (gimme != G_ARRAY) { /* arrange to do first one only */
627 for (patend = pat; !isALPHA(*patend) || *patend == 'x'; patend++) ;
628 if (index("aAbBhH", *patend) || *pat == '%') {
630 while (isDIGIT(*patend) || *patend == '*')
637 while (pat < patend) {
642 else if (*pat == '*') {
643 len = strend - strbeg; /* long enough */
646 else if (isDIGIT(*pat)) {
648 while (isDIGIT(*pat))
649 len = (len * 10) + (*pat++ - '0');
652 len = (datumtype != '@');
657 if (len == 1 && pat[-1] != '1')
666 if (len > strend - strbeg)
667 fatal("@ outside of string");
671 if (len > s - strbeg)
672 fatal("X outside of string");
676 if (len > strend - s)
677 fatal("x outside of string");
682 if (len > strend - s)
686 str = Str_new(35,len);
689 if (datumtype == 'A') {
690 aptr = s; /* borrow register */
691 s = str->str_ptr + len - 1;
692 while (s >= str->str_ptr && (!*s || isSPACE(*s)))
695 str->str_cur = s - str->str_ptr;
696 s = aptr; /* unborrow register */
698 (void)astore(stack, ++sp, str_2mortal(str));
702 if (pat[-1] == '*' || len > (strend - s) * 8)
703 len = (strend - s) * 8;
704 str = Str_new(35, len + 1);
707 aptr = pat; /* borrow register */
709 if (datumtype == 'b') {
711 for (len = 0; len < aint; len++) {
712 if (len & 7) /*SUPPRESS 595*/
716 *pat++ = '0' + (bits & 1);
721 for (len = 0; len < aint; len++) {
726 *pat++ = '0' + ((bits & 128) != 0);
730 pat = aptr; /* unborrow register */
731 (void)astore(stack, ++sp, str_2mortal(str));
735 if (pat[-1] == '*' || len > (strend - s) * 2)
736 len = (strend - s) * 2;
737 str = Str_new(35, len + 1);
740 aptr = pat; /* borrow register */
742 if (datumtype == 'h') {
744 for (len = 0; len < aint; len++) {
749 *pat++ = hexdigit[bits & 15];
754 for (len = 0; len < aint; len++) {
759 *pat++ = hexdigit[(bits >> 4) & 15];
763 pat = aptr; /* unborrow register */
764 (void)astore(stack, ++sp, str_2mortal(str));
767 if (len > strend - s)
772 if (aint >= 128) /* fake up signed chars */
780 if (aint >= 128) /* fake up signed chars */
783 str_numset(str,(double)aint);
784 (void)astore(stack, ++sp, str_2mortal(str));
789 if (len > strend - s)
802 str_numset(str,(double)auint);
803 (void)astore(stack, ++sp, str_2mortal(str));
808 along = (strend - s) / sizeof(short);
813 Copy(s,&ashort,1,short);
820 Copy(s,&ashort,1,short);
823 str_numset(str,(double)ashort);
824 (void)astore(stack, ++sp, str_2mortal(str));
831 along = (strend - s) / sizeof(unsigned short);
836 Copy(s,&aushort,1,unsigned short);
837 s += sizeof(unsigned short);
839 if (datumtype == 'n')
840 aushort = ntohs(aushort);
843 if (datumtype == 'v')
844 aushort = vtohs(aushort);
851 Copy(s,&aushort,1,unsigned short);
852 s += sizeof(unsigned short);
855 if (datumtype == 'n')
856 aushort = ntohs(aushort);
859 if (datumtype == 'v')
860 aushort = vtohs(aushort);
862 str_numset(str,(double)aushort);
863 (void)astore(stack, ++sp, str_2mortal(str));
868 along = (strend - s) / sizeof(int);
876 cdouble += (double)aint;
886 str_numset(str,(double)aint);
887 (void)astore(stack, ++sp, str_2mortal(str));
892 along = (strend - s) / sizeof(unsigned int);
897 Copy(s,&auint,1,unsigned int);
898 s += sizeof(unsigned int);
900 cdouble += (double)auint;
907 Copy(s,&auint,1,unsigned int);
908 s += sizeof(unsigned int);
910 str_numset(str,(double)auint);
911 (void)astore(stack, ++sp, str_2mortal(str));
916 along = (strend - s) / sizeof(long);
921 Copy(s,&along,1,long);
924 cdouble += (double)along;
931 Copy(s,&along,1,long);
934 str_numset(str,(double)along);
935 (void)astore(stack, ++sp, str_2mortal(str));
942 along = (strend - s) / sizeof(unsigned long);
947 Copy(s,&aulong,1,unsigned long);
948 s += sizeof(unsigned long);
950 if (datumtype == 'N')
951 aulong = ntohl(aulong);
954 if (datumtype == 'V')
955 aulong = vtohl(aulong);
958 cdouble += (double)aulong;
965 Copy(s,&aulong,1,unsigned long);
966 s += sizeof(unsigned long);
969 if (datumtype == 'N')
970 aulong = ntohl(aulong);
973 if (datumtype == 'V')
974 aulong = vtohl(aulong);
976 str_numset(str,(double)aulong);
977 (void)astore(stack, ++sp, str_2mortal(str));
982 along = (strend - s) / sizeof(char*);
986 if (sizeof(char*) > strend - s)
989 Copy(s,&aptr,1,char*);
995 (void)astore(stack, ++sp, str_2mortal(str));
1001 if (s + sizeof(quad) > strend)
1004 Copy(s,&aquad,1,quad);
1007 str = Str_new(42,0);
1008 str_numset(str,(double)aquad);
1009 (void)astore(stack, ++sp, str_2mortal(str));
1014 if (s + sizeof(unsigned quad) > strend)
1017 Copy(s,&auquad,1,unsigned quad);
1018 s += sizeof(unsigned quad);
1020 str = Str_new(43,0);
1021 str_numset(str,(double)auquad);
1022 (void)astore(stack, ++sp, str_2mortal(str));
1026 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
1029 along = (strend - s) / sizeof(float);
1034 Copy(s, &afloat,1, float);
1041 Copy(s, &afloat,1, float);
1043 str = Str_new(47, 0);
1044 str_numset(str, (double)afloat);
1045 (void)astore(stack, ++sp, str_2mortal(str));
1051 along = (strend - s) / sizeof(double);
1056 Copy(s, &adouble,1, double);
1057 s += sizeof(double);
1063 Copy(s, &adouble,1, double);
1064 s += sizeof(double);
1065 str = Str_new(48, 0);
1066 str_numset(str, (double)adouble);
1067 (void)astore(stack, ++sp, str_2mortal(str));
1072 along = (strend - s) * 3 / 4;
1073 str = Str_new(42,along);
1074 while (s < strend && *s > ' ' && *s < 'a') {
1079 len = (*s++ - ' ') & 077;
1081 if (s < strend && *s >= ' ')
1082 a = (*s++ - ' ') & 077;
1085 if (s < strend && *s >= ' ')
1086 b = (*s++ - ' ') & 077;
1089 if (s < strend && *s >= ' ')
1090 c = (*s++ - ' ') & 077;
1093 if (s < strend && *s >= ' ')
1094 d = (*s++ - ' ') & 077;
1097 hunk[0] = a << 2 | b >> 4;
1098 hunk[1] = b << 4 | c >> 2;
1099 hunk[2] = c << 6 | d;
1100 str_ncat(str,hunk, len > 3 ? 3 : len);
1105 else if (s[1] == '\n') /* possible checksum byte */
1108 (void)astore(stack, ++sp, str_2mortal(str));
1112 str = Str_new(42,0);
1113 if (index("fFdD", datumtype) ||
1114 (checksum > 32 && index("iIlLN", datumtype)) ) {
1119 while (checksum >= 16) {
1123 while (checksum >= 4) {
1129 along = (1 << checksum) - 1;
1130 while (cdouble < 0.0)
1132 cdouble = modf(cdouble / adouble, &trouble) * adouble;
1133 str_numset(str,cdouble);
1136 if (checksum < 32) {
1137 along = (1 << checksum) - 1;
1138 culong &= (unsigned long)along;
1140 str_numset(str,(double)culong);
1142 (void)astore(stack, ++sp, str_2mortal(str));
1150 do_slice(stab,str,numarray,lval,gimme,arglast)
1158 register STR **st = stack->ary_array;
1159 register int sp = arglast[1];
1160 register int max = arglast[2];
1161 register char *tmps;
1163 register int magic = 0;
1164 register ARRAY *ary;
1165 register HASH *hash;
1166 int oldarybase = arybase;
1169 if (numarray == 2) { /* a slice of a LIST */
1171 ary->ary_fill = arglast[3];
1173 st[sp] = str; /* make stack size available */
1174 str_numset(str,(double)(sp - 1));
1177 ary = stab_array(stab); /* a slice of an array */
1181 if (stab == envstab)
1183 else if (stab == sigstab)
1186 else if (stab_hash(stab)->tbl_dbm)
1188 #endif /* SOME_DBM */
1190 hash = stab_hash(stab); /* a slice of an associative array */
1193 if (gimme == G_ARRAY) {
1197 st[sp-1] = afetch(ary,
1198 ((int)str_gnum(st[sp])) - arybase, lval);
1201 st[sp-1] = &str_undef;
1207 tmps = str_get(st[sp]);
1208 len = st[sp]->str_cur;
1209 st[sp-1] = hfetch(hash,tmps,len, lval);
1211 str_magic(st[sp-1],stab,magic,tmps,len);
1214 st[sp-1] = &str_undef;
1221 st[sp] = &str_undef;
1222 else if (numarray) {
1224 st[sp] = afetch(ary,
1225 ((int)str_gnum(st[max])) - arybase, lval);
1227 st[sp] = &str_undef;
1231 tmps = str_get(st[max]);
1232 len = st[max]->str_cur;
1233 st[sp] = hfetch(hash,tmps,len, lval);
1235 str_magic(st[sp],stab,magic,tmps,len);
1238 st[sp] = &str_undef;
1241 arybase = oldarybase;
1246 do_splice(ary,gimme,arglast)
1247 register ARRAY *ary;
1251 register STR **st = stack->ary_array;
1252 register int sp = arglast[1];
1253 int max = arglast[2] + 1;
1257 register int offset;
1258 register int length;
1265 offset = (int)str_gnum(st[sp]);
1267 offset += ary->ary_fill + 1;
1271 length = (int)str_gnum(st[sp++]);
1276 length = ary->ary_max + 1; /* close enough to infinity */
1280 length = ary->ary_max + 1;
1288 if (offset > ary->ary_fill + 1)
1289 offset = ary->ary_fill + 1;
1290 after = ary->ary_fill + 1 - (offset + length);
1291 if (after < 0) { /* not that much array */
1292 length += after; /* offset+length now in array */
1294 if (!ary->ary_alloc) {
1300 /* At this point, sp .. max-1 is our new LIST */
1303 diff = newlen - length;
1305 if (diff < 0) { /* shrinking the area */
1307 New(451, tmparyval, newlen, STR*); /* so remember insertion */
1308 Copy(st+sp, tmparyval, newlen, STR*);
1311 sp = arglast[0] + 1;
1312 if (gimme == G_ARRAY) { /* copy return vals to stack */
1313 if (sp + length >= stack->ary_max) {
1314 astore(stack,sp + length, Nullstr);
1315 st = stack->ary_array;
1317 Copy(ary->ary_array+offset, st+sp, length, STR*);
1318 if (ary->ary_flags & ARF_REAL) {
1319 for (i = length, dst = st+sp; i; i--)
1320 str_2mortal(*dst++); /* free them eventualy */
1325 st[sp] = ary->ary_array[offset+length-1];
1326 if (ary->ary_flags & ARF_REAL) {
1327 str_2mortal(st[sp]);
1328 for (i = length - 1, dst = &ary->ary_array[offset]; i > 0; i--)
1329 str_free(*dst++); /* free them now */
1332 ary->ary_fill += diff;
1334 /* pull up or down? */
1336 if (offset < after) { /* easier to pull up */
1337 if (offset) { /* esp. if nothing to pull */
1338 src = &ary->ary_array[offset-1];
1339 dst = src - diff; /* diff is negative */
1340 for (i = offset; i > 0; i--) /* can't trust Copy */
1343 Zero(ary->ary_array, -diff, STR*);
1344 ary->ary_array -= diff; /* diff is negative */
1345 ary->ary_max += diff;
1348 if (after) { /* anything to pull down? */
1349 src = ary->ary_array + offset + length;
1350 dst = src + diff; /* diff is negative */
1351 Move(src, dst, after, STR*);
1353 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
1354 /* avoid later double free */
1357 for (src = tmparyval, dst = ary->ary_array + offset;
1359 *dst = Str_new(46,0);
1360 str_sset(*dst++,*src++);
1362 Safefree(tmparyval);
1365 else { /* no, expanding (or same) */
1367 New(452, tmparyval, length, STR*); /* so remember deletion */
1368 Copy(ary->ary_array+offset, tmparyval, length, STR*);
1371 if (diff > 0) { /* expanding */
1373 /* push up or down? */
1375 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
1377 src = ary->ary_array;
1379 Move(src, dst, offset, STR*);
1381 ary->ary_array -= diff; /* diff is positive */
1382 ary->ary_max += diff;
1383 ary->ary_fill += diff;
1386 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
1387 astore(ary, ary->ary_fill + diff, Nullstr);
1389 ary->ary_fill += diff;
1390 dst = ary->ary_array + ary->ary_fill;
1391 for (i = diff; i > 0; i--) {
1392 if (*dst) /* str was hanging around */
1393 str_free(*dst); /* after $#foo */
1397 dst = ary->ary_array + ary->ary_fill;
1399 for (i = after; i; i--) {
1406 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
1407 *dst = Str_new(46,0);
1408 str_sset(*dst++,*src++);
1410 sp = arglast[0] + 1;
1411 if (gimme == G_ARRAY) { /* copy return vals to stack */
1413 Copy(tmparyval, st+sp, length, STR*);
1414 if (ary->ary_flags & ARF_REAL) {
1415 for (i = length, dst = st+sp; i; i--)
1416 str_2mortal(*dst++); /* free them eventualy */
1418 Safefree(tmparyval);
1422 else if (length--) {
1423 st[sp] = tmparyval[length];
1424 if (ary->ary_flags & ARF_REAL) {
1425 str_2mortal(st[sp]);
1426 while (length-- > 0)
1427 str_free(tmparyval[length]);
1429 Safefree(tmparyval);
1432 st[sp] = &str_undef;
1438 do_grep(arg,str,gimme,arglast)
1444 STR **st = stack->ary_array;
1445 register int dst = arglast[1];
1446 register int src = dst + 1;
1447 register int sp = arglast[2];
1448 register int i = sp - arglast[1];
1449 int oldsave = savestack->ary_fill;
1450 SPAT *oldspat = curspat;
1451 int oldtmps_base = tmps_base;
1453 savesptr(&stab_val(defstab));
1454 tmps_base = tmps_max;
1455 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
1456 arg[1].arg_type &= A_MASK;
1458 arg[1].arg_type |= A_DONT;
1460 arg = arg[1].arg_ptr.arg_arg;
1463 st[src]->str_pok &= ~SP_TEMP;
1464 stab_val(defstab) = st[src];
1467 stab_val(defstab) = str_mortal(&str_undef);
1468 (void)eval(arg,G_SCALAR,sp);
1469 st = stack->ary_array;
1470 if (str_true(st[sp+1]))
1471 st[dst++] = st[src];
1475 restorelist(oldsave);
1476 tmps_base = oldtmps_base;
1477 if (gimme != G_ARRAY) {
1478 str_numset(str,(double)(dst - arglast[1]));
1480 st[arglast[0]+1] = str;
1481 return arglast[0]+1;
1483 return arglast[0] + (dst - arglast[1]);
1490 STR **st = stack->ary_array;
1491 register STR **up = &st[arglast[1]];
1492 register STR **down = &st[arglast[2]];
1493 register int i = arglast[2] - arglast[1];
1500 i = arglast[2] - arglast[1];
1501 Move(down+1,up,i/2,STR*);
1502 return arglast[2] - 1;
1506 do_sreverse(str,arglast)
1510 STR **st = stack->ary_array;
1512 register char *down;
1515 str_sset(str,st[arglast[2]]);
1517 if (str->str_cur > 1) {
1518 down = str->str_ptr + str->str_cur - 1;
1526 st[arglast[0]+1] = str;
1527 return arglast[0]+1;
1530 static CMD *sortcmd;
1531 static HASH *sortstash = Null(HASH*);
1532 static STAB *firststab = Nullstab;
1533 static STAB *secondstab = Nullstab;
1536 do_sort(str,arg,gimme,arglast)
1542 register STR **st = stack->ary_array;
1543 int sp = arglast[1];
1545 register int max = arglast[2] - sp;
1554 static ARRAY *sortstack = Null(ARRAY*);
1556 if (gimme != G_ARRAY) {
1557 str_sset(str,&str_undef);
1564 st += sp; /* temporarily make st point to args */
1565 for (i = 1; i <= max; i++) {
1568 if (!(*up)->str_pok)
1569 (void)str_2ptr(*up);
1571 (*up)->str_pok &= ~SP_TEMP;
1581 if (arg[1].arg_type == (A_CMD|A_DONT)) {
1582 sortcmd = arg[1].arg_ptr.arg_cmd;
1583 stash = curcmd->c_stash;
1586 if ((arg[1].arg_type & A_MASK) == A_WORD)
1587 stab = arg[1].arg_ptr.arg_stab;
1589 stab = stabent(str_get(sortsubvar),TRUE);
1592 if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd))
1593 fatal("Undefined subroutine \"%s\" in sort",
1595 stash = stab_estash(stab);
1602 int oldtmps_base = tmps_base;
1605 sortstack = anew(Nullstab);
1606 astore(sortstack, 0, Nullstr);
1608 sortstack->ary_flags = 0;
1612 tmps_base = tmps_max;
1613 if (sortstash != stash) {
1614 firststab = stabent("a",TRUE);
1615 secondstab = stabent("b",TRUE);
1618 oldfirst = stab_val(firststab);
1619 oldsecond = stab_val(secondstab);
1621 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1623 qsort(Nullch,max,sizeof(STR*),sortsub);
1625 stab_val(firststab) = oldfirst;
1626 stab_val(secondstab) = oldsecond;
1627 tmps_base = oldtmps_base;
1632 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1643 stab_val(firststab) = *str1;
1644 stab_val(secondstab) = *str2;
1645 cmd_exec(sortcmd,G_SCALAR,-1);
1646 return (int)str_gnum(*stack->ary_array);
1650 sortcmp(strp1,strp2)
1654 register STR *str1 = *strp1;
1655 register STR *str2 = *strp2;
1658 if (str1->str_cur < str2->str_cur) {
1660 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1666 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1668 else if (str1->str_cur == str2->str_cur)
1675 do_range(gimme,arglast)
1679 STR **st = stack->ary_array;
1680 register int sp = arglast[0];
1682 register ARRAY *ary = stack;
1686 if (gimme != G_ARRAY)
1687 fatal("panic: do_range");
1689 if (st[sp+1]->str_nok || !st[sp+1]->str_pok ||
1690 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1691 i = (int)str_gnum(st[sp+1]);
1692 max = (int)str_gnum(st[sp+2]);
1694 (void)astore(ary, sp + max - i + 1, Nullstr);
1696 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1697 str_numset(str,(double)i++);
1701 STR *final = str_mortal(st[sp+2]);
1702 char *tmps = str_get(final);
1704 str = str_mortal(st[sp+1]);
1705 while (!str->str_nok && str->str_cur <= final->str_cur &&
1706 strNE(str->str_ptr,tmps) ) {
1707 (void)astore(ary, ++sp, str);
1708 str = str_2mortal(str_smake(str));
1711 if (strEQ(str->str_ptr,tmps))
1712 (void)astore(ary, ++sp, str);
1718 do_repeatary(arglast)
1721 STR **st = stack->ary_array;
1722 register int sp = arglast[0];
1723 register int items = arglast[1] - sp;
1724 register int count = (int) str_gnum(st[arglast[2]]);
1728 max = items * count;
1729 if (max > 0 && sp + max > stack->ary_max) {
1730 astore(stack, sp + max, Nullstr);
1731 st = stack->ary_array;
1734 for (i = arglast[1]; i > sp; i--)
1735 st[i]->str_pok &= ~SP_TEMP;
1736 repeatcpy((char*)&st[arglast[1]+1], (char*)&st[sp+1],
1737 items * sizeof(STR*), count);
1745 do_caller(arg,maxarg,gimme,arglast)
1751 STR **st = stack->ary_array;
1752 register int sp = arglast[0];
1753 register CSV *csv = curcsv;
1758 fatal("There is no caller");
1760 count = (int) str_gnum(st[sp+1]);
1764 if (DBsub && csv->curcsv && csv->curcsv->sub == stab_sub(DBsub))
1770 if (gimme != G_ARRAY) {
1771 STR *str = arg->arg_ptr.arg_str;
1772 str_set(str,csv->curcmd->c_stash->tbl_name);
1779 (void)astore(stack,++sp,
1780 str_2mortal(str_make(csv->curcmd->c_stash->tbl_name,0)) );
1781 (void)astore(stack,++sp,
1782 str_2mortal(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) );
1783 (void)astore(stack,++sp,
1784 str_2mortal(str_nmake((double)csv->curcmd->c_line)) );
1787 str = Str_new(49,0);
1788 stab_efullname(str, csv->stab);
1789 (void)astore(stack,++sp, str_2mortal(str));
1790 (void)astore(stack,++sp,
1791 str_2mortal(str_nmake((double)csv->hasargs)) );
1792 (void)astore(stack,++sp,
1793 str_2mortal(str_nmake((double)csv->wantarray)) );
1795 ARRAY *ary = csv->argarray;
1798 dbargs = stab_xarray(aadd(stabent("DB'args", TRUE)));
1799 if (dbargs->ary_max < ary->ary_fill)
1800 astore(dbargs,ary->ary_fill,Nullstr);
1801 Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*);
1802 dbargs->ary_fill = ary->ary_fill;
1805 (void)astore(stack,++sp,
1806 str_2mortal(str_make("",0)));
1812 do_tms(str,gimme,arglast)
1820 STR **st = stack->ary_array;
1821 register int sp = arglast[0];
1823 if (gimme != G_ARRAY) {
1824 str_sset(str,&str_undef);
1829 (void)times(×buf);
1836 (void)astore(stack,++sp,
1837 str_2mortal(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1838 (void)astore(stack,++sp,
1839 str_2mortal(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1840 (void)astore(stack,++sp,
1841 str_2mortal(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1842 (void)astore(stack,++sp,
1843 str_2mortal(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1845 (void)astore(stack,++sp,
1846 str_2mortal(str_nmake(0.0)));
1853 do_time(str,tmbuf,gimme,arglast)
1859 register ARRAY *ary = stack;
1860 STR **st = ary->ary_array;
1861 register int sp = arglast[0];
1863 if (!tmbuf || gimme != G_ARRAY) {
1864 str_sset(str,&str_undef);
1869 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_sec)));
1870 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_min)));
1871 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_hour)));
1872 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mday)));
1873 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mon)));
1874 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_year)));
1875 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_wday)));
1876 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_yday)));
1877 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_isdst)));
1882 do_kv(str,hash,kv,gimme,arglast)
1889 register ARRAY *ary = stack;
1890 STR **st = ary->ary_array;
1891 register int sp = arglast[0];
1893 register HENT *entry;
1896 int dokeys = (kv == O_KEYS || kv == O_HASH);
1897 int dovalues = (kv == O_VALUES || kv == O_HASH);
1899 if (gimme != G_ARRAY) {
1901 (void)hiterinit(hash);
1903 while (entry = hiternext(hash)) {
1906 str_numset(str,(double)i);
1911 (void)hiterinit(hash);
1913 while (entry = hiternext(hash)) {
1915 tmps = hiterkey(entry,&i);
1918 (void)astore(ary,++sp,str_2mortal(str_make(tmps,i)));
1921 tmpstr = Str_new(45,0);
1924 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1925 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1926 str_set(tmpstr,buf);
1930 str_sset(tmpstr,hiterval(hash,entry));
1931 (void)astore(ary,++sp,str_2mortal(tmpstr));
1938 do_each(str,hash,gimme,arglast)
1944 STR **st = stack->ary_array;
1945 register int sp = arglast[0];
1946 static STR *mystrk = Nullstr;
1947 HENT *entry = hiternext(hash);
1957 if (gimme == G_ARRAY) {
1958 tmps = hiterkey(entry, &i);
1961 st[++sp] = mystrk = str_make(tmps,i);
1964 str_sset(str,hiterval(hash,entry));