1 /* $RCSfile: dolist.c,v $$Revision: 4.0.1.2 $$Date: 91/06/10 01:22:15 $
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.2 91/06/10 01:22:15 lwall
10 * patch10: //g only worked first time through
12 * Revision 4.0.1.1 91/06/07 10:58:28 lwall
13 * patch4: new copyright notice
14 * patch4: added global modifier for pattern matches
15 * patch4: // wouldn't use previous pattern if it started with a null character
16 * patch4: //o and s///o now optimize themselves fully at runtime
17 * patch4: $` was busted inside s///
18 * patch4: caller($arg) didn't work except under debugger
20 * Revision 4.0 91/03/20 01:08:03 lwall
30 #pragma function(memcmp)
31 #endif /* BUGGY_MSC */
34 do_match(str,arg,gimme,arglast)
40 register STR **st = stack->ary_array;
41 register SPAT *spat = arg[2].arg_ptr.arg_spat;
43 register int sp = arglast[0] + 1;
44 STR *srchstr = st[sp];
45 register char *s = str_get(st[sp]);
46 char *strend = s + st[sp]->str_cur;
61 global = spat->spat_flags & SPAT_GLOBAL;
62 safebase = (gimme == G_ARRAY) || global;
64 fatal("panic: do_match");
65 if (spat->spat_flags & SPAT_USED) {
78 if (spat->spat_runtime) {
80 sp = eval(spat->spat_runtime,G_SCALAR,sp);
81 st = stack->ary_array;
82 t = str_get(tmpstr = st[sp--]);
86 deb("2.SPAT /%s/\n",t);
88 if (spat->spat_regexp) {
89 regfree(spat->spat_regexp);
90 spat->spat_regexp = Null(REGEXP*); /* crucial if regcomp aborts */
92 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
93 spat->spat_flags & SPAT_FOLD);
94 if (!spat->spat_regexp->prelen && lastspat)
96 if (spat->spat_flags & SPAT_KEEP) {
97 if (spat->spat_runtime)
98 arg_free(spat->spat_runtime); /* it won't change, so */
99 spat->spat_runtime = Nullarg; /* no point compiling again */
100 scanconst(spat, t, tmpstr->str_cur);
102 if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) {
103 curcmd->c_flags &= ~CF_OPTIMIZE;
104 opt_arg(curcmd, 1, curcmd->c_type == C_EXPR);
108 if (spat->spat_regexp->startp[0]) {
109 s = spat->spat_regexp->endp[0];
112 else if (!spat->spat_regexp->nparens)
113 gimme = G_SCALAR; /* accidental array context? */
114 if (regexec(spat->spat_regexp, s, strend, s, 0,
115 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
117 if (spat->spat_regexp->subbase || global)
123 if (gimme == G_ARRAY)
125 str_sset(str,&str_no);
136 if (spat->spat_flags & SPAT_ONCE)
140 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
143 if (!spat->spat_regexp->prelen && lastspat)
147 if (global && spat->spat_regexp->startp[0])
148 s = spat->spat_regexp->endp[0];
150 if (myhint < s || myhint > strend)
151 fatal("panic: hint in do_match");
153 if (spat->spat_regexp->regback >= 0) {
154 s -= spat->spat_regexp->regback;
161 else if (spat->spat_short) {
162 if (spat->spat_flags & SPAT_SCANFIRST) {
163 if (srchstr->str_pok & SP_STUDIED) {
164 if (screamfirst[spat->spat_short->str_rare] < 0)
166 else if (!(s = screaminstr(srchstr,spat->spat_short)))
168 else if (spat->spat_flags & SPAT_ALL)
172 else if (!(s = fbminstr((unsigned char*)s,
173 (unsigned char*)strend, spat->spat_short)))
176 else if (spat->spat_flags & SPAT_ALL)
178 if (s && spat->spat_regexp->regback >= 0) {
179 ++spat->spat_short->str_u.str_useful;
180 s -= spat->spat_regexp->regback;
187 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
188 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
190 if (--spat->spat_short->str_u.str_useful < 0) {
191 str_free(spat->spat_short);
192 spat->spat_short = Nullstr; /* opt is being useless */
195 if (!spat->spat_regexp->nparens && !global)
196 gimme = G_SCALAR; /* accidental array context? */
197 if (regexec(spat->spat_regexp, s, strend, t, 0,
198 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
200 if (spat->spat_regexp->subbase || global)
203 if (spat->spat_flags & SPAT_ONCE)
204 spat->spat_flags |= SPAT_USED;
209 spat->spat_regexp->startp[0] = Nullch;
210 if (gimme == G_ARRAY)
212 str_sset(str,&str_no);
221 if (gimme == G_ARRAY) {
224 iters = spat->spat_regexp->nparens;
225 if (global && !iters)
229 if (sp + iters + i >= stack->ary_max) {
230 astore(stack,sp + iters + i, Nullstr);
231 st = stack->ary_array; /* possibly realloced */
234 for (i = !i; i <= iters; i++) {
235 st[++sp] = str_mortal(&str_no);
236 if (s = spat->spat_regexp->startp[i]) {
237 len = spat->spat_regexp->endp[i] - s;
239 str_nset(st[sp],s,len);
247 str_sset(str,&str_yes);
254 ++spat->spat_short->str_u.str_useful;
256 if (spat->spat_flags & SPAT_ONCE)
257 spat->spat_flags |= SPAT_USED;
259 spat->spat_regexp->startp[0] = s;
260 spat->spat_regexp->endp[0] = s + spat->spat_short->str_cur;
267 if (spat->spat_regexp->subbase)
268 Safefree(spat->spat_regexp->subbase);
269 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
270 spat->spat_regexp->subbeg = tmps;
271 spat->spat_regexp->subend = tmps + (strend-t);
272 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
273 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
276 str_sset(str,&str_yes);
282 spat->spat_regexp->startp[0] = Nullch;
283 ++spat->spat_short->str_u.str_useful;
285 spat->spat_regexp->startp[0] = Nullch;
286 if (gimme == G_ARRAY)
288 str_sset(str,&str_no);
295 #pragma intrinsic(memcmp)
296 #endif /* BUGGY_MSC */
299 do_split(str,spat,limit,gimme,arglast)
306 register ARRAY *ary = stack;
307 STR **st = ary->ary_array;
308 register int sp = arglast[0] + 1;
309 register char *s = str_get(st[sp]);
310 char *strend = s + st[sp--]->str_cur;
314 int maxiters = (strend - s) + 10;
317 int origlimit = limit;
321 fatal("panic: do_split");
322 else if (spat->spat_runtime) {
324 sp = eval(spat->spat_runtime,G_SCALAR,sp);
325 st = stack->ary_array;
326 m = str_get(dstr = st[sp--]);
328 if (*m == ' ' && dstr->str_cur == 1) {
329 str_set(dstr,"\\s+");
331 spat->spat_flags |= SPAT_SKIPWHITE;
333 if (spat->spat_regexp) {
334 regfree(spat->spat_regexp);
335 spat->spat_regexp = Null(REGEXP*); /* avoid possible double free */
337 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
338 spat->spat_flags & SPAT_FOLD);
339 if (spat->spat_flags & SPAT_KEEP ||
340 (spat->spat_runtime->arg_type == O_ITEM &&
341 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
342 arg_free(spat->spat_runtime); /* it won't change, so */
343 spat->spat_runtime = Nullarg; /* no point compiling again */
348 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
351 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
352 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
354 if (!(ary->ary_flags & ARF_REAL)) {
355 ary->ary_flags |= ARF_REAL;
356 for (i = ary->ary_fill; i >= 0; i--)
357 ary->ary_array[i] = Nullstr; /* don't free mere refs */
360 sp = -1; /* temporarily switch stacks */
365 if (spat->spat_flags & SPAT_SKIPWHITE) {
366 while (isascii(*s) && isspace(*s))
370 limit = maxiters + 2;
371 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
373 for (m = s; m < strend && !(isascii(*m)&&isspace(*m)); m++) ;
376 dstr = Str_new(30,m-s);
377 str_nset(dstr,s,m-s);
380 (void)astore(ary, ++sp, dstr);
381 for (s = m + 1; s < strend && isascii(*s) && isspace(*s); s++) ;
384 else if (strEQ("^",spat->spat_regexp->precomp)) {
386 for (m = s; m < strend && *m != '\n'; m++) ;
390 dstr = Str_new(30,m-s);
391 str_nset(dstr,s,m-s);
394 (void)astore(ary, ++sp, dstr);
398 else if (spat->spat_short) {
399 i = spat->spat_short->str_cur;
401 int fold = (spat->spat_flags & SPAT_FOLD);
403 i = *spat->spat_short->str_ptr;
404 if (fold && isupper(i))
409 m < strend && *m != i &&
410 (!isupper(*m) || tolower(*m) != i);
415 for (m = s; m < strend && *m != i; m++) ;
418 dstr = Str_new(30,m-s);
419 str_nset(dstr,s,m-s);
422 (void)astore(ary, ++sp, dstr);
428 while (s < strend && --limit &&
429 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
433 dstr = Str_new(31,m-s);
434 str_nset(dstr,s,m-s);
437 (void)astore(ary, ++sp, dstr);
443 maxiters += (strend - s) * spat->spat_regexp->nparens;
444 while (s < strend && --limit &&
445 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
446 if (spat->spat_regexp->subbase
447 && spat->spat_regexp->subbase != orig) {
450 orig = spat->spat_regexp->subbase;
452 strend = s + (strend - m);
454 m = spat->spat_regexp->startp[0];
455 dstr = Str_new(32,m-s);
456 str_nset(dstr,s,m-s);
459 (void)astore(ary, ++sp, dstr);
460 if (spat->spat_regexp->nparens) {
461 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
462 s = spat->spat_regexp->startp[i];
463 m = spat->spat_regexp->endp[i];
464 dstr = Str_new(33,m-s);
465 str_nset(dstr,s,m-s);
468 (void)astore(ary, ++sp, dstr);
471 s = spat->spat_regexp->endp[0];
477 iters = sp - arglast[0];
478 if (iters > maxiters)
480 if (s < strend || origlimit) { /* keep field after final delim? */
481 dstr = Str_new(34,strend-s);
482 str_nset(dstr,s,strend-s);
485 (void)astore(ary, ++sp, dstr);
490 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
497 zaps = str_get(afetch(ary,sp,FALSE));
501 while (iters > 0 && (!zapb)) {
504 zaps = str_get(afetch(ary,iters-1,FALSE));
512 if (gimme == G_ARRAY) {
514 astore(stack, arglast[0] + 1 + sp, Nullstr);
515 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
516 return arglast[0] + sp;
520 if (gimme == G_ARRAY)
524 str_numset(str,(double)iters);
531 do_unpack(str,gimme,arglast)
536 STR **st = stack->ary_array;
537 register int sp = arglast[0] + 1;
538 register char *pat = str_get(st[sp++]);
539 register char *s = str_get(st[sp]);
540 char *strend = s + st[sp--]->str_cur;
542 register char *patend = pat + st[sp]->str_cur;
547 /* These must not be in registers: */
551 unsigned short aushort;
553 unsigned long aulong;
558 unsigned long culong;
561 if (gimme != G_ARRAY) { /* arrange to do first one only */
562 for (patend = pat; !isalpha(*patend); patend++);
563 if (index("aAbBhH", *patend) || *pat == '%') {
565 while (isdigit(*patend) || *patend == '*')
572 while (pat < patend) {
577 else if (*pat == '*') {
578 len = strend - strbeg; /* long enough */
581 else if (isdigit(*pat)) {
583 while (isdigit(*pat))
584 len = (len * 10) + (*pat++ - '0');
587 len = (datumtype != '@');
592 if (len == 1 && pat[-1] != '1')
601 if (len > strend - s)
602 fatal("@ outside of string");
606 if (len > s - strbeg)
607 fatal("X outside of string");
611 if (len > strend - s)
612 fatal("x outside of string");
617 if (len > strend - s)
621 str = Str_new(35,len);
624 if (datumtype == 'A') {
625 aptr = s; /* borrow register */
626 s = str->str_ptr + len - 1;
627 while (s >= str->str_ptr && (!*s || (isascii(*s)&&isspace(*s))))
630 str->str_cur = s - str->str_ptr;
631 s = aptr; /* unborrow register */
633 (void)astore(stack, ++sp, str_2mortal(str));
637 if (pat[-1] == '*' || len > (strend - s) * 8)
638 len = (strend - s) * 8;
639 str = Str_new(35, len + 1);
642 aptr = pat; /* borrow register */
644 if (datumtype == 'b') {
646 for (len = 0; len < aint; len++) {
651 *pat++ = '0' + (bits & 1);
656 for (len = 0; len < aint; len++) {
661 *pat++ = '0' + ((bits & 128) != 0);
665 pat = aptr; /* unborrow register */
666 (void)astore(stack, ++sp, str_2mortal(str));
670 if (pat[-1] == '*' || len > (strend - s) * 2)
671 len = (strend - s) * 2;
672 str = Str_new(35, len + 1);
675 aptr = pat; /* borrow register */
677 if (datumtype == 'h') {
679 for (len = 0; len < aint; len++) {
684 *pat++ = hexdigit[bits & 15];
689 for (len = 0; len < aint; len++) {
694 *pat++ = hexdigit[(bits >> 4) & 15];
698 pat = aptr; /* unborrow register */
699 (void)astore(stack, ++sp, str_2mortal(str));
702 if (len > strend - s)
707 if (aint >= 128) /* fake up signed chars */
715 if (aint >= 128) /* fake up signed chars */
718 str_numset(str,(double)aint);
719 (void)astore(stack, ++sp, str_2mortal(str));
724 if (len > strend - s)
737 str_numset(str,(double)auint);
738 (void)astore(stack, ++sp, str_2mortal(str));
743 along = (strend - s) / sizeof(short);
748 bcopy(s,(char*)&ashort,sizeof(short));
755 bcopy(s,(char*)&ashort,sizeof(short));
758 str_numset(str,(double)ashort);
759 (void)astore(stack, ++sp, str_2mortal(str));
765 along = (strend - s) / sizeof(unsigned short);
770 bcopy(s,(char*)&aushort,sizeof(unsigned short));
771 s += sizeof(unsigned short);
773 if (datumtype == 'n')
774 aushort = ntohs(aushort);
781 bcopy(s,(char*)&aushort,sizeof(unsigned short));
782 s += sizeof(unsigned short);
785 if (datumtype == 'n')
786 aushort = ntohs(aushort);
788 str_numset(str,(double)aushort);
789 (void)astore(stack, ++sp, str_2mortal(str));
794 along = (strend - s) / sizeof(int);
799 bcopy(s,(char*)&aint,sizeof(int));
802 cdouble += (double)aint;
809 bcopy(s,(char*)&aint,sizeof(int));
812 str_numset(str,(double)aint);
813 (void)astore(stack, ++sp, str_2mortal(str));
818 along = (strend - s) / sizeof(unsigned int);
823 bcopy(s,(char*)&auint,sizeof(unsigned int));
824 s += sizeof(unsigned int);
826 cdouble += (double)auint;
833 bcopy(s,(char*)&auint,sizeof(unsigned int));
834 s += sizeof(unsigned int);
836 str_numset(str,(double)auint);
837 (void)astore(stack, ++sp, str_2mortal(str));
842 along = (strend - s) / sizeof(long);
847 bcopy(s,(char*)&along,sizeof(long));
850 cdouble += (double)along;
857 bcopy(s,(char*)&along,sizeof(long));
860 str_numset(str,(double)along);
861 (void)astore(stack, ++sp, str_2mortal(str));
867 along = (strend - s) / sizeof(unsigned long);
872 bcopy(s,(char*)&aulong,sizeof(unsigned long));
873 s += sizeof(unsigned long);
875 if (datumtype == 'N')
876 aulong = ntohl(aulong);
879 cdouble += (double)aulong;
886 bcopy(s,(char*)&aulong,sizeof(unsigned long));
887 s += sizeof(unsigned long);
890 if (datumtype == 'N')
891 aulong = ntohl(aulong);
893 str_numset(str,(double)aulong);
894 (void)astore(stack, ++sp, str_2mortal(str));
899 along = (strend - s) / sizeof(char*);
903 if (sizeof(char*) > strend - s)
906 bcopy(s,(char*)&aptr,sizeof(char*));
912 (void)astore(stack, ++sp, str_2mortal(str));
915 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
918 along = (strend - s) / sizeof(float);
923 bcopy(s, (char *)&afloat, sizeof(float));
930 bcopy(s, (char *)&afloat, sizeof(float));
932 str = Str_new(47, 0);
933 str_numset(str, (double)afloat);
934 (void)astore(stack, ++sp, str_2mortal(str));
940 along = (strend - s) / sizeof(double);
945 bcopy(s, (char *)&adouble, sizeof(double));
952 bcopy(s, (char *)&adouble, sizeof(double));
954 str = Str_new(48, 0);
955 str_numset(str, (double)adouble);
956 (void)astore(stack, ++sp, str_2mortal(str));
961 along = (strend - s) * 3 / 4;
962 str = Str_new(42,along);
963 while (s < strend && *s > ' ' && *s < 'a') {
968 len = (*s++ - ' ') & 077;
970 if (s < strend && *s >= ' ')
971 a = (*s++ - ' ') & 077;
974 if (s < strend && *s >= ' ')
975 b = (*s++ - ' ') & 077;
978 if (s < strend && *s >= ' ')
979 c = (*s++ - ' ') & 077;
982 if (s < strend && *s >= ' ')
983 d = (*s++ - ' ') & 077;
986 hunk[0] = a << 2 | b >> 4;
987 hunk[1] = b << 4 | c >> 2;
988 hunk[2] = c << 6 | d;
989 str_ncat(str,hunk, len > 3 ? 3 : len);
994 else if (s[1] == '\n') /* possible checksum byte */
997 (void)astore(stack, ++sp, str_2mortal(str));
1001 str = Str_new(42,0);
1002 if (index("fFdD", datumtype) ||
1003 (checksum > 32 && index("iIlLN", datumtype)) ) {
1008 while (checksum >= 16) {
1012 while (checksum >= 4) {
1018 along = (1 << checksum) - 1;
1019 while (cdouble < 0.0)
1021 cdouble = modf(cdouble / adouble, &trouble) * adouble;
1022 str_numset(str,cdouble);
1025 if (checksum < 32) {
1026 along = (1 << checksum) - 1;
1027 culong &= (unsigned long)along;
1029 str_numset(str,(double)culong);
1031 (void)astore(stack, ++sp, str_2mortal(str));
1039 do_slice(stab,str,numarray,lval,gimme,arglast)
1047 register STR **st = stack->ary_array;
1048 register int sp = arglast[1];
1049 register int max = arglast[2];
1050 register char *tmps;
1052 register int magic = 0;
1053 register ARRAY *ary;
1054 register HASH *hash;
1055 int oldarybase = arybase;
1058 if (numarray == 2) { /* a slice of a LIST */
1060 ary->ary_fill = arglast[3];
1062 st[sp] = str; /* make stack size available */
1063 str_numset(str,(double)(sp - 1));
1066 ary = stab_array(stab); /* a slice of an array */
1070 if (stab == envstab)
1072 else if (stab == sigstab)
1075 else if (stab_hash(stab)->tbl_dbm)
1077 #endif /* SOME_DBM */
1079 hash = stab_hash(stab); /* a slice of an associative array */
1082 if (gimme == G_ARRAY) {
1086 st[sp-1] = afetch(ary,
1087 ((int)str_gnum(st[sp])) - arybase, lval);
1090 st[sp-1] = &str_undef;
1096 tmps = str_get(st[sp]);
1097 len = st[sp]->str_cur;
1098 st[sp-1] = hfetch(hash,tmps,len, lval);
1100 str_magic(st[sp-1],stab,magic,tmps,len);
1103 st[sp-1] = &str_undef;
1111 st[sp] = afetch(ary,
1112 ((int)str_gnum(st[max])) - arybase, lval);
1114 st[sp] = &str_undef;
1118 tmps = str_get(st[max]);
1119 len = st[max]->str_cur;
1120 st[sp] = hfetch(hash,tmps,len, lval);
1122 str_magic(st[sp],stab,magic,tmps,len);
1125 st[sp] = &str_undef;
1128 arybase = oldarybase;
1133 do_splice(ary,gimme,arglast)
1134 register ARRAY *ary;
1138 register STR **st = stack->ary_array;
1139 register int sp = arglast[1];
1140 int max = arglast[2] + 1;
1144 register int offset;
1145 register int length;
1152 offset = ((int)str_gnum(st[sp])) - arybase;
1154 offset += ary->ary_fill + 1;
1156 length = (int)str_gnum(st[sp++]);
1161 length = ary->ary_max; /* close enough to infinity */
1165 length = ary->ary_max;
1173 if (offset > ary->ary_fill + 1)
1174 offset = ary->ary_fill + 1;
1175 after = ary->ary_fill + 1 - (offset + length);
1176 if (after < 0) { /* not that much array */
1177 length += after; /* offset+length now in array */
1179 if (!ary->ary_alloc) {
1185 /* At this point, sp .. max-1 is our new LIST */
1188 diff = newlen - length;
1190 if (diff < 0) { /* shrinking the area */
1192 New(451, tmparyval, newlen, STR*); /* so remember insertion */
1193 Copy(st+sp, tmparyval, newlen, STR*);
1196 sp = arglast[0] + 1;
1197 if (gimme == G_ARRAY) { /* copy return vals to stack */
1198 if (sp + length >= stack->ary_max) {
1199 astore(stack,sp + length, Nullstr);
1200 st = stack->ary_array;
1202 Copy(ary->ary_array+offset, st+sp, length, STR*);
1203 if (ary->ary_flags & ARF_REAL) {
1204 for (i = length, dst = st+sp; i; i--)
1205 str_2mortal(*dst++); /* free them eventualy */
1210 st[sp] = ary->ary_array[offset+length-1];
1211 if (ary->ary_flags & ARF_REAL)
1212 str_2mortal(st[sp]);
1214 ary->ary_fill += diff;
1216 /* pull up or down? */
1218 if (offset < after) { /* easier to pull up */
1219 if (offset) { /* esp. if nothing to pull */
1220 src = &ary->ary_array[offset-1];
1221 dst = src - diff; /* diff is negative */
1222 for (i = offset; i > 0; i--) /* can't trust Copy */
1225 Zero(ary->ary_array, -diff, STR*);
1226 ary->ary_array -= diff; /* diff is negative */
1227 ary->ary_max += diff;
1230 if (after) { /* anything to pull down? */
1231 src = ary->ary_array + offset + length;
1232 dst = src + diff; /* diff is negative */
1233 Copy(src, dst, after, STR*);
1235 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
1236 /* avoid later double free */
1239 for (src = tmparyval, dst = ary->ary_array + offset;
1241 *dst = Str_new(46,0);
1242 str_sset(*dst++,*src++);
1244 Safefree(tmparyval);
1247 else { /* no, expanding (or same) */
1249 New(452, tmparyval, length, STR*); /* so remember deletion */
1250 Copy(ary->ary_array+offset, tmparyval, length, STR*);
1253 if (diff > 0) { /* expanding */
1255 /* push up or down? */
1257 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
1259 src = ary->ary_array;
1261 Copy(src, dst, offset, STR*);
1263 ary->ary_array -= diff; /* diff is positive */
1264 ary->ary_max += diff;
1265 ary->ary_fill += diff;
1268 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
1269 astore(ary, ary->ary_fill + diff, Nullstr);
1271 ary->ary_fill += diff;
1273 dst = ary->ary_array + ary->ary_fill;
1275 for (i = after; i; i--) {
1276 if (*dst) /* str was hanging around */
1277 str_free(*dst); /* after $#foo */
1285 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
1286 *dst = Str_new(46,0);
1287 str_sset(*dst++,*src++);
1289 sp = arglast[0] + 1;
1290 if (gimme == G_ARRAY) { /* copy return vals to stack */
1292 Copy(tmparyval, st+sp, length, STR*);
1293 if (ary->ary_flags & ARF_REAL) {
1294 for (i = length, dst = st+sp; i; i--)
1295 str_2mortal(*dst++); /* free them eventualy */
1297 Safefree(tmparyval);
1302 st[sp] = tmparyval[length-1];
1303 if (ary->ary_flags & ARF_REAL)
1304 str_2mortal(st[sp]);
1305 Safefree(tmparyval);
1308 st[sp] = &str_undef;
1314 do_grep(arg,str,gimme,arglast)
1320 STR **st = stack->ary_array;
1321 register int dst = arglast[1];
1322 register int src = dst + 1;
1323 register int sp = arglast[2];
1324 register int i = sp - arglast[1];
1325 int oldsave = savestack->ary_fill;
1326 SPAT *oldspat = curspat;
1327 int oldtmps_base = tmps_base;
1329 savesptr(&stab_val(defstab));
1330 tmps_base = tmps_max;
1331 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
1332 arg[1].arg_type &= A_MASK;
1334 arg[1].arg_type |= A_DONT;
1336 arg = arg[1].arg_ptr.arg_arg;
1339 stab_val(defstab) = st[src];
1341 stab_val(defstab) = str_mortal(&str_undef);
1342 (void)eval(arg,G_SCALAR,sp);
1343 st = stack->ary_array;
1344 if (str_true(st[sp+1]))
1345 st[dst++] = st[src];
1349 restorelist(oldsave);
1350 tmps_base = oldtmps_base;
1351 if (gimme != G_ARRAY) {
1352 str_numset(str,(double)(dst - arglast[1]));
1354 st[arglast[0]+1] = str;
1355 return arglast[0]+1;
1357 return arglast[0] + (dst - arglast[1]);
1364 STR **st = stack->ary_array;
1365 register STR **up = &st[arglast[1]];
1366 register STR **down = &st[arglast[2]];
1367 register int i = arglast[2] - arglast[1];
1374 i = arglast[2] - arglast[1];
1375 Copy(down+1,up,i/2,STR*);
1376 return arglast[2] - 1;
1380 do_sreverse(str,arglast)
1384 STR **st = stack->ary_array;
1386 register char *down;
1389 str_sset(str,st[arglast[2]]);
1391 if (str->str_cur > 1) {
1392 down = str->str_ptr + str->str_cur - 1;
1400 st[arglast[0]+1] = str;
1401 return arglast[0]+1;
1404 static CMD *sortcmd;
1405 static HASH *sortstash = Null(HASH*);
1406 static STAB *firststab = Nullstab;
1407 static STAB *secondstab = Nullstab;
1410 do_sort(str,stab,gimme,arglast)
1416 register STR **st = stack->ary_array;
1417 int sp = arglast[1];
1419 register int max = arglast[2] - sp;
1426 static ARRAY *sortstack = Null(ARRAY*);
1428 if (gimme != G_ARRAY) {
1429 str_sset(str,&str_undef);
1435 st += sp; /* temporarily make st point to args */
1436 for (i = 1; i <= max; i++) {
1438 if (!(*up)->str_pok)
1439 (void)str_2ptr(*up);
1441 (*up)->str_pok &= ~SP_TEMP;
1450 int oldtmps_base = tmps_base;
1452 if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd))
1453 fatal("Undefined subroutine \"%s\" in sort", stab_name(stab));
1455 sortstack = anew(Nullstab);
1456 astore(sortstack, 0, Nullstr);
1458 sortstack->ary_flags = 0;
1462 tmps_base = tmps_max;
1463 if (sortstash != stab_stash(stab)) {
1464 firststab = stabent("a",TRUE);
1465 secondstab = stabent("b",TRUE);
1466 sortstash = stab_stash(stab);
1468 oldfirst = stab_val(firststab);
1469 oldsecond = stab_val(secondstab);
1471 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1473 qsort(Nullch,max,sizeof(STR*),sortsub);
1475 stab_val(firststab) = oldfirst;
1476 stab_val(secondstab) = oldsecond;
1477 tmps_base = oldtmps_base;
1482 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1493 stab_val(firststab) = *str1;
1494 stab_val(secondstab) = *str2;
1495 cmd_exec(sortcmd,G_SCALAR,-1);
1496 return (int)str_gnum(*stack->ary_array);
1499 sortcmp(strp1,strp2)
1503 register STR *str1 = *strp1;
1504 register STR *str2 = *strp2;
1507 if (str1->str_cur < str2->str_cur) {
1508 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1513 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1515 else if (str1->str_cur == str2->str_cur)
1522 do_range(gimme,arglast)
1526 STR **st = stack->ary_array;
1527 register int sp = arglast[0];
1529 register ARRAY *ary = stack;
1533 if (gimme != G_ARRAY)
1534 fatal("panic: do_range");
1536 if (st[sp+1]->str_nok || !st[sp+1]->str_pok ||
1537 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1538 i = (int)str_gnum(st[sp+1]);
1539 max = (int)str_gnum(st[sp+2]);
1541 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1542 str_numset(str,(double)i++);
1546 STR *final = str_mortal(st[sp+2]);
1547 char *tmps = str_get(final);
1549 str = str_mortal(st[sp+1]);
1550 while (!str->str_nok && str->str_cur <= final->str_cur &&
1551 strNE(str->str_ptr,tmps) ) {
1552 (void)astore(ary, ++sp, str);
1553 str = str_2mortal(str_smake(str));
1556 if (strEQ(str->str_ptr,tmps))
1557 (void)astore(ary, ++sp, str);
1563 do_repeatary(arglast)
1566 STR **st = stack->ary_array;
1567 register int sp = arglast[0];
1568 register int items = arglast[1] - sp;
1569 register int count = (int) str_gnum(st[arglast[2]]);
1570 register ARRAY *ary = stack;
1574 max = items * count;
1575 if (max > 0 && sp + max > stack->ary_max) {
1576 astore(stack, sp + max, Nullstr);
1577 st = stack->ary_array;
1580 for (i = arglast[1]; i > sp; i--)
1581 st[i]->str_pok &= ~SP_TEMP;
1582 repeatcpy((char*)&st[arglast[1]+1], (char*)&st[sp+1],
1583 items * sizeof(STR*), count);
1591 do_caller(arg,maxarg,gimme,arglast)
1597 STR **st = stack->ary_array;
1598 register int sp = arglast[0];
1599 register CSV *csv = curcsv;
1604 fatal("There is no caller");
1606 count = (int) str_gnum(st[sp+1]);
1610 if (DBsub && csv->curcsv && csv->curcsv->sub == stab_sub(DBsub))
1616 if (gimme != G_ARRAY) {
1617 STR *str = arg->arg_ptr.arg_str;
1618 str_set(str,csv->curcmd->c_stash->tbl_name);
1625 (void)astore(stack,++sp,
1626 str_2mortal(str_make(csv->curcmd->c_stash->tbl_name,0)) );
1627 (void)astore(stack,++sp,
1628 str_2mortal(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) );
1629 (void)astore(stack,++sp,
1630 str_2mortal(str_nmake((double)csv->curcmd->c_line)) );
1633 str = Str_new(49,0);
1634 stab_fullname(str, csv->stab);
1635 (void)astore(stack,++sp, str_2mortal(str));
1636 (void)astore(stack,++sp,
1637 str_2mortal(str_nmake((double)csv->hasargs)) );
1638 (void)astore(stack,++sp,
1639 str_2mortal(str_nmake((double)csv->wantarray)) );
1641 ARRAY *ary = csv->argarray;
1645 dbargs = stab_xarray(aadd(stabent("DB'args", TRUE)));
1646 if (dbargs->ary_max < ary->ary_fill)
1647 astore(dbargs,ary->ary_fill,Nullstr);
1648 Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*);
1649 dbargs->ary_fill = ary->ary_fill;
1652 (void)astore(stack,++sp,
1653 str_2mortal(str_make("",0)));
1659 do_tms(str,gimme,arglast)
1667 STR **st = stack->ary_array;
1668 register int sp = arglast[0];
1670 if (gimme != G_ARRAY) {
1671 str_sset(str,&str_undef);
1676 (void)times(×buf);
1683 (void)astore(stack,++sp,
1684 str_2mortal(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1685 (void)astore(stack,++sp,
1686 str_2mortal(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1687 (void)astore(stack,++sp,
1688 str_2mortal(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1689 (void)astore(stack,++sp,
1690 str_2mortal(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1692 (void)astore(stack,++sp,
1693 str_2mortal(str_nmake(0.0)));
1700 do_time(str,tmbuf,gimme,arglast)
1706 register ARRAY *ary = stack;
1707 STR **st = ary->ary_array;
1708 register int sp = arglast[0];
1710 if (!tmbuf || gimme != G_ARRAY) {
1711 str_sset(str,&str_undef);
1716 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_sec)));
1717 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_min)));
1718 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_hour)));
1719 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mday)));
1720 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mon)));
1721 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_year)));
1722 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_wday)));
1723 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_yday)));
1724 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_isdst)));
1729 do_kv(str,hash,kv,gimme,arglast)
1736 register ARRAY *ary = stack;
1737 STR **st = ary->ary_array;
1738 register int sp = arglast[0];
1740 register HENT *entry;
1743 int dokeys = (kv == O_KEYS || kv == O_HASH);
1744 int dovalues = (kv == O_VALUES || kv == O_HASH);
1746 if (gimme != G_ARRAY) {
1747 str_sset(str,&str_undef);
1752 (void)hiterinit(hash);
1753 while (entry = hiternext(hash)) {
1755 tmps = hiterkey(entry,&i);
1758 (void)astore(ary,++sp,str_2mortal(str_make(tmps,i)));
1761 tmpstr = Str_new(45,0);
1764 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1765 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1766 str_set(tmpstr,buf);
1770 str_sset(tmpstr,hiterval(hash,entry));
1771 (void)astore(ary,++sp,str_2mortal(tmpstr));
1778 do_each(str,hash,gimme,arglast)
1784 STR **st = stack->ary_array;
1785 register int sp = arglast[0];
1786 static STR *mystrk = Nullstr;
1787 HENT *entry = hiternext(hash);
1797 if (gimme == G_ARRAY) {
1798 tmps = hiterkey(entry, &i);
1801 st[++sp] = mystrk = str_make(tmps,i);
1804 str_sset(str,hiterval(hash,entry));