1 /* $RCSfile: dolist.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 10:58:28 $
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.1 91/06/07 10:58:28 lwall
10 * patch4: new copyright notice
11 * patch4: added global modifier for pattern matches
12 * patch4: // wouldn't use previous pattern if it started with a null character
13 * patch4: //o and s///o now optimize themselves fully at runtime
14 * patch4: $` was busted inside s///
15 * patch4: caller($arg) didn't work except under debugger
17 * Revision 4.0 91/03/20 01:08:03 lwall
27 #pragma function(memcmp)
28 #endif /* BUGGY_MSC */
31 do_match(str,arg,gimme,arglast)
37 register STR **st = stack->ary_array;
38 register SPAT *spat = arg[2].arg_ptr.arg_spat;
40 register int sp = arglast[0] + 1;
41 STR *srchstr = st[sp];
42 register char *s = str_get(st[sp]);
43 char *strend = s + st[sp]->str_cur;
58 global = spat->spat_flags & SPAT_GLOBAL;
59 safebase = (gimme == G_ARRAY) || global;
61 fatal("panic: do_match");
62 if (spat->spat_flags & SPAT_USED) {
75 if (spat->spat_runtime) {
77 sp = eval(spat->spat_runtime,G_SCALAR,sp);
78 st = stack->ary_array;
79 t = str_get(tmpstr = st[sp--]);
83 deb("2.SPAT /%s/\n",t);
85 if (spat->spat_regexp) {
86 regfree(spat->spat_regexp);
87 spat->spat_regexp = Null(REGEXP*); /* crucial if regcomp aborts */
89 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
90 spat->spat_flags & SPAT_FOLD);
91 if (!spat->spat_regexp->prelen && lastspat)
93 if (spat->spat_flags & SPAT_KEEP) {
94 if (spat->spat_runtime)
95 arg_free(spat->spat_runtime); /* it won't change, so */
96 spat->spat_runtime = Nullarg; /* no point compiling again */
97 scanconst(spat, t, tmpstr->str_cur);
99 if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) {
100 curcmd->c_flags &= ~CF_OPTIMIZE;
101 opt_arg(curcmd, 1, curcmd->c_type == C_EXPR);
105 if (spat->spat_regexp->startp[0]) {
106 s = spat->spat_regexp->endp[0];
109 else if (!spat->spat_regexp->nparens)
110 gimme = G_SCALAR; /* accidental array context? */
111 if (regexec(spat->spat_regexp, s, strend, s, 0,
112 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
114 if (spat->spat_regexp->subbase || global)
120 if (gimme == G_ARRAY)
122 str_sset(str,&str_no);
133 if (spat->spat_flags & SPAT_ONCE)
137 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
140 if (!spat->spat_regexp->prelen && lastspat)
144 if (global && spat->spat_regexp->startp[0])
145 s = spat->spat_regexp->endp[0];
147 if (myhint < s || myhint > strend)
148 fatal("panic: hint in do_match");
150 if (spat->spat_regexp->regback >= 0) {
151 s -= spat->spat_regexp->regback;
158 else if (spat->spat_short) {
159 if (spat->spat_flags & SPAT_SCANFIRST) {
160 if (srchstr->str_pok & SP_STUDIED) {
161 if (screamfirst[spat->spat_short->str_rare] < 0)
163 else if (!(s = screaminstr(srchstr,spat->spat_short)))
165 else if (spat->spat_flags & SPAT_ALL)
169 else if (!(s = fbminstr((unsigned char*)s,
170 (unsigned char*)strend, spat->spat_short)))
173 else if (spat->spat_flags & SPAT_ALL)
175 if (s && spat->spat_regexp->regback >= 0) {
176 ++spat->spat_short->str_u.str_useful;
177 s -= spat->spat_regexp->regback;
184 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
185 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
187 if (--spat->spat_short->str_u.str_useful < 0) {
188 str_free(spat->spat_short);
189 spat->spat_short = Nullstr; /* opt is being useless */
192 if (!spat->spat_regexp->nparens && !global)
193 gimme = G_SCALAR; /* accidental array context? */
194 if (regexec(spat->spat_regexp, s, strend, t, 0,
195 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
197 if (spat->spat_regexp->subbase || global)
200 if (spat->spat_flags & SPAT_ONCE)
201 spat->spat_flags |= SPAT_USED;
205 if (gimme == G_ARRAY)
207 str_sset(str,&str_no);
216 if (gimme == G_ARRAY) {
219 iters = spat->spat_regexp->nparens;
220 if (global && !iters)
224 if (sp + iters + i >= stack->ary_max) {
225 astore(stack,sp + iters + i, Nullstr);
226 st = stack->ary_array; /* possibly realloced */
229 for (i = !i; i <= iters; i++) {
230 st[++sp] = str_mortal(&str_no);
231 if (s = spat->spat_regexp->startp[i]) {
232 len = spat->spat_regexp->endp[i] - s;
234 str_nset(st[sp],s,len);
242 str_sset(str,&str_yes);
249 ++spat->spat_short->str_u.str_useful;
251 if (spat->spat_flags & SPAT_ONCE)
252 spat->spat_flags |= SPAT_USED;
254 spat->spat_regexp->startp[0] = s;
255 spat->spat_regexp->endp[0] = s + spat->spat_short->str_cur;
262 if (spat->spat_regexp->subbase)
263 Safefree(spat->spat_regexp->subbase);
264 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
265 spat->spat_regexp->subbeg = tmps;
266 spat->spat_regexp->subend = tmps + (strend-t);
267 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
268 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
271 str_sset(str,&str_yes);
277 spat->spat_regexp->startp[0] = Nullch;
278 ++spat->spat_short->str_u.str_useful;
279 if (gimme == G_ARRAY)
281 str_sset(str,&str_no);
288 #pragma intrinsic(memcmp)
289 #endif /* BUGGY_MSC */
292 do_split(str,spat,limit,gimme,arglast)
299 register ARRAY *ary = stack;
300 STR **st = ary->ary_array;
301 register int sp = arglast[0] + 1;
302 register char *s = str_get(st[sp]);
303 char *strend = s + st[sp--]->str_cur;
307 int maxiters = (strend - s) + 10;
310 int origlimit = limit;
314 fatal("panic: do_split");
315 else if (spat->spat_runtime) {
317 sp = eval(spat->spat_runtime,G_SCALAR,sp);
318 st = stack->ary_array;
319 m = str_get(dstr = st[sp--]);
321 if (*m == ' ' && dstr->str_cur == 1) {
322 str_set(dstr,"\\s+");
324 spat->spat_flags |= SPAT_SKIPWHITE;
326 if (spat->spat_regexp) {
327 regfree(spat->spat_regexp);
328 spat->spat_regexp = Null(REGEXP*); /* avoid possible double free */
330 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
331 spat->spat_flags & SPAT_FOLD);
332 if (spat->spat_flags & SPAT_KEEP ||
333 (spat->spat_runtime->arg_type == O_ITEM &&
334 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
335 arg_free(spat->spat_runtime); /* it won't change, so */
336 spat->spat_runtime = Nullarg; /* no point compiling again */
341 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
344 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
345 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
347 if (!(ary->ary_flags & ARF_REAL)) {
348 ary->ary_flags |= ARF_REAL;
349 for (i = ary->ary_fill; i >= 0; i--)
350 ary->ary_array[i] = Nullstr; /* don't free mere refs */
353 sp = -1; /* temporarily switch stacks */
358 if (spat->spat_flags & SPAT_SKIPWHITE) {
359 while (isascii(*s) && isspace(*s))
363 limit = maxiters + 2;
364 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
366 for (m = s; m < strend && !(isascii(*m)&&isspace(*m)); m++) ;
369 dstr = Str_new(30,m-s);
370 str_nset(dstr,s,m-s);
373 (void)astore(ary, ++sp, dstr);
374 for (s = m + 1; s < strend && isascii(*s) && isspace(*s); s++) ;
377 else if (strEQ("^",spat->spat_regexp->precomp)) {
379 for (m = s; m < strend && *m != '\n'; m++) ;
383 dstr = Str_new(30,m-s);
384 str_nset(dstr,s,m-s);
387 (void)astore(ary, ++sp, dstr);
391 else if (spat->spat_short) {
392 i = spat->spat_short->str_cur;
394 int fold = (spat->spat_flags & SPAT_FOLD);
396 i = *spat->spat_short->str_ptr;
397 if (fold && isupper(i))
402 m < strend && *m != i &&
403 (!isupper(*m) || tolower(*m) != i);
408 for (m = s; m < strend && *m != i; m++) ;
411 dstr = Str_new(30,m-s);
412 str_nset(dstr,s,m-s);
415 (void)astore(ary, ++sp, dstr);
421 while (s < strend && --limit &&
422 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
426 dstr = Str_new(31,m-s);
427 str_nset(dstr,s,m-s);
430 (void)astore(ary, ++sp, dstr);
436 maxiters += (strend - s) * spat->spat_regexp->nparens;
437 while (s < strend && --limit &&
438 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
439 if (spat->spat_regexp->subbase
440 && spat->spat_regexp->subbase != orig) {
443 orig = spat->spat_regexp->subbase;
445 strend = s + (strend - m);
447 m = spat->spat_regexp->startp[0];
448 dstr = Str_new(32,m-s);
449 str_nset(dstr,s,m-s);
452 (void)astore(ary, ++sp, dstr);
453 if (spat->spat_regexp->nparens) {
454 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
455 s = spat->spat_regexp->startp[i];
456 m = spat->spat_regexp->endp[i];
457 dstr = Str_new(33,m-s);
458 str_nset(dstr,s,m-s);
461 (void)astore(ary, ++sp, dstr);
464 s = spat->spat_regexp->endp[0];
470 iters = sp - arglast[0];
471 if (iters > maxiters)
473 if (s < strend || origlimit) { /* keep field after final delim? */
474 dstr = Str_new(34,strend-s);
475 str_nset(dstr,s,strend-s);
478 (void)astore(ary, ++sp, dstr);
483 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
490 zaps = str_get(afetch(ary,sp,FALSE));
494 while (iters > 0 && (!zapb)) {
497 zaps = str_get(afetch(ary,iters-1,FALSE));
505 if (gimme == G_ARRAY) {
507 astore(stack, arglast[0] + 1 + sp, Nullstr);
508 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
509 return arglast[0] + sp;
513 if (gimme == G_ARRAY)
517 str_numset(str,(double)iters);
524 do_unpack(str,gimme,arglast)
529 STR **st = stack->ary_array;
530 register int sp = arglast[0] + 1;
531 register char *pat = str_get(st[sp++]);
532 register char *s = str_get(st[sp]);
533 char *strend = s + st[sp--]->str_cur;
535 register char *patend = pat + st[sp]->str_cur;
540 /* These must not be in registers: */
544 unsigned short aushort;
546 unsigned long aulong;
551 unsigned long culong;
554 if (gimme != G_ARRAY) { /* arrange to do first one only */
555 for (patend = pat; !isalpha(*patend); patend++);
556 if (index("aAbBhH", *patend) || *pat == '%') {
558 while (isdigit(*patend) || *patend == '*')
565 while (pat < patend) {
570 else if (*pat == '*') {
571 len = strend - strbeg; /* long enough */
574 else if (isdigit(*pat)) {
576 while (isdigit(*pat))
577 len = (len * 10) + (*pat++ - '0');
580 len = (datumtype != '@');
585 if (len == 1 && pat[-1] != '1')
594 if (len > strend - s)
595 fatal("@ outside of string");
599 if (len > s - strbeg)
600 fatal("X outside of string");
604 if (len > strend - s)
605 fatal("x outside of string");
610 if (len > strend - s)
614 str = Str_new(35,len);
617 if (datumtype == 'A') {
618 aptr = s; /* borrow register */
619 s = str->str_ptr + len - 1;
620 while (s >= str->str_ptr && (!*s || (isascii(*s)&&isspace(*s))))
623 str->str_cur = s - str->str_ptr;
624 s = aptr; /* unborrow register */
626 (void)astore(stack, ++sp, str_2mortal(str));
630 if (pat[-1] == '*' || len > (strend - s) * 8)
631 len = (strend - s) * 8;
632 str = Str_new(35, len + 1);
635 aptr = pat; /* borrow register */
637 if (datumtype == 'b') {
639 for (len = 0; len < aint; len++) {
644 *pat++ = '0' + (bits & 1);
649 for (len = 0; len < aint; len++) {
654 *pat++ = '0' + ((bits & 128) != 0);
658 pat = aptr; /* unborrow register */
659 (void)astore(stack, ++sp, str_2mortal(str));
663 if (pat[-1] == '*' || len > (strend - s) * 2)
664 len = (strend - s) * 2;
665 str = Str_new(35, len + 1);
668 aptr = pat; /* borrow register */
670 if (datumtype == 'h') {
672 for (len = 0; len < aint; len++) {
677 *pat++ = hexdigit[bits & 15];
682 for (len = 0; len < aint; len++) {
687 *pat++ = hexdigit[(bits >> 4) & 15];
691 pat = aptr; /* unborrow register */
692 (void)astore(stack, ++sp, str_2mortal(str));
695 if (len > strend - s)
700 if (aint >= 128) /* fake up signed chars */
708 if (aint >= 128) /* fake up signed chars */
711 str_numset(str,(double)aint);
712 (void)astore(stack, ++sp, str_2mortal(str));
717 if (len > strend - s)
730 str_numset(str,(double)auint);
731 (void)astore(stack, ++sp, str_2mortal(str));
736 along = (strend - s) / sizeof(short);
741 bcopy(s,(char*)&ashort,sizeof(short));
748 bcopy(s,(char*)&ashort,sizeof(short));
751 str_numset(str,(double)ashort);
752 (void)astore(stack, ++sp, str_2mortal(str));
758 along = (strend - s) / sizeof(unsigned short);
763 bcopy(s,(char*)&aushort,sizeof(unsigned short));
764 s += sizeof(unsigned short);
766 if (datumtype == 'n')
767 aushort = ntohs(aushort);
774 bcopy(s,(char*)&aushort,sizeof(unsigned short));
775 s += sizeof(unsigned short);
778 if (datumtype == 'n')
779 aushort = ntohs(aushort);
781 str_numset(str,(double)aushort);
782 (void)astore(stack, ++sp, str_2mortal(str));
787 along = (strend - s) / sizeof(int);
792 bcopy(s,(char*)&aint,sizeof(int));
795 cdouble += (double)aint;
802 bcopy(s,(char*)&aint,sizeof(int));
805 str_numset(str,(double)aint);
806 (void)astore(stack, ++sp, str_2mortal(str));
811 along = (strend - s) / sizeof(unsigned int);
816 bcopy(s,(char*)&auint,sizeof(unsigned int));
817 s += sizeof(unsigned int);
819 cdouble += (double)auint;
826 bcopy(s,(char*)&auint,sizeof(unsigned int));
827 s += sizeof(unsigned int);
829 str_numset(str,(double)auint);
830 (void)astore(stack, ++sp, str_2mortal(str));
835 along = (strend - s) / sizeof(long);
840 bcopy(s,(char*)&along,sizeof(long));
843 cdouble += (double)along;
850 bcopy(s,(char*)&along,sizeof(long));
853 str_numset(str,(double)along);
854 (void)astore(stack, ++sp, str_2mortal(str));
860 along = (strend - s) / sizeof(unsigned long);
865 bcopy(s,(char*)&aulong,sizeof(unsigned long));
866 s += sizeof(unsigned long);
868 if (datumtype == 'N')
869 aulong = ntohl(aulong);
872 cdouble += (double)aulong;
879 bcopy(s,(char*)&aulong,sizeof(unsigned long));
880 s += sizeof(unsigned long);
883 if (datumtype == 'N')
884 aulong = ntohl(aulong);
886 str_numset(str,(double)aulong);
887 (void)astore(stack, ++sp, str_2mortal(str));
892 along = (strend - s) / sizeof(char*);
896 if (sizeof(char*) > strend - s)
899 bcopy(s,(char*)&aptr,sizeof(char*));
905 (void)astore(stack, ++sp, str_2mortal(str));
908 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
911 along = (strend - s) / sizeof(float);
916 bcopy(s, (char *)&afloat, sizeof(float));
923 bcopy(s, (char *)&afloat, sizeof(float));
925 str = Str_new(47, 0);
926 str_numset(str, (double)afloat);
927 (void)astore(stack, ++sp, str_2mortal(str));
933 along = (strend - s) / sizeof(double);
938 bcopy(s, (char *)&adouble, sizeof(double));
945 bcopy(s, (char *)&adouble, sizeof(double));
947 str = Str_new(48, 0);
948 str_numset(str, (double)adouble);
949 (void)astore(stack, ++sp, str_2mortal(str));
954 along = (strend - s) * 3 / 4;
955 str = Str_new(42,along);
956 while (s < strend && *s > ' ' && *s < 'a') {
961 len = (*s++ - ' ') & 077;
963 if (s < strend && *s >= ' ')
964 a = (*s++ - ' ') & 077;
967 if (s < strend && *s >= ' ')
968 b = (*s++ - ' ') & 077;
971 if (s < strend && *s >= ' ')
972 c = (*s++ - ' ') & 077;
975 if (s < strend && *s >= ' ')
976 d = (*s++ - ' ') & 077;
979 hunk[0] = a << 2 | b >> 4;
980 hunk[1] = b << 4 | c >> 2;
981 hunk[2] = c << 6 | d;
982 str_ncat(str,hunk, len > 3 ? 3 : len);
987 else if (s[1] == '\n') /* possible checksum byte */
990 (void)astore(stack, ++sp, str_2mortal(str));
995 if (index("fFdD", datumtype) ||
996 (checksum > 32 && index("iIlLN", datumtype)) ) {
1001 while (checksum >= 16) {
1005 while (checksum >= 4) {
1011 along = (1 << checksum) - 1;
1012 while (cdouble < 0.0)
1014 cdouble = modf(cdouble / adouble, &trouble) * adouble;
1015 str_numset(str,cdouble);
1018 if (checksum < 32) {
1019 along = (1 << checksum) - 1;
1020 culong &= (unsigned long)along;
1022 str_numset(str,(double)culong);
1024 (void)astore(stack, ++sp, str_2mortal(str));
1032 do_slice(stab,str,numarray,lval,gimme,arglast)
1040 register STR **st = stack->ary_array;
1041 register int sp = arglast[1];
1042 register int max = arglast[2];
1043 register char *tmps;
1045 register int magic = 0;
1046 register ARRAY *ary;
1047 register HASH *hash;
1048 int oldarybase = arybase;
1051 if (numarray == 2) { /* a slice of a LIST */
1053 ary->ary_fill = arglast[3];
1055 st[sp] = str; /* make stack size available */
1056 str_numset(str,(double)(sp - 1));
1059 ary = stab_array(stab); /* a slice of an array */
1063 if (stab == envstab)
1065 else if (stab == sigstab)
1068 else if (stab_hash(stab)->tbl_dbm)
1070 #endif /* SOME_DBM */
1072 hash = stab_hash(stab); /* a slice of an associative array */
1075 if (gimme == G_ARRAY) {
1079 st[sp-1] = afetch(ary,
1080 ((int)str_gnum(st[sp])) - arybase, lval);
1083 st[sp-1] = &str_undef;
1089 tmps = str_get(st[sp]);
1090 len = st[sp]->str_cur;
1091 st[sp-1] = hfetch(hash,tmps,len, lval);
1093 str_magic(st[sp-1],stab,magic,tmps,len);
1096 st[sp-1] = &str_undef;
1104 st[sp] = afetch(ary,
1105 ((int)str_gnum(st[max])) - arybase, lval);
1107 st[sp] = &str_undef;
1111 tmps = str_get(st[max]);
1112 len = st[max]->str_cur;
1113 st[sp] = hfetch(hash,tmps,len, lval);
1115 str_magic(st[sp],stab,magic,tmps,len);
1118 st[sp] = &str_undef;
1121 arybase = oldarybase;
1126 do_splice(ary,gimme,arglast)
1127 register ARRAY *ary;
1131 register STR **st = stack->ary_array;
1132 register int sp = arglast[1];
1133 int max = arglast[2] + 1;
1137 register int offset;
1138 register int length;
1145 offset = ((int)str_gnum(st[sp])) - arybase;
1147 offset += ary->ary_fill + 1;
1149 length = (int)str_gnum(st[sp++]);
1154 length = ary->ary_max; /* close enough to infinity */
1158 length = ary->ary_max;
1166 if (offset > ary->ary_fill + 1)
1167 offset = ary->ary_fill + 1;
1168 after = ary->ary_fill + 1 - (offset + length);
1169 if (after < 0) { /* not that much array */
1170 length += after; /* offset+length now in array */
1172 if (!ary->ary_alloc) {
1178 /* At this point, sp .. max-1 is our new LIST */
1181 diff = newlen - length;
1183 if (diff < 0) { /* shrinking the area */
1185 New(451, tmparyval, newlen, STR*); /* so remember insertion */
1186 Copy(st+sp, tmparyval, newlen, STR*);
1189 sp = arglast[0] + 1;
1190 if (gimme == G_ARRAY) { /* copy return vals to stack */
1191 if (sp + length >= stack->ary_max) {
1192 astore(stack,sp + length, Nullstr);
1193 st = stack->ary_array;
1195 Copy(ary->ary_array+offset, st+sp, length, STR*);
1196 if (ary->ary_flags & ARF_REAL) {
1197 for (i = length, dst = st+sp; i; i--)
1198 str_2mortal(*dst++); /* free them eventualy */
1203 st[sp] = ary->ary_array[offset+length-1];
1204 if (ary->ary_flags & ARF_REAL)
1205 str_2mortal(st[sp]);
1207 ary->ary_fill += diff;
1209 /* pull up or down? */
1211 if (offset < after) { /* easier to pull up */
1212 if (offset) { /* esp. if nothing to pull */
1213 src = &ary->ary_array[offset-1];
1214 dst = src - diff; /* diff is negative */
1215 for (i = offset; i > 0; i--) /* can't trust Copy */
1218 Zero(ary->ary_array, -diff, STR*);
1219 ary->ary_array -= diff; /* diff is negative */
1220 ary->ary_max += diff;
1223 if (after) { /* anything to pull down? */
1224 src = ary->ary_array + offset + length;
1225 dst = src + diff; /* diff is negative */
1226 Copy(src, dst, after, STR*);
1228 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
1229 /* avoid later double free */
1232 for (src = tmparyval, dst = ary->ary_array + offset;
1234 *dst = Str_new(46,0);
1235 str_sset(*dst++,*src++);
1237 Safefree(tmparyval);
1240 else { /* no, expanding (or same) */
1242 New(452, tmparyval, length, STR*); /* so remember deletion */
1243 Copy(ary->ary_array+offset, tmparyval, length, STR*);
1246 if (diff > 0) { /* expanding */
1248 /* push up or down? */
1250 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
1252 src = ary->ary_array;
1254 Copy(src, dst, offset, STR*);
1256 ary->ary_array -= diff; /* diff is positive */
1257 ary->ary_max += diff;
1258 ary->ary_fill += diff;
1261 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
1262 astore(ary, ary->ary_fill + diff, Nullstr);
1264 ary->ary_fill += diff;
1266 dst = ary->ary_array + ary->ary_fill;
1268 for (i = after; i; i--) {
1269 if (*dst) /* str was hanging around */
1270 str_free(*dst); /* after $#foo */
1278 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
1279 *dst = Str_new(46,0);
1280 str_sset(*dst++,*src++);
1282 sp = arglast[0] + 1;
1283 if (gimme == G_ARRAY) { /* copy return vals to stack */
1285 Copy(tmparyval, st+sp, length, STR*);
1286 if (ary->ary_flags & ARF_REAL) {
1287 for (i = length, dst = st+sp; i; i--)
1288 str_2mortal(*dst++); /* free them eventualy */
1290 Safefree(tmparyval);
1295 st[sp] = tmparyval[length-1];
1296 if (ary->ary_flags & ARF_REAL)
1297 str_2mortal(st[sp]);
1298 Safefree(tmparyval);
1301 st[sp] = &str_undef;
1307 do_grep(arg,str,gimme,arglast)
1313 STR **st = stack->ary_array;
1314 register int dst = arglast[1];
1315 register int src = dst + 1;
1316 register int sp = arglast[2];
1317 register int i = sp - arglast[1];
1318 int oldsave = savestack->ary_fill;
1319 SPAT *oldspat = curspat;
1320 int oldtmps_base = tmps_base;
1322 savesptr(&stab_val(defstab));
1323 tmps_base = tmps_max;
1324 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
1325 arg[1].arg_type &= A_MASK;
1327 arg[1].arg_type |= A_DONT;
1329 arg = arg[1].arg_ptr.arg_arg;
1332 stab_val(defstab) = st[src];
1334 stab_val(defstab) = str_mortal(&str_undef);
1335 (void)eval(arg,G_SCALAR,sp);
1336 st = stack->ary_array;
1337 if (str_true(st[sp+1]))
1338 st[dst++] = st[src];
1342 restorelist(oldsave);
1343 tmps_base = oldtmps_base;
1344 if (gimme != G_ARRAY) {
1345 str_numset(str,(double)(dst - arglast[1]));
1347 st[arglast[0]+1] = str;
1348 return arglast[0]+1;
1350 return arglast[0] + (dst - arglast[1]);
1357 STR **st = stack->ary_array;
1358 register STR **up = &st[arglast[1]];
1359 register STR **down = &st[arglast[2]];
1360 register int i = arglast[2] - arglast[1];
1367 i = arglast[2] - arglast[1];
1368 Copy(down+1,up,i/2,STR*);
1369 return arglast[2] - 1;
1373 do_sreverse(str,arglast)
1377 STR **st = stack->ary_array;
1379 register char *down;
1382 str_sset(str,st[arglast[2]]);
1384 if (str->str_cur > 1) {
1385 down = str->str_ptr + str->str_cur - 1;
1393 st[arglast[0]+1] = str;
1394 return arglast[0]+1;
1397 static CMD *sortcmd;
1398 static HASH *sortstash = Null(HASH*);
1399 static STAB *firststab = Nullstab;
1400 static STAB *secondstab = Nullstab;
1403 do_sort(str,stab,gimme,arglast)
1409 register STR **st = stack->ary_array;
1410 int sp = arglast[1];
1412 register int max = arglast[2] - sp;
1419 static ARRAY *sortstack = Null(ARRAY*);
1421 if (gimme != G_ARRAY) {
1422 str_sset(str,&str_undef);
1428 st += sp; /* temporarily make st point to args */
1429 for (i = 1; i <= max; i++) {
1431 if (!(*up)->str_pok)
1432 (void)str_2ptr(*up);
1434 (*up)->str_pok &= ~SP_TEMP;
1443 int oldtmps_base = tmps_base;
1445 if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd))
1446 fatal("Undefined subroutine \"%s\" in sort", stab_name(stab));
1448 sortstack = anew(Nullstab);
1449 astore(sortstack, 0, Nullstr);
1451 sortstack->ary_flags = 0;
1455 tmps_base = tmps_max;
1456 if (sortstash != stab_stash(stab)) {
1457 firststab = stabent("a",TRUE);
1458 secondstab = stabent("b",TRUE);
1459 sortstash = stab_stash(stab);
1461 oldfirst = stab_val(firststab);
1462 oldsecond = stab_val(secondstab);
1464 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1466 qsort(Nullch,max,sizeof(STR*),sortsub);
1468 stab_val(firststab) = oldfirst;
1469 stab_val(secondstab) = oldsecond;
1470 tmps_base = oldtmps_base;
1475 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1486 stab_val(firststab) = *str1;
1487 stab_val(secondstab) = *str2;
1488 cmd_exec(sortcmd,G_SCALAR,-1);
1489 return (int)str_gnum(*stack->ary_array);
1492 sortcmp(strp1,strp2)
1496 register STR *str1 = *strp1;
1497 register STR *str2 = *strp2;
1500 if (str1->str_cur < str2->str_cur) {
1501 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1506 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1508 else if (str1->str_cur == str2->str_cur)
1515 do_range(gimme,arglast)
1519 STR **st = stack->ary_array;
1520 register int sp = arglast[0];
1522 register ARRAY *ary = stack;
1526 if (gimme != G_ARRAY)
1527 fatal("panic: do_range");
1529 if (st[sp+1]->str_nok || !st[sp+1]->str_pok ||
1530 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1531 i = (int)str_gnum(st[sp+1]);
1532 max = (int)str_gnum(st[sp+2]);
1534 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1535 str_numset(str,(double)i++);
1539 STR *final = str_mortal(st[sp+2]);
1540 char *tmps = str_get(final);
1542 str = str_mortal(st[sp+1]);
1543 while (!str->str_nok && str->str_cur <= final->str_cur &&
1544 strNE(str->str_ptr,tmps) ) {
1545 (void)astore(ary, ++sp, str);
1546 str = str_2mortal(str_smake(str));
1549 if (strEQ(str->str_ptr,tmps))
1550 (void)astore(ary, ++sp, str);
1556 do_repeatary(arglast)
1559 STR **st = stack->ary_array;
1560 register int sp = arglast[0];
1561 register int items = arglast[1] - sp;
1562 register int count = (int) str_gnum(st[arglast[2]]);
1563 register ARRAY *ary = stack;
1567 max = items * count;
1568 if (max > 0 && sp + max > stack->ary_max) {
1569 astore(stack, sp + max, Nullstr);
1570 st = stack->ary_array;
1573 for (i = arglast[1]; i > sp; i--)
1574 st[i]->str_pok &= ~SP_TEMP;
1575 repeatcpy((char*)&st[arglast[1]+1], (char*)&st[sp+1],
1576 items * sizeof(STR*), count);
1584 do_caller(arg,maxarg,gimme,arglast)
1590 STR **st = stack->ary_array;
1591 register int sp = arglast[0];
1592 register CSV *csv = curcsv;
1597 fatal("There is no caller");
1599 count = (int) str_gnum(st[sp+1]);
1603 if (DBsub && csv->curcsv && csv->curcsv->sub == stab_sub(DBsub))
1609 if (gimme != G_ARRAY) {
1610 STR *str = arg->arg_ptr.arg_str;
1611 str_set(str,csv->curcmd->c_stash->tbl_name);
1618 (void)astore(stack,++sp,
1619 str_2mortal(str_make(csv->curcmd->c_stash->tbl_name,0)) );
1620 (void)astore(stack,++sp,
1621 str_2mortal(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) );
1622 (void)astore(stack,++sp,
1623 str_2mortal(str_nmake((double)csv->curcmd->c_line)) );
1626 str = Str_new(49,0);
1627 stab_fullname(str, csv->stab);
1628 (void)astore(stack,++sp, str_2mortal(str));
1629 (void)astore(stack,++sp,
1630 str_2mortal(str_nmake((double)csv->hasargs)) );
1631 (void)astore(stack,++sp,
1632 str_2mortal(str_nmake((double)csv->wantarray)) );
1634 ARRAY *ary = csv->argarray;
1638 dbargs = stab_xarray(aadd(stabent("DB'args", TRUE)));
1639 if (dbargs->ary_max < ary->ary_fill)
1640 astore(dbargs,ary->ary_fill,Nullstr);
1641 Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*);
1642 dbargs->ary_fill = ary->ary_fill;
1645 (void)astore(stack,++sp,
1646 str_2mortal(str_make("",0)));
1652 do_tms(str,gimme,arglast)
1660 STR **st = stack->ary_array;
1661 register int sp = arglast[0];
1663 if (gimme != G_ARRAY) {
1664 str_sset(str,&str_undef);
1669 (void)times(×buf);
1676 (void)astore(stack,++sp,
1677 str_2mortal(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1678 (void)astore(stack,++sp,
1679 str_2mortal(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1680 (void)astore(stack,++sp,
1681 str_2mortal(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1682 (void)astore(stack,++sp,
1683 str_2mortal(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1685 (void)astore(stack,++sp,
1686 str_2mortal(str_nmake(0.0)));
1693 do_time(str,tmbuf,gimme,arglast)
1699 register ARRAY *ary = stack;
1700 STR **st = ary->ary_array;
1701 register int sp = arglast[0];
1703 if (!tmbuf || gimme != G_ARRAY) {
1704 str_sset(str,&str_undef);
1709 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_sec)));
1710 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_min)));
1711 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_hour)));
1712 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mday)));
1713 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mon)));
1714 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_year)));
1715 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_wday)));
1716 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_yday)));
1717 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_isdst)));
1722 do_kv(str,hash,kv,gimme,arglast)
1729 register ARRAY *ary = stack;
1730 STR **st = ary->ary_array;
1731 register int sp = arglast[0];
1733 register HENT *entry;
1736 int dokeys = (kv == O_KEYS || kv == O_HASH);
1737 int dovalues = (kv == O_VALUES || kv == O_HASH);
1739 if (gimme != G_ARRAY) {
1740 str_sset(str,&str_undef);
1745 (void)hiterinit(hash);
1746 while (entry = hiternext(hash)) {
1748 tmps = hiterkey(entry,&i);
1751 (void)astore(ary,++sp,str_2mortal(str_make(tmps,i)));
1754 tmpstr = Str_new(45,0);
1757 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1758 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1759 str_set(tmpstr,buf);
1763 str_sset(tmpstr,hiterval(hash,entry));
1764 (void)astore(ary,++sp,str_2mortal(tmpstr));
1771 do_each(str,hash,gimme,arglast)
1777 STR **st = stack->ary_array;
1778 register int sp = arglast[0];
1779 static STR *mystrk = Nullstr;
1780 HENT *entry = hiternext(hash);
1790 if (gimme == G_ARRAY) {
1791 tmps = hiterkey(entry, &i);
1794 st[++sp] = mystrk = str_make(tmps,i);
1797 str_sset(str,hiterval(hash,entry));