1 /* $Header: dolist.c,v 3.0.1.7 90/03/27 15:48:42 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.7 90/03/27 15:48:42 lwall
10 * patch16: MSDOS support
11 * patch16: use of $`, $& or $' sometimes causes memory leakage
12 * patch16: splice(@array,0,$n) case cause duplicate free
13 * patch16: grep blows up on undefined array values
14 * patch16: .. now works using magical string increment
16 * Revision 3.0.1.6 90/03/12 16:33:02 lwall
17 * patch13: added list slice operator (LIST)[LIST]
18 * patch13: added splice operator: @oldelems = splice(@array,$offset,$len,LIST)
19 * patch13: made split('') act like split(//) rather than split(' ')
21 * Revision 3.0.1.5 90/02/28 17:09:44 lwall
22 * patch9: split now can split into more than 10000 elements
23 * patch9: @_ clobbered by ($foo,$bar) = split
24 * patch9: sped up pack and unpack
25 * patch9: unpack of single item now works in a scalar context
26 * patch9: slices ignored value of $[
27 * patch9: grep now returns number of items matched in scalar context
28 * patch9: grep iterations no longer in the regexp context of previous iteration
30 * Revision 3.0.1.4 89/12/21 19:58:46 lwall
31 * patch7: grep(1,@array) didn't work
32 * patch7: /$pat/; //; wrongly freed runtime pattern twice
34 * Revision 3.0.1.3 89/11/17 15:14:45 lwall
35 * patch5: grep() occasionally loses arguments or dumps core
37 * Revision 3.0.1.2 89/11/11 04:28:17 lwall
38 * patch2: non-existent slice values are now undefined rather than null
40 * Revision 3.0.1.1 89/10/26 23:11:51 lwall
41 * patch1: split in a subroutine wrongly freed referenced arguments
42 * patch1: reverse didn't work
44 * Revision 3.0 89/10/18 15:11:02 lwall
54 #pragma function(memcmp)
55 #endif /* BUGGY_MSC */
58 do_match(str,arg,gimme,arglast)
64 register STR **st = stack->ary_array;
65 register SPAT *spat = arg[2].arg_ptr.arg_spat;
67 register int sp = arglast[0] + 1;
68 STR *srchstr = st[sp];
69 register char *s = str_get(st[sp]);
70 char *strend = s + st[sp]->str_cur;
82 fatal("panic: do_match");
83 if (spat->spat_flags & SPAT_USED) {
96 if (spat->spat_runtime) {
98 sp = eval(spat->spat_runtime,G_SCALAR,sp);
99 st = stack->ary_array;
100 t = str_get(tmpstr = st[sp--]);
104 deb("2.SPAT /%s/\n",t);
106 if (spat->spat_regexp)
107 regfree(spat->spat_regexp);
108 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
109 spat->spat_flags & SPAT_FOLD,1);
110 if (!*spat->spat_regexp->precomp && lastspat)
112 if (spat->spat_flags & SPAT_KEEP) {
113 if (spat->spat_runtime)
114 arg_free(spat->spat_runtime); /* it won't change, so */
115 spat->spat_runtime = Nullarg; /* no point compiling again */
117 if (!spat->spat_regexp->nparens)
118 gimme = G_SCALAR; /* accidental array context? */
119 if (regexec(spat->spat_regexp, s, strend, s, 0,
120 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
122 if (spat->spat_regexp->subbase)
128 if (gimme == G_ARRAY)
130 str_sset(str,&str_no);
141 if (spat->spat_flags & SPAT_ONCE)
145 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
148 if (!*spat->spat_regexp->precomp && lastspat)
152 if (hint < s || hint > strend)
153 fatal("panic: hint in do_match");
156 if (spat->spat_regexp->regback >= 0) {
157 s -= spat->spat_regexp->regback;
164 else if (spat->spat_short) {
165 if (spat->spat_flags & SPAT_SCANFIRST) {
166 if (srchstr->str_pok & SP_STUDIED) {
167 if (screamfirst[spat->spat_short->str_rare] < 0)
169 else if (!(s = screaminstr(srchstr,spat->spat_short)))
171 else if (spat->spat_flags & SPAT_ALL)
175 else if (!(s = fbminstr((unsigned char*)s,
176 (unsigned char*)strend, spat->spat_short)))
179 else if (spat->spat_flags & SPAT_ALL)
181 if (s && spat->spat_regexp->regback >= 0) {
182 ++spat->spat_short->str_u.str_useful;
183 s -= spat->spat_regexp->regback;
190 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
191 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
193 if (--spat->spat_short->str_u.str_useful < 0) {
194 str_free(spat->spat_short);
195 spat->spat_short = Nullstr; /* opt is being useless */
198 if (!spat->spat_regexp->nparens)
199 gimme = G_SCALAR; /* accidental array context? */
200 if (regexec(spat->spat_regexp, s, strend, t, 0,
201 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
203 if (spat->spat_regexp->subbase)
206 if (spat->spat_flags & SPAT_ONCE)
207 spat->spat_flags |= SPAT_USED;
211 if (gimme == G_ARRAY)
213 str_sset(str,&str_no);
222 if (gimme == G_ARRAY) {
225 iters = spat->spat_regexp->nparens;
226 if (sp + iters >= stack->ary_max) {
227 astore(stack,sp + iters, Nullstr);
228 st = stack->ary_array; /* possibly realloced */
231 for (i = 1; i <= iters; i++) {
232 st[++sp] = str_static(&str_no);
233 if (s = spat->spat_regexp->startp[i]) {
234 len = spat->spat_regexp->endp[i] - s;
236 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;
256 if (spat->spat_regexp->subbase)
257 Safefree(spat->spat_regexp->subbase);
258 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
259 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
260 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
263 str_sset(str,&str_yes);
269 ++spat->spat_short->str_u.str_useful;
270 if (gimme == G_ARRAY)
272 str_sset(str,&str_no);
279 #pragma intrinsic(memcmp)
280 #endif /* BUGGY_MSC */
283 do_split(str,spat,limit,gimme,arglast)
290 register ARRAY *ary = stack;
291 STR **st = ary->ary_array;
292 register int sp = arglast[0] + 1;
293 register char *s = str_get(st[sp]);
294 char *strend = s + st[sp--]->str_cur;
298 int maxiters = (strend - s) + 10;
301 int origlimit = limit;
305 fatal("panic: do_split");
306 else if (spat->spat_runtime) {
308 sp = eval(spat->spat_runtime,G_SCALAR,sp);
309 st = stack->ary_array;
310 m = str_get(dstr = st[sp--]);
312 if (*m == ' ' && dstr->str_cur == 1) {
313 str_set(dstr,"\\s+");
315 spat->spat_flags |= SPAT_SKIPWHITE;
317 if (spat->spat_regexp)
318 regfree(spat->spat_regexp);
319 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
320 spat->spat_flags & SPAT_FOLD,1);
321 if (spat->spat_flags & SPAT_KEEP ||
322 (spat->spat_runtime->arg_type == O_ITEM &&
323 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
324 arg_free(spat->spat_runtime); /* it won't change, so */
325 spat->spat_runtime = Nullarg; /* no point compiling again */
330 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
333 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
334 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
336 if (!(ary->ary_flags & ARF_REAL)) {
337 ary->ary_flags |= ARF_REAL;
338 for (i = ary->ary_fill; i >= 0; i--)
339 ary->ary_array[i] = Nullstr; /* don't free mere refs */
342 sp = -1; /* temporarily switch stacks */
347 if (spat->spat_flags & SPAT_SKIPWHITE) {
352 limit = maxiters + 2;
353 if (spat->spat_short) {
354 i = spat->spat_short->str_cur;
356 i = *spat->spat_short->str_ptr;
358 for (m = s; m < strend && *m != i; m++) ;
362 dstr = Str_new(30,m-s);
364 dstr = str_static(&str_undef);
365 str_nset(dstr,s,m-s);
366 (void)astore(ary, ++sp, dstr);
372 while (s < strend && --limit &&
373 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
378 dstr = Str_new(31,m-s);
380 dstr = str_static(&str_undef);
381 str_nset(dstr,s,m-s);
382 (void)astore(ary, ++sp, dstr);
388 maxiters += (strend - s) * spat->spat_regexp->nparens;
389 while (s < strend && --limit &&
390 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
391 if (spat->spat_regexp->subbase
392 && spat->spat_regexp->subbase != orig) {
395 orig = spat->spat_regexp->subbase;
397 strend = s + (strend - m);
399 m = spat->spat_regexp->startp[0];
401 dstr = Str_new(32,m-s);
403 dstr = str_static(&str_undef);
404 str_nset(dstr,s,m-s);
405 (void)astore(ary, ++sp, dstr);
406 if (spat->spat_regexp->nparens) {
407 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
408 s = spat->spat_regexp->startp[i];
409 m = spat->spat_regexp->endp[i];
411 dstr = Str_new(33,m-s);
413 dstr = str_static(&str_undef);
414 str_nset(dstr,s,m-s);
415 (void)astore(ary, ++sp, dstr);
418 s = spat->spat_regexp->endp[0];
424 iters = sp - arglast[0];
425 if (iters > maxiters)
427 if (s < strend || origlimit) { /* keep field after final delim? */
429 dstr = Str_new(34,strend-s);
431 dstr = str_static(&str_undef);
432 str_nset(dstr,s,strend-s);
433 (void)astore(ary, ++sp, dstr);
438 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
445 zaps = str_get(afetch(ary,sp,FALSE));
449 while (iters > 0 && (!zapb)) {
452 zaps = str_get(afetch(ary,iters-1,FALSE));
460 if (gimme == G_ARRAY) {
462 astore(stack, arglast[0] + 1 + sp, Nullstr);
463 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
464 return arglast[0] + sp;
468 if (gimme == G_ARRAY)
472 str_numset(str,(double)iters);
479 do_unpack(str,gimme,arglast)
484 STR **st = stack->ary_array;
485 register int sp = arglast[0] + 1;
486 register char *pat = str_get(st[sp++]);
487 register char *s = str_get(st[sp]);
488 char *strend = s + st[sp--]->str_cur;
489 register char *patend = pat + st[sp]->str_cur;
493 /* These must not be in registers: */
498 unsigned char auchar;
499 unsigned short aushort;
501 unsigned long aulong;
504 if (gimme != G_ARRAY) { /* arrange to do first one only */
506 if (*pat == 'a' || *pat == 'A') {
507 while (isdigit(*patend))
512 while (pat < patend) {
516 while (isdigit(*pat))
517 len = (len * 10) + (*pat++ - '0');
529 if (s + len > strend)
531 str = Str_new(35,len);
534 if (datumtype == 'A') {
535 aptr = s; /* borrow register */
536 s = str->str_ptr + len - 1;
537 while (s >= str->str_ptr && (!*s || isspace(*s)))
540 str->str_cur = s - str->str_ptr;
541 s = aptr; /* unborrow register */
543 (void)astore(stack, ++sp, str_2static(str));
547 if (s + sizeof(char) > strend)
550 bcopy(s,(char*)&achar,sizeof(char));
555 if (aint >= 128) /* fake up signed chars */
557 str_numset(str,(double)aint);
558 (void)astore(stack, ++sp, str_2static(str));
563 if (s + sizeof(unsigned char) > strend)
566 bcopy(s,(char*)&auchar,sizeof(unsigned char));
567 s += sizeof(unsigned char);
570 auint = auchar; /* some can't cast uchar to double */
571 str_numset(str,(double)auint);
572 (void)astore(stack, ++sp, str_2static(str));
577 if (s + sizeof(short) > strend)
580 bcopy(s,(char*)&ashort,sizeof(short));
584 str_numset(str,(double)ashort);
585 (void)astore(stack, ++sp, str_2static(str));
591 if (s + sizeof(unsigned short) > strend)
594 bcopy(s,(char*)&aushort,sizeof(unsigned short));
595 s += sizeof(unsigned short);
599 if (datumtype == 'n')
600 aushort = ntohs(aushort);
602 str_numset(str,(double)aushort);
603 (void)astore(stack, ++sp, str_2static(str));
608 if (s + sizeof(int) > strend)
611 bcopy(s,(char*)&aint,sizeof(int));
615 str_numset(str,(double)aint);
616 (void)astore(stack, ++sp, str_2static(str));
621 if (s + sizeof(unsigned int) > strend)
624 bcopy(s,(char*)&auint,sizeof(unsigned int));
625 s += sizeof(unsigned int);
628 str_numset(str,(double)auint);
629 (void)astore(stack, ++sp, str_2static(str));
634 if (s + sizeof(long) > strend)
637 bcopy(s,(char*)&along,sizeof(long));
641 str_numset(str,(double)along);
642 (void)astore(stack, ++sp, str_2static(str));
648 if (s + sizeof(unsigned long) > strend)
651 bcopy(s,(char*)&aulong,sizeof(unsigned long));
652 s += sizeof(unsigned long);
656 if (datumtype == 'N')
657 aulong = ntohl(aulong);
659 str_numset(str,(double)aulong);
660 (void)astore(stack, ++sp, str_2static(str));
665 if (s + sizeof(char*) > strend)
668 bcopy(s,(char*)&aptr,sizeof(char*));
674 (void)astore(stack, ++sp, str_2static(str));
683 do_slice(stab,str,numarray,lval,gimme,arglast)
691 register STR **st = stack->ary_array;
692 register int sp = arglast[1];
693 register int max = arglast[2];
696 register int magic = 0;
699 int oldarybase = arybase;
702 if (numarray == 2) { /* a slice of a LIST */
704 ary->ary_fill = arglast[3];
706 st[sp] = str; /* make stack size available */
707 str_numset(str,(double)(sp - 1));
710 ary = stab_array(stab); /* a slice of an array */
716 else if (stab == sigstab)
719 else if (stab_hash(stab)->tbl_dbm)
721 #endif /* SOME_DBM */
723 hash = stab_hash(stab); /* a slice of an associative array */
726 if (gimme == G_ARRAY) {
730 st[sp-1] = afetch(ary,
731 ((int)str_gnum(st[sp])) - arybase, lval);
734 st[sp-1] = &str_undef;
740 tmps = str_get(st[sp]);
741 len = st[sp]->str_cur;
742 st[sp-1] = hfetch(hash,tmps,len, lval);
744 str_magic(st[sp-1],stab,magic,tmps,len);
747 st[sp-1] = &str_undef;
756 ((int)str_gnum(st[max])) - arybase, lval);
762 tmps = str_get(st[max]);
763 len = st[max]->str_cur;
764 st[sp] = hfetch(hash,tmps,len, lval);
766 str_magic(st[sp],stab,magic,tmps,len);
772 arybase = oldarybase;
777 do_splice(ary,str,gimme,arglast)
783 register STR **st = stack->ary_array;
784 register int sp = arglast[1];
785 int max = arglast[2] + 1;
797 offset = ((int)str_gnum(st[sp])) - arybase;
799 offset += ary->ary_fill + 1;
801 length = (int)str_gnum(st[sp++]);
806 length = ary->ary_max; /* close enough to infinity */
810 length = ary->ary_max;
818 if (offset > ary->ary_fill + 1)
819 offset = ary->ary_fill + 1;
820 after = ary->ary_fill + 1 - (offset + length);
821 if (after < 0) { /* not that much array */
822 length += after; /* offset+length now in array */
826 /* At this point, sp .. max-1 is our new LIST */
829 diff = newlen - length;
831 if (diff < 0) { /* shrinking the area */
833 New(451, tmparyval, newlen, STR*); /* so remember insertion */
834 Copy(st+sp, tmparyval, newlen, STR*);
838 if (gimme == G_ARRAY) { /* copy return vals to stack */
839 if (sp + length >= stack->ary_max) {
840 astore(stack,sp + length, Nullstr);
841 st = stack->ary_array;
843 Copy(ary->ary_array+offset, st+sp, length, STR*);
844 if (ary->ary_flags & ARF_REAL) {
845 for (i = length, dst = st+sp; i; i--)
846 str_2static(*dst++); /* free them eventualy */
851 st[sp] = ary->ary_array[offset+length-1];
852 if (ary->ary_flags & ARF_REAL)
855 ary->ary_fill += diff;
857 /* pull up or down? */
859 if (offset < after) { /* easier to pull up */
860 if (offset) { /* esp. if nothing to pull */
861 src = &ary->ary_array[offset-1];
862 dst = src - diff; /* diff is negative */
863 for (i = offset; i > 0; i--) /* can't trust Copy */
866 Zero(ary->ary_array, -diff, STR*);
867 ary->ary_array -= diff; /* diff is negative */
868 ary->ary_max += diff;
871 if (after) { /* anything to pull down? */
872 src = ary->ary_array + offset + length;
873 dst = src + diff; /* diff is negative */
874 Copy(src, dst, after, STR*);
876 Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
877 /* avoid later double free */
880 for (src = tmparyval, dst = ary->ary_array + offset;
882 *dst = Str_new(46,0);
883 str_sset(*dst++,*src++);
888 else { /* no, expanding (or same) */
890 New(452, tmparyval, length, STR*); /* so remember deletion */
891 Copy(ary->ary_array+offset, tmparyval, length, STR*);
894 if (diff > 0) { /* expanding */
896 /* push up or down? */
898 if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
900 src = ary->ary_array;
902 Copy(src, dst, offset, STR*);
904 ary->ary_array -= diff; /* diff is positive */
905 ary->ary_max += diff;
906 ary->ary_fill += diff;
909 if (ary->ary_fill + diff >= ary->ary_max) /* oh, well */
910 astore(ary, ary->ary_fill + diff, Nullstr);
912 ary->ary_fill += diff;
914 dst = ary->ary_array + ary->ary_fill;
916 for (i = after; i; i--) {
917 if (*dst) /* str was hanging around */
918 str_free(*dst); /* after $#foo */
926 for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
927 *dst = Str_new(46,0);
928 str_sset(*dst++,*src++);
931 if (gimme == G_ARRAY) { /* copy return vals to stack */
933 Copy(tmparyval, st+sp, length, STR*);
934 if (ary->ary_flags & ARF_REAL) {
935 for (i = length, dst = st+sp; i; i--)
936 str_2static(*dst++); /* free them eventualy */
943 st[sp] = tmparyval[length-1];
944 if (ary->ary_flags & ARF_REAL)
955 do_grep(arg,str,gimme,arglast)
961 STR **st = stack->ary_array;
962 register int dst = arglast[1];
963 register int src = dst + 1;
964 register int sp = arglast[2];
965 register int i = sp - arglast[1];
966 int oldsave = savestack->ary_fill;
967 SPAT *oldspat = curspat;
969 savesptr(&stab_val(defstab));
970 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
971 arg[1].arg_type &= A_MASK;
973 arg[1].arg_type |= A_DONT;
975 arg = arg[1].arg_ptr.arg_arg;
978 stab_val(defstab) = st[src];
980 stab_val(defstab) = str_static(&str_undef);
981 (void)eval(arg,G_SCALAR,sp);
982 st = stack->ary_array;
983 if (str_true(st[sp+1]))
988 restorelist(oldsave);
989 if (gimme != G_ARRAY) {
990 str_numset(str,(double)(dst - arglast[1]));
992 st[arglast[0]+1] = str;
995 return arglast[0] + (dst - arglast[1]);
999 do_reverse(str,gimme,arglast)
1004 STR **st = stack->ary_array;
1005 register STR **up = &st[arglast[1]];
1006 register STR **down = &st[arglast[2]];
1007 register int i = arglast[2] - arglast[1];
1009 if (gimme != G_ARRAY) {
1010 str_sset(str,&str_undef);
1012 st[arglast[0]+1] = str;
1013 return arglast[0]+1;
1020 i = arglast[2] - arglast[1];
1021 Copy(down+1,up,i/2,STR*);
1022 return arglast[2] - 1;
1025 static CMD *sortcmd;
1026 static STAB *firststab = Nullstab;
1027 static STAB *secondstab = Nullstab;
1030 do_sort(str,stab,gimme,arglast)
1036 STR **st = stack->ary_array;
1037 int sp = arglast[1];
1039 register int max = arglast[2] - sp;
1046 static ARRAY *sortstack = Null(ARRAY*);
1048 if (gimme != G_ARRAY) {
1049 str_sset(str,&str_undef);
1055 for (i = 0; i < max; i++) {
1056 if ((*up = up[1]) && !(*up)->str_pok)
1057 (void)str_2ptr(*up);
1062 if (stab_sub(stab) && (sortcmd = stab_sub(stab)->cmd)) {
1063 int oldtmps_base = tmps_base;
1066 sortstack = anew(Nullstab);
1067 sortstack->ary_flags = 0;
1071 tmps_base = tmps_max;
1073 firststab = stabent("a",TRUE);
1074 secondstab = stabent("b",TRUE);
1076 oldfirst = stab_val(firststab);
1077 oldsecond = stab_val(secondstab);
1079 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
1081 qsort(Nullch,max,sizeof(STR*),sortsub);
1083 stab_val(firststab) = oldfirst;
1084 stab_val(secondstab) = oldsecond;
1085 tmps_base = oldtmps_base;
1090 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
1093 up = &st[arglast[1]];
1094 while (max > 0 && !*up)
1108 stab_val(firststab) = *str1;
1109 stab_val(secondstab) = *str2;
1110 cmd_exec(sortcmd,G_SCALAR,-1);
1111 return (int)str_gnum(*stack->ary_array);
1114 sortcmp(strp1,strp2)
1118 register STR *str1 = *strp1;
1119 register STR *str2 = *strp2;
1127 if (str1->str_cur < str2->str_cur) {
1128 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
1133 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
1135 else if (str1->str_cur == str2->str_cur)
1142 do_range(gimme,arglast)
1146 STR **st = stack->ary_array;
1147 register int sp = arglast[0];
1149 register ARRAY *ary = stack;
1153 if (gimme != G_ARRAY)
1154 fatal("panic: do_range");
1156 if (st[sp+1]->str_nok ||
1157 (looks_like_number(st[sp+1]) && *st[sp+1]->str_ptr != '0') ) {
1158 i = (int)str_gnum(st[sp+1]);
1159 max = (int)str_gnum(st[sp+2]);
1161 (void)astore(ary, ++sp, str = str_static(&str_no));
1162 str_numset(str,(double)i++);
1166 STR *final = str_static(st[sp+2]);
1167 char *tmps = str_get(final);
1169 str = str_static(st[sp+1]);
1170 while (!str->str_nok && str->str_cur <= final->str_cur &&
1171 strNE(str->str_ptr,tmps) ) {
1172 (void)astore(ary, ++sp, str);
1173 str = str_static(str);
1176 if (strEQ(str->str_ptr,tmps))
1177 (void)astore(ary, ++sp, str);
1183 do_tms(str,gimme,arglast)
1188 STR **st = stack->ary_array;
1189 register int sp = arglast[0];
1191 if (gimme != G_ARRAY) {
1192 str_sset(str,&str_undef);
1197 (void)times(×buf);
1204 (void)astore(stack,++sp,
1205 str_2static(str_nmake(((double)timesbuf.tms_utime)/HZ)));
1206 (void)astore(stack,++sp,
1207 str_2static(str_nmake(((double)timesbuf.tms_stime)/HZ)));
1208 (void)astore(stack,++sp,
1209 str_2static(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
1210 (void)astore(stack,++sp,
1211 str_2static(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
1213 (void)astore(stack,++sp,
1214 str_2static(str_nmake(0.0)));
1220 do_time(str,tmbuf,gimme,arglast)
1226 register ARRAY *ary = stack;
1227 STR **st = ary->ary_array;
1228 register int sp = arglast[0];
1230 if (!tmbuf || gimme != G_ARRAY) {
1231 str_sset(str,&str_undef);
1236 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_sec)));
1237 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_min)));
1238 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_hour)));
1239 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mday)));
1240 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mon)));
1241 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_year)));
1242 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_wday)));
1243 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_yday)));
1244 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_isdst)));
1249 do_kv(str,hash,kv,gimme,arglast)
1256 register ARRAY *ary = stack;
1257 STR **st = ary->ary_array;
1258 register int sp = arglast[0];
1260 register HENT *entry;
1263 int dokeys = (kv == O_KEYS || kv == O_HASH);
1264 int dovalues = (kv == O_VALUES || kv == O_HASH);
1266 if (gimme != G_ARRAY) {
1267 str_sset(str,&str_undef);
1272 (void)hiterinit(hash);
1273 while (entry = hiternext(hash)) {
1275 tmps = hiterkey(entry,&i);
1276 (void)astore(ary,++sp,str_2static(str_make(tmps,i)));
1279 tmpstr = Str_new(45,0);
1282 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1283 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1284 str_set(tmpstr,buf);
1288 str_sset(tmpstr,hiterval(hash,entry));
1289 (void)astore(ary,++sp,str_2static(tmpstr));
1296 do_each(str,hash,gimme,arglast)
1302 STR **st = stack->ary_array;
1303 register int sp = arglast[0];
1304 static STR *mystrk = Nullstr;
1305 HENT *entry = hiternext(hash);
1315 if (gimme == G_ARRAY) {
1316 tmps = hiterkey(entry, &i);
1317 st[++sp] = mystrk = str_make(tmps,i);
1320 str_sset(str,hiterval(hash,entry));