1 /* $RCSfile: dolist.c,v $$Revision: 4.0.1.3 $$Date: 91/11/05 17:07:02 $
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.3 91/11/05 17:07:02 lwall
10 * patch11: prepared for ctype implementations that don't define isascii()
11 * patch11: /$foo/o optimizer could access deallocated data
12 * patch11: certain optimizations of //g in array context returned too many values
13 * patch11: regexp with no parens in array context returned wacky $`, $& and $'
14 * patch11: $' not set right on some //g
15 * patch11: added some support for 64-bit integers
16 * patch11: grep of a split lost its values
17 * patch11: added sort {} LIST
18 * patch11: multiple reallocations now avoided in 1 .. 100000
20 * Revision 4.0.1.2 91/06/10 01:22:15 lwall
21 * patch10: //g only worked first time through
23 * Revision 4.0.1.1 91/06/07 10:58:28 lwall
24 * patch4: new copyright notice
25 * patch4: added global modifier for pattern matches
26 * patch4: // wouldn't use previous pattern if it started with a null character
27 * patch4: //o and s///o now optimize themselves fully at runtime
28 * patch4: $` was busted inside s///
29 * patch4: caller($arg) didn't work except under debugger
31 * Revision 4.0 91/03/20 01:08:03 lwall
41 #pragma function(memcmp)
42 #endif /* BUGGY_MSC */
45 do_match(str,arg,gimme,arglast)
51 register STR **st = stack->ary_array;
52 register SPAT *spat = arg[2].arg_ptr.arg_spat;
54 register int sp = arglast[0] + 1;
55 STR *srchstr = st[sp];
56 register char *s = str_get(st[sp]);
57 char *strend = s + st[sp]->str_cur;
72 global = spat->spat_flags & SPAT_GLOBAL;
73 safebase = (gimme == G_ARRAY) || global;
75 fatal("panic: do_match");
76 if (spat->spat_flags & SPAT_USED) {
89 if (spat->spat_runtime) {
91 sp = eval(spat->spat_runtime,G_SCALAR,sp);
92 st = stack->ary_array;
93 t = str_get(tmpstr = st[sp--]);
97 deb("2.SPAT /%s/\n",t);
99 if (spat->spat_regexp) {
100 regfree(spat->spat_regexp);
101 spat->spat_regexp = Null(REGEXP*); /* crucial if regcomp aborts */
103 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
104 spat->spat_flags & SPAT_FOLD);
105 if (!spat->spat_regexp->prelen && lastspat)
107 if (spat->spat_flags & SPAT_KEEP) {
108 scanconst(spat,spat->spat_regexp->precomp, spat->spat_regexp->prelen);
109 if (spat->spat_runtime)
110 arg_free(spat->spat_runtime); /* it won't change, so */
111 spat->spat_runtime = Nullarg; /* no point compiling again */
113 if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) {
114 curcmd->c_flags &= ~CF_OPTIMIZE;
115 opt_arg(curcmd, 1, curcmd->c_type == C_EXPR);
119 if (spat->spat_regexp->startp[0]) {
120 s = spat->spat_regexp->endp[0];
123 else if (!spat->spat_regexp->nparens)
124 gimme = G_SCALAR; /* accidental array context? */
125 if (regexec(spat->spat_regexp, s, strend, s, 0,
126 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
128 if (spat->spat_regexp->subbase || global)
134 if (gimme == G_ARRAY)
136 str_sset(str,&str_no);
147 if (spat->spat_flags & SPAT_ONCE)
151 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
154 if (!spat->spat_regexp->prelen && lastspat)
158 if (global && spat->spat_regexp->startp[0])
159 t = s = spat->spat_regexp->endp[0];
161 if (myhint < s || myhint > strend)
162 fatal("panic: hint in do_match");
164 if (spat->spat_regexp->regback >= 0) {
165 s -= spat->spat_regexp->regback;
172 else if (spat->spat_short) {
173 if (spat->spat_flags & SPAT_SCANFIRST) {
174 if (srchstr->str_pok & SP_STUDIED) {
175 if (screamfirst[spat->spat_short->str_rare] < 0)
177 else if (!(s = screaminstr(srchstr,spat->spat_short)))
179 else if (spat->spat_flags & SPAT_ALL)
183 else if (!(s = fbminstr((unsigned char*)s,
184 (unsigned char*)strend, spat->spat_short)))
187 else if (spat->spat_flags & SPAT_ALL)
189 if (s && spat->spat_regexp->regback >= 0) {
190 ++spat->spat_short->str_u.str_useful;
191 s -= spat->spat_regexp->regback;
198 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
199 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
201 if (--spat->spat_short->str_u.str_useful < 0) {
202 str_free(spat->spat_short);
203 spat->spat_short = Nullstr; /* opt is being useless */
206 if (!spat->spat_regexp->nparens && !global) {
207 gimme = G_SCALAR; /* accidental array context? */
210 if (regexec(spat->spat_regexp, s, strend, t, 0,
211 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
213 if (spat->spat_regexp->subbase || global)
216 if (spat->spat_flags & SPAT_ONCE)
217 spat->spat_flags |= SPAT_USED;
222 spat->spat_regexp->startp[0] = Nullch;
223 if (gimme == G_ARRAY)
225 str_sset(str,&str_no);
234 if (gimme == G_ARRAY) {
237 iters = spat->spat_regexp->nparens;
238 if (global && !iters)
242 if (sp + iters + i >= stack->ary_max) {
243 astore(stack,sp + iters + i, Nullstr);
244 st = stack->ary_array; /* possibly realloced */
247 for (i = !i; i <= iters; i++) {
248 st[++sp] = str_mortal(&str_no);
250 if (s = spat->spat_regexp->startp[i]) {
251 len = spat->spat_regexp->endp[i] - s;
253 str_nset(st[sp],s,len);
261 str_sset(str,&str_yes);
268 ++spat->spat_short->str_u.str_useful;
270 if (spat->spat_flags & SPAT_ONCE)
271 spat->spat_flags |= SPAT_USED;
273 spat->spat_regexp->subbeg = t;
274 spat->spat_regexp->subend = strend;
275 spat->spat_regexp->startp[0] = s;
276 spat->spat_regexp->endp[0] = s + spat->spat_short->str_cur;
283 if (spat->spat_regexp->subbase)
284 Safefree(spat->spat_regexp->subbase);
285 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
286 spat->spat_regexp->subbeg = tmps;
287 spat->spat_regexp->subend = tmps + (strend-t);
288 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
289 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
292 str_sset(str,&str_yes);
298 spat->spat_regexp->startp[0] = Nullch;
299 ++spat->spat_short->str_u.str_useful;
301 spat->spat_regexp->startp[0] = Nullch;
302 if (gimme == G_ARRAY)
304 str_sset(str,&str_no);
311 #pragma intrinsic(memcmp)
312 #endif /* BUGGY_MSC */
315 do_split(str,spat,limit,gimme,arglast)
322 register ARRAY *ary = stack;
323 STR **st = ary->ary_array;
324 register int sp = arglast[0] + 1;
325 register char *s = str_get(st[sp]);
326 char *strend = s + st[sp--]->str_cur;
330 int maxiters = (strend - s) + 10;
333 int origlimit = limit;
337 fatal("panic: do_split");
338 else if (spat->spat_runtime) {
340 sp = eval(spat->spat_runtime,G_SCALAR,sp);
341 st = stack->ary_array;
342 m = str_get(dstr = st[sp--]);
344 if (*m == ' ' && dstr->str_cur == 1) {
345 str_set(dstr,"\\s+");
347 spat->spat_flags |= SPAT_SKIPWHITE;
349 if (spat->spat_regexp) {
350 regfree(spat->spat_regexp);
351 spat->spat_regexp = Null(REGEXP*); /* avoid possible double free */
353 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
354 spat->spat_flags & SPAT_FOLD);
355 if (spat->spat_flags & SPAT_KEEP ||
356 (spat->spat_runtime->arg_type == O_ITEM &&
357 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
358 arg_free(spat->spat_runtime); /* it won't change, so */
359 spat->spat_runtime = Nullarg; /* no point compiling again */
364 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
367 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
368 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
370 if (!(ary->ary_flags & ARF_REAL)) {
371 ary->ary_flags |= ARF_REAL;
372 for (i = ary->ary_fill; i >= 0; i--)
373 ary->ary_array[i] = Nullstr; /* don't free mere refs */
376 sp = -1; /* temporarily switch stacks */
381 if (spat->spat_flags & SPAT_SKIPWHITE) {
386 limit = maxiters + 2;
387 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
390 for (m = s; m < strend && !isSPACE(*m); m++) ;
393 dstr = Str_new(30,m-s);
394 str_nset(dstr,s,m-s);
397 (void)astore(ary, ++sp, dstr);
399 for (s = m + 1; s < strend && isSPACE(*s); s++) ;
402 else if (strEQ("^",spat->spat_regexp->precomp)) {
405 for (m = s; m < strend && *m != '\n'; m++) ;
409 dstr = Str_new(30,m-s);
410 str_nset(dstr,s,m-s);
413 (void)astore(ary, ++sp, dstr);
417 else if (spat->spat_short) {
418 i = spat->spat_short->str_cur;
420 int fold = (spat->spat_flags & SPAT_FOLD);
422 i = *spat->spat_short->str_ptr;
423 if (fold && isUPPER(i))
428 m < strend && *m != i &&
429 (!isUPPER(*m) || tolower(*m) != i);
430 m++) /*SUPPRESS 530*/
433 else /*SUPPRESS 530*/
434 for (m = s; m < strend && *m != i; m++) ;
437 dstr = Str_new(30,m-s);
438 str_nset(dstr,s,m-s);
441 (void)astore(ary, ++sp, dstr);
447 while (s < strend && --limit &&
448 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
452 dstr = Str_new(31,m-s);
453 str_nset(dstr,s,m-s);
456 (void)astore(ary, ++sp, dstr);
462 maxiters += (strend - s) * spat->spat_regexp->nparens;
463 while (s < strend && --limit &&
464 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
465 if (spat->spat_regexp->subbase
466 && spat->spat_regexp->subbase != orig) {
469 orig = spat->spat_regexp->subbase;
471 strend = s + (strend - m);
473 m = spat->spat_regexp->startp[0];
474 dstr = Str_new(32,m-s);
475 str_nset(dstr,s,m-s);
478 (void)astore(ary, ++sp, dstr);
479 if (spat->spat_regexp->nparens) {
480 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
481 s = spat->spat_regexp->startp[i];
482 m = spat->spat_regexp->endp[i];
483 dstr = Str_new(33,m-s);
484 str_nset(dstr,s,m-s);
487 (void)astore(ary, ++sp, dstr);
490 s = spat->spat_regexp->endp[0];
496 iters = sp - arglast[0];
497 if (iters > maxiters)
499 if (s < strend || origlimit) { /* keep field after final delim? */
500 dstr = Str_new(34,strend-s);
501 str_nset(dstr,s,strend-s);
504 (void)astore(ary, ++sp, dstr);
509 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
516 zaps = str_get(afetch(ary,sp,FALSE));
520 while (iters > 0 && (!zapb)) {
523 zaps = str_get(afetch(ary,iters-1,FALSE));
531 if (gimme == G_ARRAY) {
533 astore(stack, arglast[0] + 1 + sp, Nullstr);
534 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
535 return arglast[0] + sp;
539 if (gimme == G_ARRAY)
543 str_numset(str,(double)iters);
550 do_unpack(str,gimme,arglast)
555 STR **st = stack->ary_array;
556 register int sp = arglast[0] + 1;
557 register char *pat = str_get(st[sp++]);
558 register char *s = str_get(st[sp]);
559 char *strend = s + st[sp--]->str_cur;
561 register char *patend = pat + st[sp]->str_cur;
566 /* These must not be in registers: */
573 unsigned short aushort;
575 unsigned long aulong;
577 unsigned quad auquad;
583 unsigned long culong;
586 if (gimme != G_ARRAY) { /* arrange to do first one only */
588 for (patend = pat; !isALPHA(*patend) || *patend == 'x'; patend++) ;
589 if (index("aAbBhH", *patend) || *pat == '%') {
591 while (isDIGIT(*patend) || *patend == '*')
598 while (pat < patend) {
603 else if (*pat == '*') {
604 len = strend - strbeg; /* long enough */
607 else if (isDIGIT(*pat)) {
609 while (isDIGIT(*pat))
610 len = (len * 10) + (*pat++ - '0');
613 len = (datumtype != '@');
618 if (len == 1 && pat[-1] != '1')
627 if (len > strend - s)
628 fatal("@ outside of string");
632 if (len > s - strbeg)
633 fatal("X outside of string");
637 if (len > strend - s)
638 fatal("x outside of string");
643 if (len > strend - s)
647 str = Str_new(35,len);
650 if (datumtype == 'A') {
651 aptr = s; /* borrow register */
652 s = str->str_ptr + len - 1;
653 while (s >= str->str_ptr && (!*s || isSPACE(*s)))
656 str->str_cur = s - str->str_ptr;
657 s = aptr; /* unborrow register */
659 (void)astore(stack, ++sp, str_2mortal(str));
663 if (pat[-1] == '*' || len > (strend - s) * 8)
664 len = (strend - s) * 8;
665 str = Str_new(35, len + 1);
668 aptr = pat; /* borrow register */
670 if (datumtype == 'b') {
672 for (len = 0; len < aint; len++) {
673 if (len & 7) /*SUPPRESS 595*/
677 *pat++ = '0' + (bits & 1);
682 for (len = 0; len < aint; len++) {
687 *pat++ = '0' + ((bits & 128) != 0);
691 pat = aptr; /* unborrow register */
692 (void)astore(stack, ++sp, str_2mortal(str));
696 if (pat[-1] == '*' || len > (strend - s) * 2)
697 len = (strend - s) * 2;
698 str = Str_new(35, len + 1);
701 aptr = pat; /* borrow register */
703 if (datumtype == 'h') {
705 for (len = 0; len < aint; len++) {
710 *pat++ = hexdigit[bits & 15];
715 for (len = 0; len < aint; len++) {
720 *pat++ = hexdigit[(bits >> 4) & 15];
724 pat = aptr; /* unborrow register */
725 (void)astore(stack, ++sp, str_2mortal(str));
728 if (len > strend - s)
733 if (aint >= 128) /* fake up signed chars */
741 if (aint >= 128) /* fake up signed chars */
744 str_numset(str,(double)aint);
745 (void)astore(stack, ++sp, str_2mortal(str));
750 if (len > strend - s)
763 str_numset(str,(double)auint);
764 (void)astore(stack, ++sp, str_2mortal(str));
769 along = (strend - s) / sizeof(short);
774 bcopy(s,(char*)&ashort,sizeof(short));
781 bcopy(s,(char*)&ashort,sizeof(short));
784 str_numset(str,(double)ashort);
785 (void)astore(stack, ++sp, str_2mortal(str));
791 along = (strend - s) / sizeof(unsigned short);
796 bcopy(s,(char*)&aushort,sizeof(unsigned short));
797 s += sizeof(unsigned short);
799 if (datumtype == 'n')
800 aushort = ntohs(aushort);
807 bcopy(s,(char*)&aushort,sizeof(unsigned short));
808 s += sizeof(unsigned short);
811 if (datumtype == 'n')
812 aushort = ntohs(aushort);
814 str_numset(str,(double)aushort);
815 (void)astore(stack, ++sp, str_2mortal(str));
820 along = (strend - s) / sizeof(int);
825 bcopy(s,(char*)&aint,sizeof(int));
828 cdouble += (double)aint;
835 bcopy(s,(char*)&aint,sizeof(int));
838 str_numset(str,(double)aint);
839 (void)astore(stack, ++sp, str_2mortal(str));
844 along = (strend - s) / sizeof(unsigned int);
849 bcopy(s,(char*)&auint,sizeof(unsigned int));
850 s += sizeof(unsigned int);
852 cdouble += (double)auint;
859 bcopy(s,(char*)&auint,sizeof(unsigned int));
860 s += sizeof(unsigned int);
862 str_numset(str,(double)auint);
863 (void)astore(stack, ++sp, str_2mortal(str));
868 along = (strend - s) / sizeof(long);
873 bcopy(s,(char*)&along,sizeof(long));
876 cdouble += (double)along;
883 bcopy(s,(char*)&along,sizeof(long));
886 str_numset(str,(double)along);
887 (void)astore(stack, ++sp, str_2mortal(str));
893 along = (strend - s) / sizeof(unsigned long);
898 bcopy(s,(char*)&aulong,sizeof(unsigned long));
899 s += sizeof(unsigned long);
901 if (datumtype == 'N')
902 aulong = ntohl(aulong);
905 cdouble += (double)aulong;
912 bcopy(s,(char*)&aulong,sizeof(unsigned long));
913 s += sizeof(unsigned long);
916 if (datumtype == 'N')
917 aulong = ntohl(aulong);
919 str_numset(str,(double)aulong);
920 (void)astore(stack, ++sp, str_2mortal(str));
925 along = (strend - s) / sizeof(char*);
929 if (sizeof(char*) > strend - s)
932 bcopy(s,(char*)&aptr,sizeof(char*));
938 (void)astore(stack, ++sp, str_2mortal(str));
944 if (s + sizeof(quad) > strend)
947 bcopy(s,(char*)&aquad,sizeof(quad));
951 str_numset(str,(double)aquad);
952 (void)astore(stack, ++sp, str_2mortal(str));
957 if (s + sizeof(unsigned quad) > strend)
960 bcopy(s,(char*)&auquad,sizeof(unsigned quad));
961 s += sizeof(unsigned quad);
964 str_numset(str,(double)auquad);
965 (void)astore(stack, ++sp, str_2mortal(str));
969 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
972 along = (strend - s) / sizeof(float);
977 bcopy(s, (char *)&afloat, sizeof(float));
984 bcopy(s, (char *)&afloat, sizeof(float));
986 str = Str_new(47, 0);
987 str_numset(str, (double)afloat);
988 (void)astore(stack, ++sp, str_2mortal(str));
994 along = (strend - s) / sizeof(double);
999 bcopy(s, (char *)&adouble, sizeof(double));
1000 s += sizeof(double);
1006 bcopy(s, (char *)&adouble, sizeof(double));
1007 s += sizeof(double);
1008 str = Str_new(48, 0);
1009 str_numset(str, (double)adouble);
1010 (void)astore(stack, ++sp, str_2mortal(str));
1015 along = (strend - s) * 3 / 4;
1016 str = Str_new(42,along);
1017 while (s < strend && *s > ' ' && *s < 'a') {
1022 len = (*s++ - ' ') & 077;
1024 if (s < strend && *s >= ' ')
1025 a = (*s++ - ' ') & 077;
1028 if (s < strend && *s >= ' ')
1029 b = (*s++ - ' ') & 077;
1032 if (s < strend && *s >= ' ')
1033 c = (*s++ - ' ') & 077;
1036 if (s < strend && *s >= ' ')
1037 d = (*s++ - ' ') & 077;
1040 hunk[0] = a << 2 | b >> 4;
1041 hunk[1] = b << 4 | c >> 2;
1042 hunk[2] = c << 6 | d;
1043 str_ncat(str,hunk, len > 3 ? 3 : len);
1048 else if (s[1] == '\n') /* possible checksum byte */
1051 (void)astore(stack, ++sp, str_2mortal(str));
1055 str = Str_new(42,0);
1056 if (index("fFdD", datumtype) ||
1057 (checksum > 32 && index("iIlLN", datumtype)) ) {
1062 while (checksum >= 16) {
1066 while (checksum >= 4) {
1072 along = (1 << checksum) - 1;
1073 while (cdouble < 0.0)
1075 cdouble = modf(cdouble / adouble, &trouble) * adouble;
1076 str_numset(str,cdouble);
1079 if (checksum < 32) {
1080 along = (1 << checksum) - 1;
1081 culong &= (unsigned long)along;
1083 str_numset(str,(double)culong);
1085 (void)astore(stack, ++sp, str_2mortal(str));
1093 do_slice(stab,str,numarray,lval,gimme,arglast)
1101 register STR **st = stack->ary_array;
1102 register int sp = arglast[1];
1103 register int max = arglast[2];
1104 register char *tmps;
1106 register int magic = 0;
1107 register ARRAY *ary;
1108 register HASH *hash;
1109 int oldarybase = arybase;
1112 if (numarray == 2) { /* a slice of a LIST */
1114 ary->ary_fill = arglast[3];
1116 st[sp] = str; /* make stack size available */
1117 str_numset(str,(double)(sp - 1));
1120 ary = stab_array(stab); /* a slice of an array */
1124 if (stab == envstab)
1126 else if (stab == sigstab)
1129 else if (stab_hash(stab)->tbl_dbm)
1131 #endif /* SOME_DBM */
1133 hash = stab_hash(stab); /* a slice of an associative array */
1136 if (gimme == G_ARRAY) {
1140 st[sp-1] = afetch(ary,
1141 ((int)str_gnum(st[sp])) - arybase, lval);
1144 st[sp-1] = &str_undef;
1150 tmps = str_get(st[sp]);
1151 len = st[sp]->str_cur;
1152 st[sp-1] = hfetch(hash,tmps,len, lval);
1154 str_magic(st[sp-1],stab,magic,tmps,len);
1157 st[sp-1] = &str_undef;
1165 st[sp] = afetch(ary,
1166 ((int)str_gnum(st[max])) - arybase, lval);
1168 st[sp] = &str_undef;
1172 tmps = str_get(st[max]);
1173 len = st[max]->str_cur;
1174 st[sp] = hfetch(hash,tmps,len, lval);
1176 str_magic(st[sp],stab,magic,tmps,len);
1179 st[sp] = &str_undef;
1182 arybase = oldarybase;
1187 do_splice(ary,gimme,arglast)
1188 register ARRAY *ary;
1192 register STR **st = stack->ary_array;
1193 register int sp = arglast[1];
1194 int max = arglast[2] + 1;
1198 register int offset;
1199 register int length;
1206 offset = ((int)str_gnum(st[sp])) - arybase;
1208 offset += ary->ary_fill + 1;
1210 length = (int)str_gnum(st[sp++]);
1215 length = ary->ary_max + 1; /* close enough to infinity */
1219 length = ary->ary_max + 1;
1227 if (offset > ary->ary_fill + 1)
1228 offset = ary->ary_fill + 1;
1229 after = ary->ary_fill + 1 - (offset + length);
1230 if (after < 0) { /* not that much array */
1231 length += after; /* offset+length now in array */
1233 if (!ary->ary_alloc) {
1239 /* At this point, sp .. max-1 is our new LIST */
1242 diff = newlen - length;
1244 if (diff < 0) { /* shrinking the area */
1246 New(451, tmparyval, newlen, STR*); /* so remember insertion */
1247 Copy(st+sp, tmparyval, newlen, STR*);
1250 sp = arglast[0] + 1;
1251 if (gimme == G_ARRAY) { /* copy return vals to stack */
1252 if (sp + length >= stack->ary_max) {
1253 astore(stack,sp + length, Nullstr);
1254 st = stack->ary_array;
1256 Copy(ary->ary_array+offset, st+sp, length, STR*);
1257 if (ary->ary_flags & ARF_REAL) {
1258 for (i = length, dst = st+sp; i; i--)
1259 str_2mortal(*dst++); /* free them eventualy */
1264 st[sp] = ary->ary_array[offset+length-1];
1265 if (ary->ary_flags & ARF_REAL)
1266 str_2mortal(st[sp]);
1268 ary->ary_fill += diff;
1270 /* pull up or down? */
1272 if (offset < after) { /* easier to pull up */
1273 if (offset) { /* esp. if nothing to pull */
1274 src = &ary->ary_array[offset-1];
1275 dst = src - diff; /* diff is negative */
1276 for (i = offset; i > 0; i--) /* can't trust Copy */
1279 Zero(ary->ary_array, -diff, STR*);
1280 ary->ary_array -= diff; /* diff is negative */
1281 ary->ary_max += diff;
1284 if (after) { /* anything to pull down? */
1285 src = ary->ary_array + offset + length;
1286 dst = src + diff; /* diff is negative */
1287 Copy(src, dst, after, STR*);
1289 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
1290 /* avoid later double free */
1293 for (src = tmparyval, dst = ary->ary_array + offset;
1295 *dst = Str_new(46,0);
1296 str_sset(*dst++,*src++);
1298 Safefree(tmparyval);
1301 else { /* no, expanding (or same) */
1303 New(452, tmparyval, length, STR*); /* so remember deletion */
1304 Copy(ary->ary_array+offset, tmparyval, length, STR*);
1307 if (diff > 0) { /* expanding */
1309 /* push up or down? */
1311 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
1313 src = ary->ary_array;
1315 Copy(src, dst, offset, STR*);
1317 ary->ary_array -= diff; /* diff is positive */
1318 ary->ary_max += diff;
1319 ary->ary_fill += diff;
1322 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
1323 astore(ary, ary->ary_fill + diff, Nullstr);
1325 ary->ary_fill += diff;
1327 dst = ary->ary_array + ary->ary_fill;
1329 for (i = after; i; i--) {
1330 if (*dst) /* str was hanging around */
1331 str_free(*dst); /* after $#foo */
1339 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
1340 *dst = Str_new(46,0);
1341 str_sset(*dst++,*src++);
1343 sp = arglast[0] + 1;
1344 if (gimme == G_ARRAY) { /* copy return vals to stack */
1346 Copy(tmparyval, st+sp, length, STR*);
1347 if (ary->ary_flags & ARF_REAL) {
1348 for (i = length, dst = st+sp; i; i--)
1349 str_2mortal(*dst++); /* free them eventualy */
1351 Safefree(tmparyval);
1356 st[sp] = tmparyval[length-1];
1357 if (ary->ary_flags & ARF_REAL)
1358 str_2mortal(st[sp]);
1359 Safefree(tmparyval);
1362 st[sp] = &str_undef;
1368 do_grep(arg,str,gimme,arglast)
1374 STR **st = stack->ary_array;
1375 register int dst = arglast[1];
1376 register int src = dst + 1;
1377 register int sp = arglast[2];
1378 register int i = sp - arglast[1];
1379 int oldsave = savestack->ary_fill;
1380 SPAT *oldspat = curspat;
1381 int oldtmps_base = tmps_base;
1383 savesptr(&stab_val(defstab));
1384 tmps_base = tmps_max;
1385 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
1386 arg[1].arg_type &= A_MASK;
1388 arg[1].arg_type |= A_DONT;
1390 arg = arg[1].arg_ptr.arg_arg;
1393 st[src]->str_pok &= ~SP_TEMP;
1394 stab_val(defstab) = st[src];
1397 stab_val(defstab) = str_mortal(&str_undef);
1398 (void)eval(arg,G_SCALAR,sp);
1399 st = stack->ary_array;
1400 if (str_true(st[sp+1]))
1401 st[dst++] = st[src];
1405 restorelist(oldsave);
1406 tmps_base = oldtmps_base;
1407 if (gimme != G_ARRAY) {
1408 str_numset(str,(double)(dst - arglast[1]));
1410 st[arglast[0]+1] = str;
1411 return arglast[0]+1;
1413 return arglast[0] + (dst - arglast[1]);
1420 STR **st = stack->ary_array;
1421 register STR **up = &st[arglast[1]];
1422 register STR **down = &st[arglast[2]];
1423 register int i = arglast[2] - arglast[1];
1430 i = arglast[2] - arglast[1];
1431 Copy(down+1,up,i/2,STR*);
1432 return arglast[2] - 1;
1436 do_sreverse(str,arglast)
1440 STR **st = stack->ary_array;
1442 register char *down;
1445 str_sset(str,st[arglast[2]]);
1447 if (str->str_cur > 1) {
1448 down = str->str_ptr + str->str_cur - 1;
1456 st[arglast[0]+1] = str;
1457 return arglast[0]+1;
1460 static CMD *sortcmd;
1461 static HASH *sortstash = Null(HASH*);
1462 static STAB *firststab = Nullstab;
1463 static STAB *secondstab = Nullstab;
1466 do_sort(str,arg,gimme,arglast)
1472 register STR **st = stack->ary_array;
1473 int sp = arglast[1];
1475 register int max = arglast[2] - sp;
1483 static ARRAY *sortstack = Null(ARRAY*);
1485 if (gimme != G_ARRAY) {
1486 str_sset(str,&str_undef);
1492 st += sp; /* temporarily make st point to args */
1493 for (i = 1; i <= max; i++) {
1496 if (!(*up)->str_pok)
1497 (void)str_2ptr(*up);
1499 (*up)->str_pok &= ~SP_TEMP;
1509 if (arg[1].arg_type == (A_CMD|A_DONT)) {
1510 sortcmd = arg[1].arg_ptr.arg_cmd;
1511 stash = curcmd->c_stash;
1514 if ((arg[1].arg_type & A_MASK) == A_WORD)
1515 stab = arg[1].arg_ptr.arg_stab;
1517 stab = stabent(str_get(st[sp+1]),TRUE);
1520 if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd))
1521 fatal("Undefined subroutine \"%s\" in sort",
1523 stash = stab_stash(stab);
1530 int oldtmps_base = tmps_base;
1533 sortstack = anew(Nullstab);
1534 astore(sortstack, 0, Nullstr);
1536 sortstack->ary_flags = 0;
1540 tmps_base = tmps_max;
1541 if (sortstash != stash) {
1542 firststab = stabent("a",TRUE);
1543 secondstab = stabent("b",TRUE);
1546 oldfirst = stab_val(firststab);
1547 oldsecond = stab_val(secondstab);
1549 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1551 qsort(Nullch,max,sizeof(STR*),sortsub);
1553 stab_val(firststab) = oldfirst;
1554 stab_val(secondstab) = oldsecond;
1555 tmps_base = oldtmps_base;
1560 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1571 stab_val(firststab) = *str1;
1572 stab_val(secondstab) = *str2;
1573 cmd_exec(sortcmd,G_SCALAR,-1);
1574 return (int)str_gnum(*stack->ary_array);
1577 sortcmp(strp1,strp2)
1581 register STR *str1 = *strp1;
1582 register STR *str2 = *strp2;
1585 if (str1->str_cur < str2->str_cur) {
1587 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1593 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1595 else if (str1->str_cur == str2->str_cur)
1602 do_range(gimme,arglast)
1606 STR **st = stack->ary_array;
1607 register int sp = arglast[0];
1609 register ARRAY *ary = stack;
1613 if (gimme != G_ARRAY)
1614 fatal("panic: do_range");
1616 if (st[sp+1]->str_nok || !st[sp+1]->str_pok ||
1617 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1618 i = (int)str_gnum(st[sp+1]);
1619 max = (int)str_gnum(st[sp+2]);
1621 (void)astore(ary, sp + max - i + 1, Nullstr);
1623 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1624 str_numset(str,(double)i++);
1628 STR *final = str_mortal(st[sp+2]);
1629 char *tmps = str_get(final);
1631 str = str_mortal(st[sp+1]);
1632 while (!str->str_nok && str->str_cur <= final->str_cur &&
1633 strNE(str->str_ptr,tmps) ) {
1634 (void)astore(ary, ++sp, str);
1635 str = str_2mortal(str_smake(str));
1638 if (strEQ(str->str_ptr,tmps))
1639 (void)astore(ary, ++sp, str);
1645 do_repeatary(arglast)
1648 STR **st = stack->ary_array;
1649 register int sp = arglast[0];
1650 register int items = arglast[1] - sp;
1651 register int count = (int) str_gnum(st[arglast[2]]);
1655 max = items * count;
1656 if (max > 0 && sp + max > stack->ary_max) {
1657 astore(stack, sp + max, Nullstr);
1658 st = stack->ary_array;
1661 for (i = arglast[1]; i > sp; i--)
1662 st[i]->str_pok &= ~SP_TEMP;
1663 repeatcpy((char*)&st[arglast[1]+1], (char*)&st[sp+1],
1664 items * sizeof(STR*), count);
1672 do_caller(arg,maxarg,gimme,arglast)
1678 STR **st = stack->ary_array;
1679 register int sp = arglast[0];
1680 register CSV *csv = curcsv;
1685 fatal("There is no caller");
1687 count = (int) str_gnum(st[sp+1]);
1691 if (DBsub && csv->curcsv && csv->curcsv->sub == stab_sub(DBsub))
1697 if (gimme != G_ARRAY) {
1698 STR *str = arg->arg_ptr.arg_str;
1699 str_set(str,csv->curcmd->c_stash->tbl_name);
1706 (void)astore(stack,++sp,
1707 str_2mortal(str_make(csv->curcmd->c_stash->tbl_name,0)) );
1708 (void)astore(stack,++sp,
1709 str_2mortal(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) );
1710 (void)astore(stack,++sp,
1711 str_2mortal(str_nmake((double)csv->curcmd->c_line)) );
1714 str = Str_new(49,0);
1715 stab_fullname(str, csv->stab);
1716 (void)astore(stack,++sp, str_2mortal(str));
1717 (void)astore(stack,++sp,
1718 str_2mortal(str_nmake((double)csv->hasargs)) );
1719 (void)astore(stack,++sp,
1720 str_2mortal(str_nmake((double)csv->wantarray)) );
1722 ARRAY *ary = csv->argarray;
1725 dbargs = stab_xarray(aadd(stabent("DB'args", TRUE)));
1726 if (dbargs->ary_max < ary->ary_fill)
1727 astore(dbargs,ary->ary_fill,Nullstr);
1728 Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*);
1729 dbargs->ary_fill = ary->ary_fill;
1732 (void)astore(stack,++sp,
1733 str_2mortal(str_make("",0)));
1739 do_tms(str,gimme,arglast)
1747 STR **st = stack->ary_array;
1748 register int sp = arglast[0];
1750 if (gimme != G_ARRAY) {
1751 str_sset(str,&str_undef);
1756 (void)times(×buf);
1763 (void)astore(stack,++sp,
1764 str_2mortal(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1765 (void)astore(stack,++sp,
1766 str_2mortal(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1767 (void)astore(stack,++sp,
1768 str_2mortal(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1769 (void)astore(stack,++sp,
1770 str_2mortal(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1772 (void)astore(stack,++sp,
1773 str_2mortal(str_nmake(0.0)));
1780 do_time(str,tmbuf,gimme,arglast)
1786 register ARRAY *ary = stack;
1787 STR **st = ary->ary_array;
1788 register int sp = arglast[0];
1790 if (!tmbuf || gimme != G_ARRAY) {
1791 str_sset(str,&str_undef);
1796 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_sec)));
1797 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_min)));
1798 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_hour)));
1799 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mday)));
1800 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mon)));
1801 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_year)));
1802 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_wday)));
1803 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_yday)));
1804 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_isdst)));
1809 do_kv(str,hash,kv,gimme,arglast)
1816 register ARRAY *ary = stack;
1817 STR **st = ary->ary_array;
1818 register int sp = arglast[0];
1820 register HENT *entry;
1823 int dokeys = (kv == O_KEYS || kv == O_HASH);
1824 int dovalues = (kv == O_VALUES || kv == O_HASH);
1826 if (gimme != G_ARRAY) {
1827 str_sset(str,&str_undef);
1832 (void)hiterinit(hash);
1834 while (entry = hiternext(hash)) {
1836 tmps = hiterkey(entry,&i);
1839 (void)astore(ary,++sp,str_2mortal(str_make(tmps,i)));
1842 tmpstr = Str_new(45,0);
1845 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1846 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1847 str_set(tmpstr,buf);
1851 str_sset(tmpstr,hiterval(hash,entry));
1852 (void)astore(ary,++sp,str_2mortal(tmpstr));
1859 do_each(str,hash,gimme,arglast)
1865 STR **st = stack->ary_array;
1866 register int sp = arglast[0];
1867 static STR *mystrk = Nullstr;
1868 HENT *entry = hiternext(hash);
1878 if (gimme == G_ARRAY) {
1879 tmps = hiterkey(entry, &i);
1882 st[++sp] = mystrk = str_make(tmps,i);
1885 str_sset(str,hiterval(hash,entry));