1 /* $Header: dolist.c,v 3.0.1.5 90/02/28 17:09:44 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.5 90/02/28 17:09:44 lwall
10 * patch9: split now can split into more than 10000 elements
11 * patch9: @_ clobbered by ($foo,$bar) = split
12 * patch9: sped up pack and unpack
13 * patch9: unpack of single item now works in a scalar context
14 * patch9: slices ignored value of $[
15 * patch9: grep now returns number of items matched in scalar context
16 * patch9: grep iterations no longer in the regexp context of previous iteration
18 * Revision 3.0.1.4 89/12/21 19:58:46 lwall
19 * patch7: grep(1,@array) didn't work
20 * patch7: /$pat/; //; wrongly freed runtime pattern twice
22 * Revision 3.0.1.3 89/11/17 15:14:45 lwall
23 * patch5: grep() occasionally loses arguments or dumps core
25 * Revision 3.0.1.2 89/11/11 04:28:17 lwall
26 * patch2: non-existent slice values are now undefined rather than null
28 * Revision 3.0.1.1 89/10/26 23:11:51 lwall
29 * patch1: split in a subroutine wrongly freed referenced arguments
30 * patch1: reverse didn't work
32 * Revision 3.0 89/10/18 15:11:02 lwall
42 do_match(str,arg,gimme,arglast)
48 register STR **st = stack->ary_array;
49 register SPAT *spat = arg[2].arg_ptr.arg_spat;
51 register int sp = arglast[0] + 1;
52 STR *srchstr = st[sp];
53 register char *s = str_get(st[sp]);
54 char *strend = s + st[sp]->str_cur;
66 fatal("panic: do_match");
67 if (spat->spat_flags & SPAT_USED) {
80 if (spat->spat_runtime) {
82 sp = eval(spat->spat_runtime,G_SCALAR,sp);
83 st = stack->ary_array;
84 t = str_get(tmpstr = st[sp--]);
88 deb("2.SPAT /%s/\n",t);
90 if (spat->spat_regexp)
91 regfree(spat->spat_regexp);
92 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
93 spat->spat_flags & SPAT_FOLD,1);
94 if (!*spat->spat_regexp->precomp && lastspat)
96 if (spat->spat_flags & SPAT_KEEP) {
97 if (spat->spat_runtime)
98 arg_free(spat->spat_runtime); /* it won't change, so */
99 spat->spat_runtime = Nullarg; /* no point compiling again */
101 if (!spat->spat_regexp->nparens)
102 gimme = G_SCALAR; /* accidental array context? */
103 if (regexec(spat->spat_regexp, s, strend, s, 0,
104 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
106 if (spat->spat_regexp->subbase)
112 if (gimme == G_ARRAY)
114 str_sset(str,&str_no);
125 if (spat->spat_flags & SPAT_ONCE)
129 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
132 if (!*spat->spat_regexp->precomp && lastspat)
136 if (hint < s || hint > strend)
137 fatal("panic: hint in do_match");
140 if (spat->spat_regexp->regback >= 0) {
141 s -= spat->spat_regexp->regback;
148 else if (spat->spat_short) {
149 if (spat->spat_flags & SPAT_SCANFIRST) {
150 if (srchstr->str_pok & SP_STUDIED) {
151 if (screamfirst[spat->spat_short->str_rare] < 0)
153 else if (!(s = screaminstr(srchstr,spat->spat_short)))
155 else if (spat->spat_flags & SPAT_ALL)
159 else if (!(s = fbminstr((unsigned char*)s,
160 (unsigned char*)strend, spat->spat_short)))
163 else if (spat->spat_flags & SPAT_ALL)
165 if (s && spat->spat_regexp->regback >= 0) {
166 ++spat->spat_short->str_u.str_useful;
167 s -= spat->spat_regexp->regback;
174 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
175 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
177 if (--spat->spat_short->str_u.str_useful < 0) {
178 str_free(spat->spat_short);
179 spat->spat_short = Nullstr; /* opt is being useless */
182 if (!spat->spat_regexp->nparens)
183 gimme = G_SCALAR; /* accidental array context? */
184 if (regexec(spat->spat_regexp, s, strend, t, 0,
185 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
187 if (spat->spat_regexp->subbase)
190 if (spat->spat_flags & SPAT_ONCE)
191 spat->spat_flags |= SPAT_USED;
195 if (gimme == G_ARRAY)
197 str_sset(str,&str_no);
206 if (gimme == G_ARRAY) {
209 iters = spat->spat_regexp->nparens;
210 if (sp + iters >= stack->ary_max) {
211 astore(stack,sp + iters, Nullstr);
212 st = stack->ary_array; /* possibly realloced */
215 for (i = 1; i <= iters; i++) {
216 st[++sp] = str_static(&str_no);
217 if (s = spat->spat_regexp->startp[i]) {
218 len = spat->spat_regexp->endp[i] - s;
220 str_nset(st[sp],s,len);
226 str_sset(str,&str_yes);
233 ++spat->spat_short->str_u.str_useful;
235 if (spat->spat_flags & SPAT_ONCE)
236 spat->spat_flags |= SPAT_USED;
240 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
241 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
242 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
245 str_sset(str,&str_yes);
251 ++spat->spat_short->str_u.str_useful;
252 if (gimme == G_ARRAY)
254 str_sset(str,&str_no);
261 do_split(str,spat,limit,gimme,arglast)
268 register ARRAY *ary = stack;
269 STR **st = ary->ary_array;
270 register int sp = arglast[0] + 1;
271 register char *s = str_get(st[sp]);
272 char *strend = s + st[sp--]->str_cur;
276 int maxiters = (strend - s) + 10;
279 int origlimit = limit;
283 fatal("panic: do_split");
284 else if (spat->spat_runtime) {
286 sp = eval(spat->spat_runtime,G_SCALAR,sp);
287 st = stack->ary_array;
288 m = str_get(dstr = st[sp--]);
290 if (!dstr->str_cur || (*m == ' ' && dstr->str_cur == 1)) {
291 str_set(dstr,"\\s+");
293 spat->spat_flags |= SPAT_SKIPWHITE;
295 if (spat->spat_regexp)
296 regfree(spat->spat_regexp);
297 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
298 spat->spat_flags & SPAT_FOLD,1);
299 if (spat->spat_flags & SPAT_KEEP ||
300 (spat->spat_runtime->arg_type == O_ITEM &&
301 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
302 arg_free(spat->spat_runtime); /* it won't change, so */
303 spat->spat_runtime = Nullarg; /* no point compiling again */
308 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
311 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
312 if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {
314 if (!(ary->ary_flags & ARF_REAL)) {
315 ary->ary_flags |= ARF_REAL;
316 for (i = ary->ary_fill; i >= 0; i--)
317 ary->ary_array[i] = Nullstr; /* don't free mere refs */
320 sp = -1; /* temporarily switch stacks */
325 if (spat->spat_flags & SPAT_SKIPWHITE) {
330 limit = maxiters + 2;
331 if (spat->spat_short) {
332 i = spat->spat_short->str_cur;
334 i = *spat->spat_short->str_ptr;
336 for (m = s; m < strend && *m != i; m++) ;
340 dstr = Str_new(30,m-s);
342 dstr = str_static(&str_undef);
343 str_nset(dstr,s,m-s);
344 (void)astore(ary, ++sp, dstr);
350 while (s < strend && --limit &&
351 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
356 dstr = Str_new(31,m-s);
358 dstr = str_static(&str_undef);
359 str_nset(dstr,s,m-s);
360 (void)astore(ary, ++sp, dstr);
366 maxiters += (strend - s) * spat->spat_regexp->nparens;
367 while (s < strend && --limit &&
368 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
369 if (spat->spat_regexp->subbase
370 && spat->spat_regexp->subbase != orig) {
373 orig = spat->spat_regexp->subbase;
375 strend = s + (strend - m);
377 m = spat->spat_regexp->startp[0];
379 dstr = Str_new(32,m-s);
381 dstr = str_static(&str_undef);
382 str_nset(dstr,s,m-s);
383 (void)astore(ary, ++sp, dstr);
384 if (spat->spat_regexp->nparens) {
385 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
386 s = spat->spat_regexp->startp[i];
387 m = spat->spat_regexp->endp[i];
389 dstr = Str_new(33,m-s);
391 dstr = str_static(&str_undef);
392 str_nset(dstr,s,m-s);
393 (void)astore(ary, ++sp, dstr);
396 s = spat->spat_regexp->endp[0];
402 iters = sp - arglast[0];
403 if (iters > maxiters)
405 if (s < strend || origlimit) { /* keep field after final delim? */
407 dstr = Str_new(34,strend-s);
409 dstr = str_static(&str_undef);
410 str_nset(dstr,s,strend-s);
411 (void)astore(ary, ++sp, dstr);
416 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
423 zaps = str_get(afetch(ary,sp,FALSE));
427 while (iters > 0 && (!zapb)) {
430 zaps = str_get(afetch(ary,iters-1,FALSE));
438 if (gimme == G_ARRAY) {
440 astore(stack, arglast[0] + 1 + sp, Nullstr);
441 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
442 return arglast[0] + sp;
446 if (gimme == G_ARRAY)
450 str_numset(str,(double)iters);
457 do_unpack(str,gimme,arglast)
462 STR **st = stack->ary_array;
463 register int sp = arglast[0] + 1;
464 register char *pat = str_get(st[sp++]);
465 register char *s = str_get(st[sp]);
466 char *strend = s + st[sp--]->str_cur;
467 register char *patend = pat + st[sp]->str_cur;
471 /* These must not be in registers: */
476 unsigned char auchar;
477 unsigned short aushort;
479 unsigned long aulong;
482 if (gimme != G_ARRAY) { /* arrange to do first one only */
484 if (*pat == 'a' || *pat == 'A') {
485 while (isdigit(*patend))
490 while (pat < patend) {
494 while (isdigit(*pat))
495 len = (len * 10) + (*pat++ - '0');
507 if (s + len > strend)
509 str = Str_new(35,len);
512 if (datumtype == 'A') {
513 aptr = s; /* borrow register */
514 s = str->str_ptr + len - 1;
515 while (s >= str->str_ptr && (!*s || isspace(*s)))
518 str->str_cur = s - str->str_ptr;
519 s = aptr; /* unborrow register */
521 (void)astore(stack, ++sp, str_2static(str));
525 if (s + sizeof(char) > strend)
528 bcopy(s,(char*)&achar,sizeof(char));
533 if (aint >= 128) /* fake up signed chars */
535 str_numset(str,(double)aint);
536 (void)astore(stack, ++sp, str_2static(str));
541 if (s + sizeof(unsigned char) > strend)
544 bcopy(s,(char*)&auchar,sizeof(unsigned char));
545 s += sizeof(unsigned char);
548 auint = auchar; /* some can't cast uchar to double */
549 str_numset(str,(double)auint);
550 (void)astore(stack, ++sp, str_2static(str));
555 if (s + sizeof(short) > strend)
558 bcopy(s,(char*)&ashort,sizeof(short));
562 str_numset(str,(double)ashort);
563 (void)astore(stack, ++sp, str_2static(str));
569 if (s + sizeof(unsigned short) > strend)
572 bcopy(s,(char*)&aushort,sizeof(unsigned short));
573 s += sizeof(unsigned short);
577 if (datumtype == 'n')
578 aushort = ntohs(aushort);
580 str_numset(str,(double)aushort);
581 (void)astore(stack, ++sp, str_2static(str));
586 if (s + sizeof(int) > strend)
589 bcopy(s,(char*)&aint,sizeof(int));
593 str_numset(str,(double)aint);
594 (void)astore(stack, ++sp, str_2static(str));
599 if (s + sizeof(unsigned int) > strend)
602 bcopy(s,(char*)&auint,sizeof(unsigned int));
603 s += sizeof(unsigned int);
606 str_numset(str,(double)auint);
607 (void)astore(stack, ++sp, str_2static(str));
612 if (s + sizeof(long) > strend)
615 bcopy(s,(char*)&along,sizeof(long));
619 str_numset(str,(double)along);
620 (void)astore(stack, ++sp, str_2static(str));
626 if (s + sizeof(unsigned long) > strend)
629 bcopy(s,(char*)&aulong,sizeof(unsigned long));
630 s += sizeof(unsigned long);
634 if (datumtype == 'N')
635 aulong = ntohl(aulong);
637 str_numset(str,(double)aulong);
638 (void)astore(stack, ++sp, str_2static(str));
643 if (s + sizeof(char*) > strend)
646 bcopy(s,(char*)&aptr,sizeof(char*));
652 (void)astore(stack, ++sp, str_2static(str));
661 do_slice(stab,numarray,lval,gimme,arglast)
668 register STR **st = stack->ary_array;
669 register int sp = arglast[1];
670 register int max = arglast[2];
673 register int magic = 0;
675 if (lval && !numarray) {
678 else if (stab == sigstab)
681 else if (stab_hash(stab)->tbl_dbm)
683 #endif /* SOME_DBM */
686 if (gimme == G_ARRAY) {
690 st[sp-1] = afetch(stab_array(stab),
691 ((int)str_gnum(st[sp])) - arybase, lval);
694 st[sp-1] = &str_undef;
700 tmps = str_get(st[sp]);
701 len = st[sp]->str_cur;
702 st[sp-1] = hfetch(stab_hash(stab),tmps,len, lval);
704 str_magic(st[sp-1],stab,magic,tmps,len);
707 st[sp-1] = &str_undef;
715 st[sp] = afetch(stab_array(stab),
716 ((int)str_gnum(st[max])) - arybase, lval);
722 tmps = str_get(st[max]);
723 len = st[max]->str_cur;
724 st[sp] = hfetch(stab_hash(stab),tmps,len, lval);
726 str_magic(st[sp],stab,magic,tmps,len);
736 do_grep(arg,str,gimme,arglast)
742 STR **st = stack->ary_array;
743 register int dst = arglast[1];
744 register int src = dst + 1;
745 register int sp = arglast[2];
746 register int i = sp - arglast[1];
747 int oldsave = savestack->ary_fill;
748 SPAT *oldspat = curspat;
750 savesptr(&stab_val(defstab));
751 if ((arg[1].arg_type & A_MASK) != A_EXPR) {
752 arg[1].arg_type &= A_MASK;
754 arg[1].arg_type |= A_DONT;
756 arg = arg[1].arg_ptr.arg_arg;
758 stab_val(defstab) = st[src];
759 (void)eval(arg,G_SCALAR,sp);
760 st = stack->ary_array;
761 if (str_true(st[sp+1]))
766 restorelist(oldsave);
767 if (gimme != G_ARRAY) {
768 str_numset(str,(double)(dst - arglast[1]));
770 st[arglast[0]+1] = str;
773 return arglast[0] + (dst - arglast[1]);
777 do_reverse(str,gimme,arglast)
782 STR **st = stack->ary_array;
783 register STR **up = &st[arglast[1]];
784 register STR **down = &st[arglast[2]];
785 register int i = arglast[2] - arglast[1];
787 if (gimme != G_ARRAY) {
788 str_sset(str,&str_undef);
790 st[arglast[0]+1] = str;
798 i = arglast[2] - arglast[1];
799 Copy(down+1,up,i/2,STR*);
800 return arglast[2] - 1;
804 static STAB *firststab = Nullstab;
805 static STAB *secondstab = Nullstab;
808 do_sort(str,stab,gimme,arglast)
814 STR **st = stack->ary_array;
817 register int max = arglast[2] - sp;
824 static ARRAY *sortstack = Null(ARRAY*);
826 if (gimme != G_ARRAY) {
827 str_sset(str,&str_undef);
833 for (i = 0; i < max; i++) {
834 if ((*up = up[1]) && !(*up)->str_pok)
840 if (stab_sub(stab) && (sortcmd = stab_sub(stab)->cmd)) {
841 int oldtmps_base = tmps_base;
844 sortstack = anew(Nullstab);
845 sortstack->ary_flags = 0;
849 tmps_base = tmps_max;
851 firststab = stabent("a",TRUE);
852 secondstab = stabent("b",TRUE);
854 oldfirst = stab_val(firststab);
855 oldsecond = stab_val(secondstab);
857 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
859 qsort(Nullch,max,sizeof(STR*),sortsub);
861 stab_val(firststab) = oldfirst;
862 stab_val(secondstab) = oldsecond;
863 tmps_base = oldtmps_base;
868 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
871 up = &st[arglast[1]];
872 while (max > 0 && !*up)
886 stab_val(firststab) = *str1;
887 stab_val(secondstab) = *str2;
888 cmd_exec(sortcmd,G_SCALAR,-1);
889 return (int)str_gnum(*stack->ary_array);
896 register STR *str1 = *strp1;
897 register STR *str2 = *strp2;
905 if (str1->str_cur < str2->str_cur) {
906 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
911 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
913 else if (str1->str_cur == str2->str_cur)
920 do_range(gimme,arglast)
924 STR **st = stack->ary_array;
925 register int sp = arglast[0];
926 register int i = (int)str_gnum(st[sp+1]);
927 register ARRAY *ary = stack;
929 int max = (int)str_gnum(st[sp+2]);
931 if (gimme != G_ARRAY)
932 fatal("panic: do_range");
935 (void)astore(ary, ++sp, str = str_static(&str_no));
936 str_numset(str,(double)i++);
942 do_tms(str,gimme,arglast)
947 STR **st = stack->ary_array;
948 register int sp = arglast[0];
950 if (gimme != G_ARRAY) {
951 str_sset(str,&str_undef);
956 (void)times(×buf);
963 (void)astore(stack,++sp,
964 str_2static(str_nmake(((double)timesbuf.tms_utime)/HZ)));
965 (void)astore(stack,++sp,
966 str_2static(str_nmake(((double)timesbuf.tms_stime)/HZ)));
967 (void)astore(stack,++sp,
968 str_2static(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
969 (void)astore(stack,++sp,
970 str_2static(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
972 (void)astore(stack,++sp,
973 str_2static(str_nmake(0.0)));
979 do_time(str,tmbuf,gimme,arglast)
985 register ARRAY *ary = stack;
986 STR **st = ary->ary_array;
987 register int sp = arglast[0];
989 if (!tmbuf || gimme != G_ARRAY) {
990 str_sset(str,&str_undef);
995 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_sec)));
996 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_min)));
997 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_hour)));
998 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mday)));
999 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mon)));
1000 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_year)));
1001 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_wday)));
1002 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_yday)));
1003 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_isdst)));
1008 do_kv(str,hash,kv,gimme,arglast)
1015 register ARRAY *ary = stack;
1016 STR **st = ary->ary_array;
1017 register int sp = arglast[0];
1019 register HENT *entry;
1022 int dokeys = (kv == O_KEYS || kv == O_HASH);
1023 int dovalues = (kv == O_VALUES || kv == O_HASH);
1025 if (gimme != G_ARRAY) {
1026 str_sset(str,&str_undef);
1031 (void)hiterinit(hash);
1032 while (entry = hiternext(hash)) {
1034 tmps = hiterkey(entry,&i);
1035 (void)astore(ary,++sp,str_2static(str_make(tmps,i)));
1038 tmpstr = Str_new(45,0);
1041 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1042 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1043 str_set(tmpstr,buf);
1047 str_sset(tmpstr,hiterval(hash,entry));
1048 (void)astore(ary,++sp,str_2static(tmpstr));
1055 do_each(str,hash,gimme,arglast)
1061 STR **st = stack->ary_array;
1062 register int sp = arglast[0];
1063 static STR *mystrk = Nullstr;
1064 HENT *entry = hiternext(hash);
1074 if (gimme == G_ARRAY) {
1075 tmps = hiterkey(entry, &i);
1076 st[++sp] = mystrk = str_make(tmps,i);
1079 str_sset(str,hiterval(hash,entry));