1 /* $Header: dolist.c,v 4.0 91/03/20 01:08:03 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 4.0 91/03/20 01:08:03 lwall
19 #pragma function(memcmp)
20 #endif /* BUGGY_MSC */
23 do_match(str,arg,gimme,arglast)
29 register STR **st = stack->ary_array;
30 register SPAT *spat = arg[2].arg_ptr.arg_spat;
32 register int sp = arglast[0] + 1;
33 STR *srchstr = st[sp];
34 register char *s = str_get(st[sp]);
35 char *strend = s + st[sp]->str_cur;
49 fatal("panic: do_match");
50 if (spat->spat_flags & SPAT_USED) {
63 if (spat->spat_runtime) {
65 sp = eval(spat->spat_runtime,G_SCALAR,sp);
66 st = stack->ary_array;
67 t = str_get(tmpstr = st[sp--]);
71 deb("2.SPAT /%s/\n",t);
73 if (spat->spat_regexp) {
74 regfree(spat->spat_regexp);
75 spat->spat_regexp = Null(REGEXP*); /* crucial if regcomp aborts */
77 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
78 spat->spat_flags & SPAT_FOLD);
79 if (!*spat->spat_regexp->precomp && lastspat)
81 if (spat->spat_flags & SPAT_KEEP) {
82 if (spat->spat_runtime)
83 arg_free(spat->spat_runtime); /* it won't change, so */
84 spat->spat_runtime = Nullarg; /* no point compiling again */
86 if (!spat->spat_regexp->nparens)
87 gimme = G_SCALAR; /* accidental array context? */
88 if (regexec(spat->spat_regexp, s, strend, s, 0,
89 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
91 if (spat->spat_regexp->subbase)
99 str_sset(str,&str_no);
110 if (spat->spat_flags & SPAT_ONCE)
114 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
117 if (!*spat->spat_regexp->precomp && lastspat)
121 if (myhint < s || myhint > strend)
122 fatal("panic: hint in do_match");
124 if (spat->spat_regexp->regback >= 0) {
125 s -= spat->spat_regexp->regback;
132 else if (spat->spat_short) {
133 if (spat->spat_flags & SPAT_SCANFIRST) {
134 if (srchstr->str_pok & SP_STUDIED) {
135 if (screamfirst[spat->spat_short->str_rare] < 0)
137 else if (!(s = screaminstr(srchstr,spat->spat_short)))
139 else if (spat->spat_flags & SPAT_ALL)
143 else if (!(s = fbminstr((unsigned char*)s,
144 (unsigned char*)strend, spat->spat_short)))
147 else if (spat->spat_flags & SPAT_ALL)
149 if (s && spat->spat_regexp->regback >= 0) {
150 ++spat->spat_short->str_u.str_useful;
151 s -= spat->spat_regexp->regback;
158 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
159 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
161 if (--spat->spat_short->str_u.str_useful < 0) {
162 str_free(spat->spat_short);
163 spat->spat_short = Nullstr; /* opt is being useless */
166 if (!spat->spat_regexp->nparens)
167 gimme = G_SCALAR; /* accidental array context? */
168 if (regexec(spat->spat_regexp, s, strend, t, 0,
169 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
171 if (spat->spat_regexp->subbase)
174 if (spat->spat_flags & SPAT_ONCE)
175 spat->spat_flags |= SPAT_USED;
179 if (gimme == G_ARRAY)
181 str_sset(str,&str_no);
190 if (gimme == G_ARRAY) {
193 iters = spat->spat_regexp->nparens;
194 if (sp + iters >= stack->ary_max) {
195 astore(stack,sp + iters, Nullstr);
196 st = stack->ary_array; /* possibly realloced */
199 for (i = 1; i <= iters; i++) {
200 st[++sp] = str_mortal(&str_no);
201 if (s = spat->spat_regexp->startp[i]) {
202 len = spat->spat_regexp->endp[i] - s;
204 str_nset(st[sp],s,len);
210 str_sset(str,&str_yes);
217 ++spat->spat_short->str_u.str_useful;
219 if (spat->spat_flags & SPAT_ONCE)
220 spat->spat_flags |= SPAT_USED;
224 if (spat->spat_regexp->subbase)
225 Safefree(spat->spat_regexp->subbase);
226 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
227 spat->spat_regexp->subend = tmps + (strend-t);
228 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
229 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
232 str_sset(str,&str_yes);
238 ++spat->spat_short->str_u.str_useful;
239 if (gimme == G_ARRAY)
241 str_sset(str,&str_no);
248 #pragma intrinsic(memcmp)
249 #endif /* BUGGY_MSC */
252 do_split(str,spat,limit,gimme,arglast)
259 register ARRAY *ary = stack;
260 STR **st = ary->ary_array;
261 register int sp = arglast[0] + 1;
262 register char *s = str_get(st[sp]);
263 char *strend = s + st[sp--]->str_cur;
267 int maxiters = (strend - s) + 10;
270 int origlimit = limit;
274 fatal("panic: do_split");
275 else if (spat->spat_runtime) {
277 sp = eval(spat->spat_runtime,G_SCALAR,sp);
278 st = stack->ary_array;
279 m = str_get(dstr = st[sp--]);
281 if (*m == ' ' && dstr->str_cur == 1) {
282 str_set(dstr,"\\s+");
284 spat->spat_flags |= SPAT_SKIPWHITE;
286 if (spat->spat_regexp) {
287 regfree(spat->spat_regexp);
288 spat->spat_regexp = Null(REGEXP*); /* avoid possible double free */
290 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
291 spat->spat_flags & SPAT_FOLD);
292 if (spat->spat_flags & SPAT_KEEP ||
293 (spat->spat_runtime->arg_type == O_ITEM &&
294 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
295 arg_free(spat->spat_runtime); /* it won't change, so */
296 spat->spat_runtime = Nullarg; /* no point compiling again */
301 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
304 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
305 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
307 if (!(ary->ary_flags & ARF_REAL)) {
308 ary->ary_flags |= ARF_REAL;
309 for (i = ary->ary_fill; i >= 0; i--)
310 ary->ary_array[i] = Nullstr; /* don't free mere refs */
313 sp = -1; /* temporarily switch stacks */
318 if (spat->spat_flags & SPAT_SKIPWHITE) {
319 while (isascii(*s) && isspace(*s))
323 limit = maxiters + 2;
324 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
326 for (m = s; m < strend && !(isascii(*m)&&isspace(*m)); m++) ;
329 dstr = Str_new(30,m-s);
330 str_nset(dstr,s,m-s);
333 (void)astore(ary, ++sp, dstr);
334 for (s = m + 1; s < strend && isascii(*s) && isspace(*s); s++) ;
337 else if (strEQ("^",spat->spat_regexp->precomp)) {
339 for (m = s; m < strend && *m != '\n'; m++) ;
343 dstr = Str_new(30,m-s);
344 str_nset(dstr,s,m-s);
347 (void)astore(ary, ++sp, dstr);
351 else if (spat->spat_short) {
352 i = spat->spat_short->str_cur;
354 int fold = (spat->spat_flags & SPAT_FOLD);
356 i = *spat->spat_short->str_ptr;
357 if (fold && isupper(i))
362 m < strend && *m != i &&
363 (!isupper(*m) || tolower(*m) != i);
368 for (m = s; m < strend && *m != i; m++) ;
371 dstr = Str_new(30,m-s);
372 str_nset(dstr,s,m-s);
375 (void)astore(ary, ++sp, dstr);
381 while (s < strend && --limit &&
382 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
386 dstr = Str_new(31,m-s);
387 str_nset(dstr,s,m-s);
390 (void)astore(ary, ++sp, dstr);
396 maxiters += (strend - s) * spat->spat_regexp->nparens;
397 while (s < strend && --limit &&
398 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
399 if (spat->spat_regexp->subbase
400 && spat->spat_regexp->subbase != orig) {
403 orig = spat->spat_regexp->subbase;
405 strend = s + (strend - m);
407 m = spat->spat_regexp->startp[0];
408 dstr = Str_new(32,m-s);
409 str_nset(dstr,s,m-s);
412 (void)astore(ary, ++sp, dstr);
413 if (spat->spat_regexp->nparens) {
414 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
415 s = spat->spat_regexp->startp[i];
416 m = spat->spat_regexp->endp[i];
417 dstr = Str_new(33,m-s);
418 str_nset(dstr,s,m-s);
421 (void)astore(ary, ++sp, dstr);
424 s = spat->spat_regexp->endp[0];
430 iters = sp - arglast[0];
431 if (iters > maxiters)
433 if (s < strend || origlimit) { /* keep field after final delim? */
434 dstr = Str_new(34,strend-s);
435 str_nset(dstr,s,strend-s);
438 (void)astore(ary, ++sp, dstr);
443 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
450 zaps = str_get(afetch(ary,sp,FALSE));
454 while (iters > 0 && (!zapb)) {
457 zaps = str_get(afetch(ary,iters-1,FALSE));
465 if (gimme == G_ARRAY) {
467 astore(stack, arglast[0] + 1 + sp, Nullstr);
468 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
469 return arglast[0] + sp;
473 if (gimme == G_ARRAY)
477 str_numset(str,(double)iters);
484 do_unpack(str,gimme,arglast)
489 STR **st = stack->ary_array;
490 register int sp = arglast[0] + 1;
491 register char *pat = str_get(st[sp++]);
492 register char *s = str_get(st[sp]);
493 char *strend = s + st[sp--]->str_cur;
495 register char *patend = pat + st[sp]->str_cur;
500 /* These must not be in registers: */
504 unsigned short aushort;
506 unsigned long aulong;
511 unsigned long culong;
514 if (gimme != G_ARRAY) { /* arrange to do first one only */
515 for (patend = pat; !isalpha(*patend); patend++);
516 if (index("aAbBhH", *patend) || *pat == '%') {
518 while (isdigit(*patend) || *patend == '*')
525 while (pat < patend) {
530 else if (*pat == '*') {
531 len = strend - strbeg; /* long enough */
534 else if (isdigit(*pat)) {
536 while (isdigit(*pat))
537 len = (len * 10) + (*pat++ - '0');
540 len = (datumtype != '@');
545 if (len == 1 && pat[-1] != '1')
554 if (len > strend - s)
555 fatal("@ outside of string");
559 if (len > s - strbeg)
560 fatal("X outside of string");
564 if (len > strend - s)
565 fatal("x outside of string");
570 if (len > strend - s)
574 str = Str_new(35,len);
577 if (datumtype == 'A') {
578 aptr = s; /* borrow register */
579 s = str->str_ptr + len - 1;
580 while (s >= str->str_ptr && (!*s || (isascii(*s)&&isspace(*s))))
583 str->str_cur = s - str->str_ptr;
584 s = aptr; /* unborrow register */
586 (void)astore(stack, ++sp, str_2mortal(str));
590 if (pat[-1] == '*' || len > (strend - s) * 8)
591 len = (strend - s) * 8;
592 str = Str_new(35, len + 1);
595 aptr = pat; /* borrow register */
597 if (datumtype == 'b') {
599 for (len = 0; len < aint; len++) {
604 *pat++ = '0' + (bits & 1);
609 for (len = 0; len < aint; len++) {
614 *pat++ = '0' + ((bits & 128) != 0);
618 pat = aptr; /* unborrow register */
619 (void)astore(stack, ++sp, str_2mortal(str));
623 if (pat[-1] == '*' || len > (strend - s) * 2)
624 len = (strend - s) * 2;
625 str = Str_new(35, len + 1);
628 aptr = pat; /* borrow register */
630 if (datumtype == 'h') {
632 for (len = 0; len < aint; len++) {
637 *pat++ = hexdigit[bits & 15];
642 for (len = 0; len < aint; len++) {
647 *pat++ = hexdigit[(bits >> 4) & 15];
651 pat = aptr; /* unborrow register */
652 (void)astore(stack, ++sp, str_2mortal(str));
655 if (len > strend - s)
660 if (aint >= 128) /* fake up signed chars */
668 if (aint >= 128) /* fake up signed chars */
671 str_numset(str,(double)aint);
672 (void)astore(stack, ++sp, str_2mortal(str));
677 if (len > strend - s)
690 str_numset(str,(double)auint);
691 (void)astore(stack, ++sp, str_2mortal(str));
696 along = (strend - s) / sizeof(short);
701 bcopy(s,(char*)&ashort,sizeof(short));
708 bcopy(s,(char*)&ashort,sizeof(short));
711 str_numset(str,(double)ashort);
712 (void)astore(stack, ++sp, str_2mortal(str));
718 along = (strend - s) / sizeof(unsigned short);
723 bcopy(s,(char*)&aushort,sizeof(unsigned short));
724 s += sizeof(unsigned short);
726 if (datumtype == 'n')
727 aushort = ntohs(aushort);
734 bcopy(s,(char*)&aushort,sizeof(unsigned short));
735 s += sizeof(unsigned short);
738 if (datumtype == 'n')
739 aushort = ntohs(aushort);
741 str_numset(str,(double)aushort);
742 (void)astore(stack, ++sp, str_2mortal(str));
747 along = (strend - s) / sizeof(int);
752 bcopy(s,(char*)&aint,sizeof(int));
755 cdouble += (double)aint;
762 bcopy(s,(char*)&aint,sizeof(int));
765 str_numset(str,(double)aint);
766 (void)astore(stack, ++sp, str_2mortal(str));
771 along = (strend - s) / sizeof(unsigned int);
776 bcopy(s,(char*)&auint,sizeof(unsigned int));
777 s += sizeof(unsigned int);
779 cdouble += (double)auint;
786 bcopy(s,(char*)&auint,sizeof(unsigned int));
787 s += sizeof(unsigned int);
789 str_numset(str,(double)auint);
790 (void)astore(stack, ++sp, str_2mortal(str));
795 along = (strend - s) / sizeof(long);
800 bcopy(s,(char*)&along,sizeof(long));
803 cdouble += (double)along;
810 bcopy(s,(char*)&along,sizeof(long));
813 str_numset(str,(double)along);
814 (void)astore(stack, ++sp, str_2mortal(str));
820 along = (strend - s) / sizeof(unsigned long);
825 bcopy(s,(char*)&aulong,sizeof(unsigned long));
826 s += sizeof(unsigned long);
828 if (datumtype == 'N')
829 aulong = ntohl(aulong);
832 cdouble += (double)aulong;
839 bcopy(s,(char*)&aulong,sizeof(unsigned long));
840 s += sizeof(unsigned long);
843 if (datumtype == 'N')
844 aulong = ntohl(aulong);
846 str_numset(str,(double)aulong);
847 (void)astore(stack, ++sp, str_2mortal(str));
852 along = (strend - s) / sizeof(char*);
856 if (sizeof(char*) > strend - s)
859 bcopy(s,(char*)&aptr,sizeof(char*));
865 (void)astore(stack, ++sp, str_2mortal(str));
868 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
871 along = (strend - s) / sizeof(float);
876 bcopy(s, (char *)&afloat, sizeof(float));
883 bcopy(s, (char *)&afloat, sizeof(float));
885 str = Str_new(47, 0);
886 str_numset(str, (double)afloat);
887 (void)astore(stack, ++sp, str_2mortal(str));
893 along = (strend - s) / sizeof(double);
898 bcopy(s, (char *)&adouble, sizeof(double));
905 bcopy(s, (char *)&adouble, sizeof(double));
907 str = Str_new(48, 0);
908 str_numset(str, (double)adouble);
909 (void)astore(stack, ++sp, str_2mortal(str));
914 along = (strend - s) * 3 / 4;
915 str = Str_new(42,along);
916 while (s < strend && *s > ' ' && *s < 'a') {
921 len = (*s++ - ' ') & 077;
923 if (s < strend && *s >= ' ')
924 a = (*s++ - ' ') & 077;
927 if (s < strend && *s >= ' ')
928 b = (*s++ - ' ') & 077;
931 if (s < strend && *s >= ' ')
932 c = (*s++ - ' ') & 077;
935 if (s < strend && *s >= ' ')
936 d = (*s++ - ' ') & 077;
939 hunk[0] = a << 2 | b >> 4;
940 hunk[1] = b << 4 | c >> 2;
941 hunk[2] = c << 6 | d;
942 str_ncat(str,hunk, len > 3 ? 3 : len);
947 else if (s[1] == '\n') /* possible checksum byte */
950 (void)astore(stack, ++sp, str_2mortal(str));
955 if (index("fFdD", datumtype) ||
956 (checksum > 32 && index("iIlLN", datumtype)) ) {
961 while (checksum >= 16) {
965 while (checksum >= 4) {
971 along = (1 << checksum) - 1;
972 while (cdouble < 0.0)
974 cdouble = modf(cdouble / adouble, &trouble) * adouble;
975 str_numset(str,cdouble);
979 along = (1 << checksum) - 1;
980 culong &= (unsigned long)along;
982 str_numset(str,(double)culong);
984 (void)astore(stack, ++sp, str_2mortal(str));
992 do_slice(stab,str,numarray,lval,gimme,arglast)
1000 register STR **st = stack->ary_array;
1001 register int sp = arglast[1];
1002 register int max = arglast[2];
1003 register char *tmps;
1005 register int magic = 0;
1006 register ARRAY *ary;
1007 register HASH *hash;
1008 int oldarybase = arybase;
1011 if (numarray == 2) { /* a slice of a LIST */
1013 ary->ary_fill = arglast[3];
1015 st[sp] = str; /* make stack size available */
1016 str_numset(str,(double)(sp - 1));
1019 ary = stab_array(stab); /* a slice of an array */
1023 if (stab == envstab)
1025 else if (stab == sigstab)
1028 else if (stab_hash(stab)->tbl_dbm)
1030 #endif /* SOME_DBM */
1032 hash = stab_hash(stab); /* a slice of an associative array */
1035 if (gimme == G_ARRAY) {
1039 st[sp-1] = afetch(ary,
1040 ((int)str_gnum(st[sp])) - arybase, lval);
1043 st[sp-1] = &str_undef;
1049 tmps = str_get(st[sp]);
1050 len = st[sp]->str_cur;
1051 st[sp-1] = hfetch(hash,tmps,len, lval);
1053 str_magic(st[sp-1],stab,magic,tmps,len);
1056 st[sp-1] = &str_undef;
1064 st[sp] = afetch(ary,
1065 ((int)str_gnum(st[max])) - arybase, lval);
1067 st[sp] = &str_undef;
1071 tmps = str_get(st[max]);
1072 len = st[max]->str_cur;
1073 st[sp] = hfetch(hash,tmps,len, lval);
1075 str_magic(st[sp],stab,magic,tmps,len);
1078 st[sp] = &str_undef;
1081 arybase = oldarybase;
1086 do_splice(ary,gimme,arglast)
1087 register ARRAY *ary;
1091 register STR **st = stack->ary_array;
1092 register int sp = arglast[1];
1093 int max = arglast[2] + 1;
1097 register int offset;
1098 register int length;
1105 offset = ((int)str_gnum(st[sp])) - arybase;
1107 offset += ary->ary_fill + 1;
1109 length = (int)str_gnum(st[sp++]);
1114 length = ary->ary_max; /* close enough to infinity */
1118 length = ary->ary_max;
1126 if (offset > ary->ary_fill + 1)
1127 offset = ary->ary_fill + 1;
1128 after = ary->ary_fill + 1 - (offset + length);
1129 if (after < 0) { /* not that much array */
1130 length += after; /* offset+length now in array */
1132 if (!ary->ary_alloc) {
1138 /* At this point, sp .. max-1 is our new LIST */
1141 diff = newlen - length;
1143 if (diff < 0) { /* shrinking the area */
1145 New(451, tmparyval, newlen, STR*); /* so remember insertion */
1146 Copy(st+sp, tmparyval, newlen, STR*);
1149 sp = arglast[0] + 1;
1150 if (gimme == G_ARRAY) { /* copy return vals to stack */
1151 if (sp + length >= stack->ary_max) {
1152 astore(stack,sp + length, Nullstr);
1153 st = stack->ary_array;
1155 Copy(ary->ary_array+offset, st+sp, length, STR*);
1156 if (ary->ary_flags & ARF_REAL) {
1157 for (i = length, dst = st+sp; i; i--)
1158 str_2mortal(*dst++); /* free them eventualy */
1163 st[sp] = ary->ary_array[offset+length-1];
1164 if (ary->ary_flags & ARF_REAL)
1165 str_2mortal(st[sp]);
1167 ary->ary_fill += diff;
1169 /* pull up or down? */
1171 if (offset < after) { /* easier to pull up */
1172 if (offset) { /* esp. if nothing to pull */
1173 src = &ary->ary_array[offset-1];
1174 dst = src - diff; /* diff is negative */
1175 for (i = offset; i > 0; i--) /* can't trust Copy */
1178 Zero(ary->ary_array, -diff, STR*);
1179 ary->ary_array -= diff; /* diff is negative */
1180 ary->ary_max += diff;
1183 if (after) { /* anything to pull down? */
1184 src = ary->ary_array + offset + length;
1185 dst = src + diff; /* diff is negative */
1186 Copy(src, dst, after, STR*);
1188 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
1189 /* avoid later double free */
1192 for (src = tmparyval, dst = ary->ary_array + offset;
1194 *dst = Str_new(46,0);
1195 str_sset(*dst++,*src++);
1197 Safefree(tmparyval);
1200 else { /* no, expanding (or same) */
1202 New(452, tmparyval, length, STR*); /* so remember deletion */
1203 Copy(ary->ary_array+offset, tmparyval, length, STR*);
1206 if (diff > 0) { /* expanding */
1208 /* push up or down? */
1210 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
1212 src = ary->ary_array;
1214 Copy(src, dst, offset, STR*);
1216 ary->ary_array -= diff; /* diff is positive */
1217 ary->ary_max += diff;
1218 ary->ary_fill += diff;
1221 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
1222 astore(ary, ary->ary_fill + diff, Nullstr);
1224 ary->ary_fill += diff;
1226 dst = ary->ary_array + ary->ary_fill;
1228 for (i = after; i; i--) {
1229 if (*dst) /* str was hanging around */
1230 str_free(*dst); /* after $#foo */
1238 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
1239 *dst = Str_new(46,0);
1240 str_sset(*dst++,*src++);
1242 sp = arglast[0] + 1;
1243 if (gimme == G_ARRAY) { /* copy return vals to stack */
1245 Copy(tmparyval, st+sp, length, STR*);
1246 if (ary->ary_flags & ARF_REAL) {
1247 for (i = length, dst = st+sp; i; i--)
1248 str_2mortal(*dst++); /* free them eventualy */
1250 Safefree(tmparyval);
1255 st[sp] = tmparyval[length-1];
1256 if (ary->ary_flags & ARF_REAL)
1257 str_2mortal(st[sp]);
1258 Safefree(tmparyval);
1261 st[sp] = &str_undef;
1267 do_grep(arg,str,gimme,arglast)
1273 STR **st = stack->ary_array;
1274 register int dst = arglast[1];
1275 register int src = dst + 1;
1276 register int sp = arglast[2];
1277 register int i = sp - arglast[1];
1278 int oldsave = savestack->ary_fill;
1279 SPAT *oldspat = curspat;
1280 int oldtmps_base = tmps_base;
1282 savesptr(&stab_val(defstab));
1283 tmps_base = tmps_max;
1284 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
1285 arg[1].arg_type &= A_MASK;
1287 arg[1].arg_type |= A_DONT;
1289 arg = arg[1].arg_ptr.arg_arg;
1292 stab_val(defstab) = st[src];
1294 stab_val(defstab) = str_mortal(&str_undef);
1295 (void)eval(arg,G_SCALAR,sp);
1296 st = stack->ary_array;
1297 if (str_true(st[sp+1]))
1298 st[dst++] = st[src];
1302 restorelist(oldsave);
1303 tmps_base = oldtmps_base;
1304 if (gimme != G_ARRAY) {
1305 str_numset(str,(double)(dst - arglast[1]));
1307 st[arglast[0]+1] = str;
1308 return arglast[0]+1;
1310 return arglast[0] + (dst - arglast[1]);
1317 STR **st = stack->ary_array;
1318 register STR **up = &st[arglast[1]];
1319 register STR **down = &st[arglast[2]];
1320 register int i = arglast[2] - arglast[1];
1327 i = arglast[2] - arglast[1];
1328 Copy(down+1,up,i/2,STR*);
1329 return arglast[2] - 1;
1333 do_sreverse(str,arglast)
1337 STR **st = stack->ary_array;
1339 register char *down;
1342 str_sset(str,st[arglast[2]]);
1344 if (str->str_cur > 1) {
1345 down = str->str_ptr + str->str_cur - 1;
1353 st[arglast[0]+1] = str;
1354 return arglast[0]+1;
1357 static CMD *sortcmd;
1358 static HASH *sortstash = Null(HASH*);
1359 static STAB *firststab = Nullstab;
1360 static STAB *secondstab = Nullstab;
1363 do_sort(str,stab,gimme,arglast)
1369 register STR **st = stack->ary_array;
1370 int sp = arglast[1];
1372 register int max = arglast[2] - sp;
1379 static ARRAY *sortstack = Null(ARRAY*);
1381 if (gimme != G_ARRAY) {
1382 str_sset(str,&str_undef);
1388 st += sp; /* temporarily make st point to args */
1389 for (i = 1; i <= max; i++) {
1391 if (!(*up)->str_pok)
1392 (void)str_2ptr(*up);
1394 (*up)->str_pok &= ~SP_TEMP;
1403 int oldtmps_base = tmps_base;
1405 if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd))
1406 fatal("Undefined subroutine \"%s\" in sort", stab_name(stab));
1408 sortstack = anew(Nullstab);
1409 astore(sortstack, 0, Nullstr);
1411 sortstack->ary_flags = 0;
1415 tmps_base = tmps_max;
1416 if (sortstash != stab_stash(stab)) {
1417 firststab = stabent("a",TRUE);
1418 secondstab = stabent("b",TRUE);
1419 sortstash = stab_stash(stab);
1421 oldfirst = stab_val(firststab);
1422 oldsecond = stab_val(secondstab);
1424 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1426 qsort(Nullch,max,sizeof(STR*),sortsub);
1428 stab_val(firststab) = oldfirst;
1429 stab_val(secondstab) = oldsecond;
1430 tmps_base = oldtmps_base;
1435 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1446 stab_val(firststab) = *str1;
1447 stab_val(secondstab) = *str2;
1448 cmd_exec(sortcmd,G_SCALAR,-1);
1449 return (int)str_gnum(*stack->ary_array);
1452 sortcmp(strp1,strp2)
1456 register STR *str1 = *strp1;
1457 register STR *str2 = *strp2;
1460 if (str1->str_cur < str2->str_cur) {
1461 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1466 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1468 else if (str1->str_cur == str2->str_cur)
1475 do_range(gimme,arglast)
1479 STR **st = stack->ary_array;
1480 register int sp = arglast[0];
1482 register ARRAY *ary = stack;
1486 if (gimme != G_ARRAY)
1487 fatal("panic: do_range");
1489 if (st[sp+1]->str_nok || !st[sp+1]->str_pok ||
1490 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1491 i = (int)str_gnum(st[sp+1]);
1492 max = (int)str_gnum(st[sp+2]);
1494 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1495 str_numset(str,(double)i++);
1499 STR *final = str_mortal(st[sp+2]);
1500 char *tmps = str_get(final);
1502 str = str_mortal(st[sp+1]);
1503 while (!str->str_nok && str->str_cur <= final->str_cur &&
1504 strNE(str->str_ptr,tmps) ) {
1505 (void)astore(ary, ++sp, str);
1506 str = str_2mortal(str_smake(str));
1509 if (strEQ(str->str_ptr,tmps))
1510 (void)astore(ary, ++sp, str);
1516 do_repeatary(arglast)
1519 STR **st = stack->ary_array;
1520 register int sp = arglast[0];
1521 register int items = arglast[1] - sp;
1522 register int count = (int) str_gnum(st[arglast[2]]);
1523 register ARRAY *ary = stack;
1527 max = items * count;
1528 if (max > 0 && sp + max > stack->ary_max) {
1529 astore(stack, sp + max, Nullstr);
1530 st = stack->ary_array;
1533 for (i = arglast[1]; i > sp; i--)
1534 st[i]->str_pok &= ~SP_TEMP;
1535 repeatcpy((char*)&st[arglast[1]+1], (char*)&st[sp+1],
1536 items * sizeof(STR*), count);
1544 do_caller(arg,maxarg,gimme,arglast)
1550 STR **st = stack->ary_array;
1551 register int sp = arglast[0];
1552 register CSV *csv = curcsv;
1557 fatal("There is no caller");
1559 count = (int) str_gnum(st[sp+1]);
1563 if (DBsub && csv->curcsv && csv->curcsv->sub == stab_sub(DBsub))
1569 if (gimme != G_ARRAY) {
1570 STR *str = arg->arg_ptr.arg_str;
1571 str_set(str,csv->curcmd->c_stash->tbl_name);
1578 (void)astore(stack,++sp,
1579 str_2mortal(str_make(csv->curcmd->c_stash->tbl_name,0)) );
1580 (void)astore(stack,++sp,
1581 str_2mortal(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) );
1582 (void)astore(stack,++sp,
1583 str_2mortal(str_nmake((double)csv->curcmd->c_line)) );
1586 str = Str_new(49,0);
1587 stab_fullname(str, csv->stab);
1588 (void)astore(stack,++sp, str_2mortal(str));
1589 (void)astore(stack,++sp,
1590 str_2mortal(str_nmake((double)csv->hasargs)) );
1591 (void)astore(stack,++sp,
1592 str_2mortal(str_nmake((double)csv->wantarray)) );
1594 ARRAY *ary = csv->argarray;
1596 if (dbargs->ary_max < ary->ary_fill)
1597 astore(dbargs,ary->ary_fill,Nullstr);
1598 Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*);
1599 dbargs->ary_fill = ary->ary_fill;
1602 (void)astore(stack,++sp,
1603 str_2mortal(str_make("",0)));
1609 do_tms(str,gimme,arglast)
1617 STR **st = stack->ary_array;
1618 register int sp = arglast[0];
1620 if (gimme != G_ARRAY) {
1621 str_sset(str,&str_undef);
1626 (void)times(×buf);
1633 (void)astore(stack,++sp,
1634 str_2mortal(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1635 (void)astore(stack,++sp,
1636 str_2mortal(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1637 (void)astore(stack,++sp,
1638 str_2mortal(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1639 (void)astore(stack,++sp,
1640 str_2mortal(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1642 (void)astore(stack,++sp,
1643 str_2mortal(str_nmake(0.0)));
1650 do_time(str,tmbuf,gimme,arglast)
1656 register ARRAY *ary = stack;
1657 STR **st = ary->ary_array;
1658 register int sp = arglast[0];
1660 if (!tmbuf || gimme != G_ARRAY) {
1661 str_sset(str,&str_undef);
1666 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_sec)));
1667 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_min)));
1668 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_hour)));
1669 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mday)));
1670 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_mon)));
1671 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_year)));
1672 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_wday)));
1673 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_yday)));
1674 (void)astore(ary,++sp,str_2mortal(str_nmake((double)tmbuf->tm_isdst)));
1679 do_kv(str,hash,kv,gimme,arglast)
1686 register ARRAY *ary = stack;
1687 STR **st = ary->ary_array;
1688 register int sp = arglast[0];
1690 register HENT *entry;
1693 int dokeys = (kv == O_KEYS || kv == O_HASH);
1694 int dovalues = (kv == O_VALUES || kv == O_HASH);
1696 if (gimme != G_ARRAY) {
1697 str_sset(str,&str_undef);
1702 (void)hiterinit(hash);
1703 while (entry = hiternext(hash)) {
1705 tmps = hiterkey(entry,&i);
1708 (void)astore(ary,++sp,str_2mortal(str_make(tmps,i)));
1711 tmpstr = Str_new(45,0);
1714 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1715 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1716 str_set(tmpstr,buf);
1720 str_sset(tmpstr,hiterval(hash,entry));
1721 (void)astore(ary,++sp,str_2mortal(tmpstr));
1728 do_each(str,hash,gimme,arglast)
1734 STR **st = stack->ary_array;
1735 register int sp = arglast[0];
1736 static STR *mystrk = Nullstr;
1737 HENT *entry = hiternext(hash);
1747 if (gimme == G_ARRAY) {
1748 tmps = hiterkey(entry, &i);
1751 st[++sp] = mystrk = str_make(tmps,i);
1754 str_sset(str,hiterval(hash,entry));