1 /* $Header: dolist.c,v 3.0.1.10 90/10/15 16:19:48 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 3.0.1.10 90/10/15 16:19:48 lwall
10 * patch29: added caller
11 * patch29: added scalar reverse
12 * patch29: sort undefined_subroutine @array is now a fatal error
14 * Revision 3.0.1.9 90/08/13 22:15:35 lwall
15 * patch28: defined(@array) and defined(%array) didn't work right
17 * Revision 3.0.1.8 90/08/09 03:15:56 lwall
18 * patch19: certain kinds of matching cause "panic: hint"
19 * patch19: $' broke on embedded nulls
20 * patch19: split on /\s+/, /^/ and ' ' is now special cased for speed
21 * patch19: split on /x/i didn't work
22 * patch19: couldn't unpack an 'A' or 'a' field in a scalar context
23 * patch19: unpack called bcopy on each character of a C/c field
24 * patch19: pack/unpack know about uudecode lines
25 * patch19: fixed sort on undefined strings and sped up slightly
26 * patch19: each and keys returned garbage on null key in DBM file
28 * Revision 3.0.1.7 90/03/27 15:48:42 lwall
29 * patch16: MSDOS support
30 * patch16: use of $`, $& or $' sometimes causes memory leakage
31 * patch16: splice(@array,0,$n) case cause duplicate free
32 * patch16: grep blows up on undefined array values
33 * patch16: .. now works using magical string increment
35 * Revision 3.0.1.6 90/03/12 16:33:02 lwall
36 * patch13: added list slice operator (LIST)[LIST]
37 * patch13: added splice operator: @oldelems = splice(@array,$offset,$len,LIST)
38 * patch13: made split('') act like split(//) rather than split(' ')
40 * Revision 3.0.1.5 90/02/28 17:09:44 lwall
41 * patch9: split now can split into more than 10000 elements
42 * patch9: @_ clobbered by ($foo,$bar) = split
43 * patch9: sped up pack and unpack
44 * patch9: unpack of single item now works in a scalar context
45 * patch9: slices ignored value of $[
46 * patch9: grep now returns number of items matched in scalar context
47 * patch9: grep iterations no longer in the regexp context of previous iteration
49 * Revision 3.0.1.4 89/12/21 19:58:46 lwall
50 * patch7: grep(1,@array) didn't work
51 * patch7: /$pat/; //; wrongly freed runtime pattern twice
53 * Revision 3.0.1.3 89/11/17 15:14:45 lwall
54 * patch5: grep() occasionally loses arguments or dumps core
56 * Revision 3.0.1.2 89/11/11 04:28:17 lwall
57 * patch2: non-existent slice values are now undefined rather than null
59 * Revision 3.0.1.1 89/10/26 23:11:51 lwall
60 * patch1: split in a subroutine wrongly freed referenced arguments
61 * patch1: reverse didn't work
63 * Revision 3.0 89/10/18 15:11:02 lwall
73 #pragma function(memcmp)
74 #endif /* BUGGY_MSC */
77 do_match(str,arg,gimme,arglast)
83 register STR **st = stack->ary_array;
84 register SPAT *spat = arg[2].arg_ptr.arg_spat;
86 register int sp = arglast[0] + 1;
87 STR *srchstr = st[sp];
88 register char *s = str_get(st[sp]);
89 char *strend = s + st[sp]->str_cur;
103 fatal("panic: do_match");
104 if (spat->spat_flags & SPAT_USED) {
107 deb("2.SPAT USED\n");
109 if (gimme == G_ARRAY)
117 if (spat->spat_runtime) {
119 sp = eval(spat->spat_runtime,G_SCALAR,sp);
120 st = stack->ary_array;
121 t = str_get(tmpstr = st[sp--]);
125 deb("2.SPAT /%s/\n",t);
127 if (spat->spat_regexp)
128 regfree(spat->spat_regexp);
129 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
130 spat->spat_flags & SPAT_FOLD);
131 if (!*spat->spat_regexp->precomp && lastspat)
133 if (spat->spat_flags & SPAT_KEEP) {
134 if (spat->spat_runtime)
135 arg_free(spat->spat_runtime); /* it won't change, so */
136 spat->spat_runtime = Nullarg; /* no point compiling again */
138 if (!spat->spat_regexp->nparens)
139 gimme = G_SCALAR; /* accidental array context? */
140 if (regexec(spat->spat_regexp, s, strend, s, 0,
141 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
143 if (spat->spat_regexp->subbase)
149 if (gimme == G_ARRAY)
151 str_sset(str,&str_no);
162 if (spat->spat_flags & SPAT_ONCE)
166 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
169 if (!*spat->spat_regexp->precomp && lastspat)
173 if (myhint < s || myhint > strend)
174 fatal("panic: hint in do_match");
176 if (spat->spat_regexp->regback >= 0) {
177 s -= spat->spat_regexp->regback;
184 else if (spat->spat_short) {
185 if (spat->spat_flags & SPAT_SCANFIRST) {
186 if (srchstr->str_pok & SP_STUDIED) {
187 if (screamfirst[spat->spat_short->str_rare] < 0)
189 else if (!(s = screaminstr(srchstr,spat->spat_short)))
191 else if (spat->spat_flags & SPAT_ALL)
195 else if (!(s = fbminstr((unsigned char*)s,
196 (unsigned char*)strend, spat->spat_short)))
199 else if (spat->spat_flags & SPAT_ALL)
201 if (s && spat->spat_regexp->regback >= 0) {
202 ++spat->spat_short->str_u.str_useful;
203 s -= spat->spat_regexp->regback;
210 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
211 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
213 if (--spat->spat_short->str_u.str_useful < 0) {
214 str_free(spat->spat_short);
215 spat->spat_short = Nullstr; /* opt is being useless */
218 if (!spat->spat_regexp->nparens)
219 gimme = G_SCALAR; /* accidental array context? */
220 if (regexec(spat->spat_regexp, s, strend, t, 0,
221 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
223 if (spat->spat_regexp->subbase)
226 if (spat->spat_flags & SPAT_ONCE)
227 spat->spat_flags |= SPAT_USED;
231 if (gimme == G_ARRAY)
233 str_sset(str,&str_no);
242 if (gimme == G_ARRAY) {
245 iters = spat->spat_regexp->nparens;
246 if (sp + iters >= stack->ary_max) {
247 astore(stack,sp + iters, Nullstr);
248 st = stack->ary_array; /* possibly realloced */
251 for (i = 1; i <= iters; i++) {
252 st[++sp] = str_static(&str_no);
253 if (s = spat->spat_regexp->startp[i]) {
254 len = spat->spat_regexp->endp[i] - s;
256 str_nset(st[sp],s,len);
262 str_sset(str,&str_yes);
269 ++spat->spat_short->str_u.str_useful;
271 if (spat->spat_flags & SPAT_ONCE)
272 spat->spat_flags |= SPAT_USED;
276 if (spat->spat_regexp->subbase)
277 Safefree(spat->spat_regexp->subbase);
278 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
279 spat->spat_regexp->subend = tmps + (strend-t);
280 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
281 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
284 str_sset(str,&str_yes);
290 ++spat->spat_short->str_u.str_useful;
291 if (gimme == G_ARRAY)
293 str_sset(str,&str_no);
300 #pragma intrinsic(memcmp)
301 #endif /* BUGGY_MSC */
304 do_split(str,spat,limit,gimme,arglast)
311 register ARRAY *ary = stack;
312 STR **st = ary->ary_array;
313 register int sp = arglast[0] + 1;
314 register char *s = str_get(st[sp]);
315 char *strend = s + st[sp--]->str_cur;
319 int maxiters = (strend - s) + 10;
322 int origlimit = limit;
326 fatal("panic: do_split");
327 else if (spat->spat_runtime) {
329 sp = eval(spat->spat_runtime,G_SCALAR,sp);
330 st = stack->ary_array;
331 m = str_get(dstr = st[sp--]);
333 if (*m == ' ' && dstr->str_cur == 1) {
334 str_set(dstr,"\\s+");
336 spat->spat_flags |= SPAT_SKIPWHITE;
338 if (spat->spat_regexp)
339 regfree(spat->spat_regexp);
340 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
341 spat->spat_flags & SPAT_FOLD);
342 if (spat->spat_flags & SPAT_KEEP ||
343 (spat->spat_runtime->arg_type == O_ITEM &&
344 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
345 arg_free(spat->spat_runtime); /* it won't change, so */
346 spat->spat_runtime = Nullarg; /* no point compiling again */
351 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
354 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
355 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
357 if (!(ary->ary_flags & ARF_REAL)) {
358 ary->ary_flags |= ARF_REAL;
359 for (i = ary->ary_fill; i >= 0; i--)
360 ary->ary_array[i] = Nullstr; /* don't free mere refs */
363 sp = -1; /* temporarily switch stacks */
368 if (spat->spat_flags & SPAT_SKIPWHITE) {
373 limit = maxiters + 2;
374 if (strEQ("\\s+",spat->spat_regexp->precomp)) {
376 for (m = s; m < strend && !isspace(*m); m++) ;
380 dstr = Str_new(30,m-s);
382 dstr = str_static(&str_undef);
383 str_nset(dstr,s,m-s);
384 (void)astore(ary, ++sp, dstr);
385 for (s = m + 1; s < strend && isspace(*s); s++) ;
388 else if (strEQ("^",spat->spat_regexp->precomp)) {
390 for (m = s; m < strend && *m != '\n'; m++) ;
395 dstr = Str_new(30,m-s);
397 dstr = str_static(&str_undef);
398 str_nset(dstr,s,m-s);
399 (void)astore(ary, ++sp, dstr);
403 else if (spat->spat_short) {
404 i = spat->spat_short->str_cur;
406 int fold = (spat->spat_flags & SPAT_FOLD);
408 i = *spat->spat_short->str_ptr;
409 if (fold && isupper(i))
414 m < strend && *m != i &&
415 (!isupper(*m) || tolower(*m) != i);
420 for (m = s; m < strend && *m != i; m++) ;
424 dstr = Str_new(30,m-s);
426 dstr = str_static(&str_undef);
427 str_nset(dstr,s,m-s);
428 (void)astore(ary, ++sp, dstr);
434 while (s < strend && --limit &&
435 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
440 dstr = Str_new(31,m-s);
442 dstr = str_static(&str_undef);
443 str_nset(dstr,s,m-s);
444 (void)astore(ary, ++sp, dstr);
450 maxiters += (strend - s) * spat->spat_regexp->nparens;
451 while (s < strend && --limit &&
452 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
453 if (spat->spat_regexp->subbase
454 && spat->spat_regexp->subbase != orig) {
457 orig = spat->spat_regexp->subbase;
459 strend = s + (strend - m);
461 m = spat->spat_regexp->startp[0];
463 dstr = Str_new(32,m-s);
465 dstr = str_static(&str_undef);
466 str_nset(dstr,s,m-s);
467 (void)astore(ary, ++sp, dstr);
468 if (spat->spat_regexp->nparens) {
469 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
470 s = spat->spat_regexp->startp[i];
471 m = spat->spat_regexp->endp[i];
473 dstr = Str_new(33,m-s);
475 dstr = str_static(&str_undef);
476 str_nset(dstr,s,m-s);
477 (void)astore(ary, ++sp, dstr);
480 s = spat->spat_regexp->endp[0];
486 iters = sp - arglast[0];
487 if (iters > maxiters)
489 if (s < strend || origlimit) { /* keep field after final delim? */
491 dstr = Str_new(34,strend-s);
493 dstr = str_static(&str_undef);
494 str_nset(dstr,s,strend-s);
495 (void)astore(ary, ++sp, dstr);
500 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
507 zaps = str_get(afetch(ary,sp,FALSE));
511 while (iters > 0 && (!zapb)) {
514 zaps = str_get(afetch(ary,iters-1,FALSE));
522 if (gimme == G_ARRAY) {
524 astore(stack, arglast[0] + 1 + sp, Nullstr);
525 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
526 return arglast[0] + sp;
530 if (gimme == G_ARRAY)
534 str_numset(str,(double)iters);
541 do_unpack(str,gimme,arglast)
546 STR **st = stack->ary_array;
547 register int sp = arglast[0] + 1;
548 register char *pat = str_get(st[sp++]);
549 register char *s = str_get(st[sp]);
550 char *strend = s + st[sp--]->str_cur;
552 register char *patend = pat + st[sp]->str_cur;
556 /* These must not be in registers: */
561 unsigned char auchar;
562 unsigned short aushort;
564 unsigned long aulong;
569 unsigned long culong;
572 if (gimme != G_ARRAY) { /* arrange to do first one only */
573 for (patend = pat; !isalpha(*patend); patend++);
574 if (*patend == 'a' || *patend == 'A' || *pat == '%') {
576 while (isdigit(*patend) || *patend == '*')
583 while (pat < patend) {
588 else if (*pat == '*')
589 len = strend - strbeg; /* long enough */
590 else if (isdigit(*pat)) {
592 while (isdigit(*pat))
593 len = (len * 10) + (*pat++ - '0');
596 len = (datumtype != '@');
601 if (len == 1 && pat[-1] != '1')
610 if (len > strend - s)
611 fatal("@ outside of string");
615 if (len > s - strbeg)
616 fatal("X outside of string");
620 if (len > strend - s)
621 fatal("x outside of string");
626 if (len > strend - s)
630 str = Str_new(35,len);
633 if (datumtype == 'A') {
634 aptr = s; /* borrow register */
635 s = str->str_ptr + len - 1;
636 while (s >= str->str_ptr && (!*s || isspace(*s)))
639 str->str_cur = s - str->str_ptr;
640 s = aptr; /* unborrow register */
642 (void)astore(stack, ++sp, str_2static(str));
645 if (len > strend - s)
650 if (aint >= 128) /* fake up signed chars */
658 if (aint >= 128) /* fake up signed chars */
661 str_numset(str,(double)aint);
662 (void)astore(stack, ++sp, str_2static(str));
667 if (len > strend - s)
680 str_numset(str,(double)auint);
681 (void)astore(stack, ++sp, str_2static(str));
686 along = (strend - s) / sizeof(short);
691 bcopy(s,(char*)&ashort,sizeof(short));
698 bcopy(s,(char*)&ashort,sizeof(short));
701 str_numset(str,(double)ashort);
702 (void)astore(stack, ++sp, str_2static(str));
708 along = (strend - s) / sizeof(unsigned short);
713 bcopy(s,(char*)&aushort,sizeof(unsigned short));
714 s += sizeof(unsigned short);
716 if (datumtype == 'n')
717 aushort = ntohs(aushort);
724 bcopy(s,(char*)&aushort,sizeof(unsigned short));
725 s += sizeof(unsigned short);
728 if (datumtype == 'n')
729 aushort = ntohs(aushort);
731 str_numset(str,(double)aushort);
732 (void)astore(stack, ++sp, str_2static(str));
737 along = (strend - s) / sizeof(int);
742 bcopy(s,(char*)&aint,sizeof(int));
745 cdouble += (double)aint;
752 bcopy(s,(char*)&aint,sizeof(int));
755 str_numset(str,(double)aint);
756 (void)astore(stack, ++sp, str_2static(str));
761 along = (strend - s) / sizeof(unsigned int);
766 bcopy(s,(char*)&auint,sizeof(unsigned int));
767 s += sizeof(unsigned int);
769 cdouble += (double)auint;
776 bcopy(s,(char*)&auint,sizeof(unsigned int));
777 s += sizeof(unsigned int);
779 str_numset(str,(double)auint);
780 (void)astore(stack, ++sp, str_2static(str));
785 along = (strend - s) / sizeof(long);
790 bcopy(s,(char*)&along,sizeof(long));
793 cdouble += (double)along;
800 bcopy(s,(char*)&along,sizeof(long));
803 str_numset(str,(double)along);
804 (void)astore(stack, ++sp, str_2static(str));
810 along = (strend - s) / sizeof(unsigned long);
815 bcopy(s,(char*)&aulong,sizeof(unsigned long));
816 s += sizeof(unsigned long);
818 if (datumtype == 'N')
819 aulong = ntohl(aulong);
822 cdouble += (double)aulong;
829 bcopy(s,(char*)&aulong,sizeof(unsigned long));
830 s += sizeof(unsigned long);
833 if (datumtype == 'N')
834 aulong = ntohl(aulong);
836 str_numset(str,(double)aulong);
837 (void)astore(stack, ++sp, str_2static(str));
842 along = (strend - s) / sizeof(char*);
846 if (sizeof(char*) > strend - s)
849 bcopy(s,(char*)&aptr,sizeof(char*));
855 (void)astore(stack, ++sp, str_2static(str));
858 /* float and double added gnb@melba.bby.oz.au 22/11/89 */
861 along = (strend - s) / sizeof(float);
866 bcopy(s, (char *)&afloat, sizeof(float));
873 bcopy(s, (char *)&afloat, sizeof(float));
875 str = Str_new(47, 0);
876 str_numset(str, (double)afloat);
877 (void)astore(stack, ++sp, str_2static(str));
883 along = (strend - s) / sizeof(double);
888 bcopy(s, (char *)&adouble, sizeof(double));
895 bcopy(s, (char *)&adouble, sizeof(double));
897 str = Str_new(48, 0);
898 str_numset(str, (double)adouble);
899 (void)astore(stack, ++sp, str_2static(str));
904 along = (strend - s) * 3 / 4;
905 str = Str_new(42,along);
906 while (s < strend && *s > ' ' && *s < 'a') {
911 len = (*s++ - ' ') & 077;
913 if (s < strend && *s >= ' ')
914 a = (*s++ - ' ') & 077;
917 if (s < strend && *s >= ' ')
918 b = (*s++ - ' ') & 077;
921 if (s < strend && *s >= ' ')
922 c = (*s++ - ' ') & 077;
925 if (s < strend && *s >= ' ')
926 d = (*s++ - ' ') & 077;
929 hunk[0] = a << 2 | b >> 4;
930 hunk[1] = b << 4 | c >> 2;
931 hunk[2] = c << 6 | d;
932 str_ncat(str,hunk, len > 3 ? 3 : len);
937 else if (s[1] == '\n') /* possible checksum byte */
940 (void)astore(stack, ++sp, str_2static(str));
945 if (index("fFdD", datumtype) ||
946 (checksum > 32 && index("iIlLN", datumtype)) ) {
951 while (checksum >= 16) {
955 while (checksum >= 4) {
961 along = (1 << checksum) - 1;
962 while (cdouble < 0.0)
964 cdouble = modf(cdouble / adouble, &trouble) * adouble;
965 str_numset(str,cdouble);
968 along = (1 << checksum) - 1;
969 culong &= (unsigned long)along;
970 str_numset(str,(double)culong);
972 (void)astore(stack, ++sp, str_2static(str));
980 do_slice(stab,str,numarray,lval,gimme,arglast)
988 register STR **st = stack->ary_array;
989 register int sp = arglast[1];
990 register int max = arglast[2];
993 register int magic = 0;
996 int oldarybase = arybase;
999 if (numarray == 2) { /* a slice of a LIST */
1001 ary->ary_fill = arglast[3];
1003 st[sp] = str; /* make stack size available */
1004 str_numset(str,(double)(sp - 1));
1007 ary = stab_array(stab); /* a slice of an array */
1011 if (stab == envstab)
1013 else if (stab == sigstab)
1016 else if (stab_hash(stab)->tbl_dbm)
1018 #endif /* SOME_DBM */
1020 hash = stab_hash(stab); /* a slice of an associative array */
1023 if (gimme == G_ARRAY) {
1027 st[sp-1] = afetch(ary,
1028 ((int)str_gnum(st[sp])) - arybase, lval);
1031 st[sp-1] = &str_undef;
1037 tmps = str_get(st[sp]);
1038 len = st[sp]->str_cur;
1039 st[sp-1] = hfetch(hash,tmps,len, lval);
1041 str_magic(st[sp-1],stab,magic,tmps,len);
1044 st[sp-1] = &str_undef;
1052 st[sp] = afetch(ary,
1053 ((int)str_gnum(st[max])) - arybase, lval);
1055 st[sp] = &str_undef;
1059 tmps = str_get(st[max]);
1060 len = st[max]->str_cur;
1061 st[sp] = hfetch(hash,tmps,len, lval);
1063 str_magic(st[sp],stab,magic,tmps,len);
1066 st[sp] = &str_undef;
1069 arybase = oldarybase;
1074 do_splice(ary,gimme,arglast)
1075 register ARRAY *ary;
1079 register STR **st = stack->ary_array;
1080 register int sp = arglast[1];
1081 int max = arglast[2] + 1;
1085 register int offset;
1086 register int length;
1093 offset = ((int)str_gnum(st[sp])) - arybase;
1095 offset += ary->ary_fill + 1;
1097 length = (int)str_gnum(st[sp++]);
1102 length = ary->ary_max; /* close enough to infinity */
1106 length = ary->ary_max;
1114 if (offset > ary->ary_fill + 1)
1115 offset = ary->ary_fill + 1;
1116 after = ary->ary_fill + 1 - (offset + length);
1117 if (after < 0) { /* not that much array */
1118 length += after; /* offset+length now in array */
1120 if (!ary->ary_alloc) {
1126 /* At this point, sp .. max-1 is our new LIST */
1129 diff = newlen - length;
1131 if (diff < 0) { /* shrinking the area */
1133 New(451, tmparyval, newlen, STR*); /* so remember insertion */
1134 Copy(st+sp, tmparyval, newlen, STR*);
1137 sp = arglast[0] + 1;
1138 if (gimme == G_ARRAY) { /* copy return vals to stack */
1139 if (sp + length >= stack->ary_max) {
1140 astore(stack,sp + length, Nullstr);
1141 st = stack->ary_array;
1143 Copy(ary->ary_array+offset, st+sp, length, STR*);
1144 if (ary->ary_flags & ARF_REAL) {
1145 for (i = length, dst = st+sp; i; i--)
1146 str_2static(*dst++); /* free them eventualy */
1151 st[sp] = ary->ary_array[offset+length-1];
1152 if (ary->ary_flags & ARF_REAL)
1153 str_2static(st[sp]);
1155 ary->ary_fill += diff;
1157 /* pull up or down? */
1159 if (offset < after) { /* easier to pull up */
1160 if (offset) { /* esp. if nothing to pull */
1161 src = &ary->ary_array[offset-1];
1162 dst = src - diff; /* diff is negative */
1163 for (i = offset; i > 0; i--) /* can't trust Copy */
1166 Zero(ary->ary_array, -diff, STR*);
1167 ary->ary_array -= diff; /* diff is negative */
1168 ary->ary_max += diff;
1171 if (after) { /* anything to pull down? */
1172 src = ary->ary_array + offset + length;
1173 dst = src + diff; /* diff is negative */
1174 Copy(src, dst, after, STR*);
1176 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
1177 /* avoid later double free */
1180 for (src = tmparyval, dst = ary->ary_array + offset;
1182 *dst = Str_new(46,0);
1183 str_sset(*dst++,*src++);
1185 Safefree(tmparyval);
1188 else { /* no, expanding (or same) */
1190 New(452, tmparyval, length, STR*); /* so remember deletion */
1191 Copy(ary->ary_array+offset, tmparyval, length, STR*);
1194 if (diff > 0) { /* expanding */
1196 /* push up or down? */
1198 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
1200 src = ary->ary_array;
1202 Copy(src, dst, offset, STR*);
1204 ary->ary_array -= diff; /* diff is positive */
1205 ary->ary_max += diff;
1206 ary->ary_fill += diff;
1209 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
1210 astore(ary, ary->ary_fill + diff, Nullstr);
1212 ary->ary_fill += diff;
1214 dst = ary->ary_array + ary->ary_fill;
1216 for (i = after; i; i--) {
1217 if (*dst) /* str was hanging around */
1218 str_free(*dst); /* after $#foo */
1226 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
1227 *dst = Str_new(46,0);
1228 str_sset(*dst++,*src++);
1230 sp = arglast[0] + 1;
1231 if (gimme == G_ARRAY) { /* copy return vals to stack */
1233 Copy(tmparyval, st+sp, length, STR*);
1234 if (ary->ary_flags & ARF_REAL) {
1235 for (i = length, dst = st+sp; i; i--)
1236 str_2static(*dst++); /* free them eventualy */
1238 Safefree(tmparyval);
1243 st[sp] = tmparyval[length-1];
1244 if (ary->ary_flags & ARF_REAL)
1245 str_2static(st[sp]);
1246 Safefree(tmparyval);
1249 st[sp] = &str_undef;
1255 do_grep(arg,str,gimme,arglast)
1261 STR **st = stack->ary_array;
1262 register int dst = arglast[1];
1263 register int src = dst + 1;
1264 register int sp = arglast[2];
1265 register int i = sp - arglast[1];
1266 int oldsave = savestack->ary_fill;
1267 SPAT *oldspat = curspat;
1269 savesptr(&stab_val(defstab));
1270 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
1271 arg[1].arg_type &= A_MASK;
1273 arg[1].arg_type |= A_DONT;
1275 arg = arg[1].arg_ptr.arg_arg;
1278 stab_val(defstab) = st[src];
1280 stab_val(defstab) = str_static(&str_undef);
1281 (void)eval(arg,G_SCALAR,sp);
1282 st = stack->ary_array;
1283 if (str_true(st[sp+1]))
1284 st[dst++] = st[src];
1288 restorelist(oldsave);
1289 if (gimme != G_ARRAY) {
1290 str_numset(str,(double)(dst - arglast[1]));
1292 st[arglast[0]+1] = str;
1293 return arglast[0]+1;
1295 return arglast[0] + (dst - arglast[1]);
1299 do_reverse(str,gimme,arglast)
1304 STR **st = stack->ary_array;
1305 register STR **up = &st[arglast[1]];
1306 register STR **down = &st[arglast[2]];
1307 register int i = arglast[2] - arglast[1];
1314 i = arglast[2] - arglast[1];
1315 Copy(down+1,up,i/2,STR*);
1316 return arglast[2] - 1;
1320 do_sreverse(str,gimme,arglast)
1325 STR **st = stack->ary_array;
1327 register char *down;
1330 str_sset(str,st[arglast[2]]);
1332 if (str->str_cur > 1) {
1333 down = str->str_ptr + str->str_cur - 1;
1341 st[arglast[0]+1] = str;
1342 return arglast[0]+1;
1345 static CMD *sortcmd;
1346 static STAB *firststab = Nullstab;
1347 static STAB *secondstab = Nullstab;
1350 do_sort(str,stab,gimme,arglast)
1356 register STR **st = stack->ary_array;
1357 int sp = arglast[1];
1359 register int max = arglast[2] - sp;
1366 static ARRAY *sortstack = Null(ARRAY*);
1368 if (gimme != G_ARRAY) {
1369 str_sset(str,&str_undef);
1375 st += sp; /* temporarily make st point to args */
1376 for (i = 1; i <= max; i++) {
1378 if (!(*up)->str_pok)
1379 (void)str_2ptr(*up);
1388 int oldtmps_base = tmps_base;
1390 if (!stab_sub(stab) || !(sortcmd = stab_sub(stab)->cmd))
1391 fatal("Undefined subroutine \"%s\" in sort", stab_name(stab));
1393 sortstack = anew(Nullstab);
1394 sortstack->ary_flags = 0;
1398 tmps_base = tmps_max;
1400 firststab = stabent("a",TRUE);
1401 secondstab = stabent("b",TRUE);
1403 oldfirst = stab_val(firststab);
1404 oldsecond = stab_val(secondstab);
1406 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1408 qsort(Nullch,max,sizeof(STR*),sortsub);
1410 stab_val(firststab) = oldfirst;
1411 stab_val(secondstab) = oldsecond;
1412 tmps_base = oldtmps_base;
1417 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1428 stab_val(firststab) = *str1;
1429 stab_val(secondstab) = *str2;
1430 cmd_exec(sortcmd,G_SCALAR,-1);
1431 return (int)str_gnum(*stack->ary_array);
1434 sortcmp(strp1,strp2)
1438 register STR *str1 = *strp1;
1439 register STR *str2 = *strp2;
1442 if (str1->str_cur < str2->str_cur) {
1443 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1448 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1450 else if (str1->str_cur == str2->str_cur)
1457 do_range(gimme,arglast)
1461 STR **st = stack->ary_array;
1462 register int sp = arglast[0];
1464 register ARRAY *ary = stack;
1468 if (gimme != G_ARRAY)
1469 fatal("panic: do_range");
1471 if (st[sp+1]->str_nok ||
1472 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1473 i = (int)str_gnum(st[sp+1]);
1474 max = (int)str_gnum(st[sp+2]);
1476 (void)astore(ary, ++sp, str = str_static(&str_no));
1477 str_numset(str,(double)i++);
1481 STR *final = str_static(st[sp+2]);
1482 char *tmps = str_get(final);
1484 str = str_static(st[sp+1]);
1485 while (!str->str_nok && str->str_cur <= final->str_cur &&
1486 strNE(str->str_ptr,tmps) ) {
1487 (void)astore(ary, ++sp, str);
1488 str = str_static(str);
1491 if (strEQ(str->str_ptr,tmps))
1492 (void)astore(ary, ++sp, str);
1498 do_caller(arg,maxarg,gimme,arglast)
1504 STR **st = stack->ary_array;
1505 register int sp = arglast[0];
1506 register CSV *csv = curcsv;
1511 fatal("There is no caller");
1513 count = (int) str_gnum(st[sp+1]);
1517 if (csv->curcsv && csv->curcsv->sub == stab_sub(DBsub))
1523 if (gimme != G_ARRAY) {
1524 STR *str = arg->arg_ptr.arg_str;
1525 str_set(str,csv->curcmd->c_stash->tbl_name);
1532 (void)astore(stack,++sp,
1533 str_2static(str_make(csv->curcmd->c_stash->tbl_name,0)) );
1534 (void)astore(stack,++sp,
1535 str_2static(str_make(stab_val(csv->curcmd->c_filestab)->str_ptr,0)) );
1536 (void)astore(stack,++sp,
1537 str_2static(str_nmake((double)csv->curcmd->c_line)) );
1540 str = str_static(&str_undef);
1541 stab_fullname(str, csv->stab);
1542 (void)astore(stack,++sp, str);
1543 (void)astore(stack,++sp,
1544 str_2static(str_nmake((double)csv->hasargs)) );
1545 (void)astore(stack,++sp,
1546 str_2static(str_nmake((double)csv->wantarray)) );
1548 ARRAY *ary = csv->argarray;
1550 if (dbargs->ary_max < ary->ary_fill)
1551 astore(dbargs,ary->ary_fill,Nullstr);
1552 Copy(ary->ary_array, dbargs->ary_array, ary->ary_fill+1, STR*);
1553 dbargs->ary_fill = ary->ary_fill;
1556 (void)astore(stack,++sp,
1557 str_2static(str_make("",0)));
1563 do_tms(str,gimme,arglast)
1571 STR **st = stack->ary_array;
1572 register int sp = arglast[0];
1574 if (gimme != G_ARRAY) {
1575 str_sset(str,&str_undef);
1580 (void)times(×buf);
1587 (void)astore(stack,++sp,
1588 str_2static(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1589 (void)astore(stack,++sp,
1590 str_2static(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1591 (void)astore(stack,++sp,
1592 str_2static(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1593 (void)astore(stack,++sp,
1594 str_2static(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1596 (void)astore(stack,++sp,
1597 str_2static(str_nmake(0.0)));
1604 do_time(str,tmbuf,gimme,arglast)
1610 register ARRAY *ary = stack;
1611 STR **st = ary->ary_array;
1612 register int sp = arglast[0];
1614 if (!tmbuf || gimme != G_ARRAY) {
1615 str_sset(str,&str_undef);
1620 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_sec)));
1621 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_min)));
1622 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_hour)));
1623 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mday)));
1624 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mon)));
1625 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_year)));
1626 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_wday)));
1627 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_yday)));
1628 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_isdst)));
1633 do_kv(str,hash,kv,gimme,arglast)
1640 register ARRAY *ary = stack;
1641 STR **st = ary->ary_array;
1642 register int sp = arglast[0];
1644 register HENT *entry;
1647 int dokeys = (kv == O_KEYS || kv == O_HASH);
1648 int dovalues = (kv == O_VALUES || kv == O_HASH);
1650 if (gimme != G_ARRAY) {
1651 str_sset(str,&str_undef);
1656 (void)hiterinit(hash);
1657 while (entry = hiternext(hash)) {
1659 tmps = hiterkey(entry,&i);
1662 (void)astore(ary,++sp,str_2static(str_make(tmps,i)));
1665 tmpstr = Str_new(45,0);
1668 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1669 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1670 str_set(tmpstr,buf);
1674 str_sset(tmpstr,hiterval(hash,entry));
1675 (void)astore(ary,++sp,str_2static(tmpstr));
1682 do_each(str,hash,gimme,arglast)
1688 STR **st = stack->ary_array;
1689 register int sp = arglast[0];
1690 static STR *mystrk = Nullstr;
1691 HENT *entry = hiternext(hash);
1701 if (gimme == G_ARRAY) {
1702 tmps = hiterkey(entry, &i);
1705 st[++sp] = mystrk = str_make(tmps,i);
1708 str_sset(str,hiterval(hash,entry));