1 /* $Header: dolist.c,v 3.0.1.3 89/11/17 15:14:45 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.3 89/11/17 15:14:45 lwall
10 * patch5: grep() occasionally loses arguments or dumps core
12 * Revision 3.0.1.2 89/11/11 04:28:17 lwall
13 * patch2: non-existent slice values are now undefined rather than null
15 * Revision 3.0.1.1 89/10/26 23:11:51 lwall
16 * patch1: split in a subroutine wrongly freed referenced arguments
17 * patch1: reverse didn't work
19 * Revision 3.0 89/10/18 15:11:02 lwall
29 do_match(str,arg,gimme,arglast)
35 register STR **st = stack->ary_array;
36 register SPAT *spat = arg[2].arg_ptr.arg_spat;
38 register int sp = arglast[0] + 1;
39 STR *srchstr = st[sp];
40 register char *s = str_get(st[sp]);
41 char *strend = s + st[sp]->str_cur;
53 fatal("panic: do_match");
54 if (spat->spat_flags & SPAT_USED) {
67 if (spat->spat_runtime) {
69 sp = eval(spat->spat_runtime,G_SCALAR,sp);
70 st = stack->ary_array;
71 t = str_get(tmpstr = st[sp--]);
75 deb("2.SPAT /%s/\n",t);
77 if (spat->spat_regexp)
78 regfree(spat->spat_regexp);
79 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
80 spat->spat_flags & SPAT_FOLD,1);
81 if (!*spat->spat_regexp->precomp && lastspat)
83 if (spat->spat_flags & SPAT_KEEP) {
84 arg_free(spat->spat_runtime); /* it won't change, so */
85 spat->spat_runtime = Nullarg; /* no point compiling again */
87 if (!spat->spat_regexp->nparens)
88 gimme = G_SCALAR; /* accidental array context? */
89 if (regexec(spat->spat_regexp, s, strend, s, 0,
90 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
92 if (spat->spat_regexp->subbase)
100 str_sset(str,&str_no);
111 if (spat->spat_flags & SPAT_ONCE)
115 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
118 if (!*spat->spat_regexp->precomp && lastspat)
122 if (hint < s || hint > strend)
123 fatal("panic: hint in do_match");
126 if (spat->spat_regexp->regback >= 0) {
127 s -= spat->spat_regexp->regback;
134 else if (spat->spat_short) {
135 if (spat->spat_flags & SPAT_SCANFIRST) {
136 if (srchstr->str_pok & SP_STUDIED) {
137 if (screamfirst[spat->spat_short->str_rare] < 0)
139 else if (!(s = screaminstr(srchstr,spat->spat_short)))
141 else if (spat->spat_flags & SPAT_ALL)
145 else if (!(s = fbminstr((unsigned char*)s,
146 (unsigned char*)strend, spat->spat_short)))
149 else if (spat->spat_flags & SPAT_ALL)
151 if (s && spat->spat_regexp->regback >= 0) {
152 ++spat->spat_short->str_u.str_useful;
153 s -= spat->spat_regexp->regback;
160 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
161 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
163 if (--spat->spat_short->str_u.str_useful < 0) {
164 str_free(spat->spat_short);
165 spat->spat_short = Nullstr; /* opt is being useless */
168 if (!spat->spat_regexp->nparens)
169 gimme = G_SCALAR; /* accidental array context? */
170 if (regexec(spat->spat_regexp, s, strend, t, 0,
171 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
173 if (spat->spat_regexp->subbase)
176 if (spat->spat_flags & SPAT_ONCE)
177 spat->spat_flags |= SPAT_USED;
181 if (gimme == G_ARRAY)
183 str_sset(str,&str_no);
192 if (gimme == G_ARRAY) {
195 iters = spat->spat_regexp->nparens;
196 if (sp + iters >= stack->ary_max) {
197 astore(stack,sp + iters, Nullstr);
198 st = stack->ary_array; /* possibly realloced */
201 for (i = 1; i <= iters; i++) {
202 st[++sp] = str_static(&str_no);
203 if (s = spat->spat_regexp->startp[i]) {
204 len = spat->spat_regexp->endp[i] - s;
206 str_nset(st[sp],s,len);
212 str_sset(str,&str_yes);
219 ++spat->spat_short->str_u.str_useful;
221 if (spat->spat_flags & SPAT_ONCE)
222 spat->spat_flags |= SPAT_USED;
226 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
227 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
228 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
231 str_sset(str,&str_yes);
237 ++spat->spat_short->str_u.str_useful;
238 if (gimme == G_ARRAY)
240 str_sset(str,&str_no);
247 do_split(str,spat,limit,gimme,arglast)
254 register ARRAY *ary = stack;
255 STR **st = ary->ary_array;
256 register int sp = arglast[0] + 1;
257 register char *s = str_get(st[sp]);
258 char *strend = s + st[sp--]->str_cur;
264 int origlimit = limit;
268 fatal("panic: do_split");
269 else if (spat->spat_runtime) {
271 sp = eval(spat->spat_runtime,G_SCALAR,sp);
272 st = stack->ary_array;
273 m = str_get(dstr = st[sp--]);
275 if (!dstr->str_cur || (*m == ' ' && dstr->str_cur == 1)) {
276 str_set(dstr,"\\s+");
278 spat->spat_flags |= SPAT_SKIPWHITE;
280 if (spat->spat_regexp)
281 regfree(spat->spat_regexp);
282 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
283 spat->spat_flags & SPAT_FOLD,1);
284 if (spat->spat_flags & SPAT_KEEP ||
285 (spat->spat_runtime->arg_type == O_ITEM &&
286 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
287 arg_free(spat->spat_runtime); /* it won't change, so */
288 spat->spat_runtime = Nullarg; /* no point compiling again */
293 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
296 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
297 if (ary && ((ary->ary_flags & ARF_REAL) || gimme != G_ARRAY)) {
299 if (!(ary->ary_flags & ARF_REAL)) {
300 ary->ary_flags |= ARF_REAL;
301 for (i = ary->ary_fill; i >= 0; i--)
302 ary->ary_array[i] = Nullstr; /* don't free mere refs */
305 sp = -1; /* temporarily switch stacks */
310 if (spat->spat_flags & SPAT_SKIPWHITE) {
316 if (spat->spat_short) {
317 i = spat->spat_short->str_cur;
319 i = *spat->spat_short->str_ptr;
321 for (m = s; m < strend && *m != i; m++) ;
325 dstr = Str_new(30,m-s);
327 dstr = str_static(&str_undef);
328 str_nset(dstr,s,m-s);
329 (void)astore(ary, ++sp, dstr);
335 while (s < strend && --limit &&
336 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
341 dstr = Str_new(31,m-s);
343 dstr = str_static(&str_undef);
344 str_nset(dstr,s,m-s);
345 (void)astore(ary, ++sp, dstr);
351 while (s < strend && --limit &&
352 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
353 if (spat->spat_regexp->subbase
354 && spat->spat_regexp->subbase != orig) {
357 orig = spat->spat_regexp->subbase;
359 strend = s + (strend - m);
361 m = spat->spat_regexp->startp[0];
363 dstr = Str_new(32,m-s);
365 dstr = str_static(&str_undef);
366 str_nset(dstr,s,m-s);
367 (void)astore(ary, ++sp, dstr);
368 if (spat->spat_regexp->nparens) {
369 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
370 s = spat->spat_regexp->startp[i];
371 m = spat->spat_regexp->endp[i];
373 dstr = Str_new(33,m-s);
375 dstr = str_static(&str_undef);
376 str_nset(dstr,s,m-s);
377 (void)astore(ary, ++sp, dstr);
380 s = spat->spat_regexp->endp[0];
386 iters = sp - arglast[0];
389 if (s < strend || origlimit) { /* keep field after final delim? */
391 dstr = Str_new(34,strend-s);
393 dstr = str_static(&str_undef);
394 str_nset(dstr,s,strend-s);
395 (void)astore(ary, ++sp, dstr);
400 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
407 zaps = str_get(afetch(ary,sp,FALSE));
411 while (iters > 0 && (!zapb)) {
414 zaps = str_get(afetch(ary,iters-1,FALSE));
422 if (gimme == G_ARRAY) {
424 astore(stack, arglast[0] + 1 + sp, Nullstr);
425 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
426 return arglast[0] + sp;
430 if (gimme == G_ARRAY)
434 str_numset(str,(double)iters);
441 do_unpack(str,gimme,arglast)
446 STR **st = stack->ary_array;
447 register int sp = arglast[0] + 1;
448 register char *pat = str_get(st[sp++]);
449 register char *s = str_get(st[sp]);
450 char *strend = s + st[sp--]->str_cur;
451 register char *patend = pat + st[sp]->str_cur;
455 /* These must not be in registers: */
460 unsigned char auchar;
461 unsigned short aushort;
463 unsigned long aulong;
466 if (gimme != G_ARRAY) {
467 str_sset(str,&str_undef);
473 while (pat < patend) {
477 while (isdigit(*pat))
490 if (s + len > strend)
492 str = Str_new(35,len);
495 if (datumtype == 'A') {
496 aptr = s; /* borrow register */
497 s = str->str_ptr + len - 1;
498 while (s >= str->str_ptr && (!*s || isspace(*s)))
501 str->str_cur = s - str->str_ptr;
502 s = aptr; /* unborrow register */
504 (void)astore(stack, ++sp, str_2static(str));
508 if (s + sizeof(char) > strend)
511 bcopy(s,(char*)&achar,sizeof(char));
516 if (aint >= 128) /* fake up signed chars */
518 str_numset(str,(double)aint);
519 (void)astore(stack, ++sp, str_2static(str));
524 if (s + sizeof(unsigned char) > strend)
527 bcopy(s,(char*)&auchar,sizeof(unsigned char));
528 s += sizeof(unsigned char);
531 auint = auchar; /* some can't cast uchar to double */
532 str_numset(str,(double)auint);
533 (void)astore(stack, ++sp, str_2static(str));
538 if (s + sizeof(short) > strend)
541 bcopy(s,(char*)&ashort,sizeof(short));
545 str_numset(str,(double)ashort);
546 (void)astore(stack, ++sp, str_2static(str));
552 if (s + sizeof(unsigned short) > strend)
555 bcopy(s,(char*)&aushort,sizeof(unsigned short));
556 s += sizeof(unsigned short);
560 if (datumtype == 'n')
561 aushort = ntohs(aushort);
563 str_numset(str,(double)aushort);
564 (void)astore(stack, ++sp, str_2static(str));
569 if (s + sizeof(int) > strend)
572 bcopy(s,(char*)&aint,sizeof(int));
576 str_numset(str,(double)aint);
577 (void)astore(stack, ++sp, str_2static(str));
582 if (s + sizeof(unsigned int) > strend)
585 bcopy(s,(char*)&auint,sizeof(unsigned int));
586 s += sizeof(unsigned int);
589 str_numset(str,(double)auint);
590 (void)astore(stack, ++sp, str_2static(str));
595 if (s + sizeof(long) > strend)
598 bcopy(s,(char*)&along,sizeof(long));
602 str_numset(str,(double)along);
603 (void)astore(stack, ++sp, str_2static(str));
609 if (s + sizeof(unsigned long) > strend)
612 bcopy(s,(char*)&aulong,sizeof(unsigned long));
613 s += sizeof(unsigned long);
617 if (datumtype == 'N')
618 aulong = ntohl(aulong);
620 str_numset(str,(double)aulong);
621 (void)astore(stack, ++sp, str_2static(str));
626 if (s + sizeof(char*) > strend)
629 bcopy(s,(char*)&aptr,sizeof(char*));
635 (void)astore(stack, ++sp, str_2static(str));
644 do_slice(stab,numarray,lval,gimme,arglast)
651 register STR **st = stack->ary_array;
652 register int sp = arglast[1];
653 register int max = arglast[2];
656 register int magic = 0;
658 if (lval && !numarray) {
661 else if (stab == sigstab)
664 else if (stab_hash(stab)->tbl_dbm)
666 #endif /* SOME_DBM */
669 if (gimme == G_ARRAY) {
673 st[sp-1] = afetch(stab_array(stab),(int)str_gnum(st[sp]),
677 st[sp-1] = &str_undef;
683 tmps = str_get(st[sp]);
684 len = st[sp]->str_cur;
685 st[sp-1] = hfetch(stab_hash(stab),tmps,len, lval);
687 str_magic(st[sp-1],stab,magic,tmps,len);
690 st[sp-1] = &str_undef;
698 st[sp] = afetch(stab_array(stab),(int)str_gnum(st[max]), lval);
704 tmps = str_get(st[max]);
705 len = st[max]->str_cur;
706 st[sp] = hfetch(stab_hash(stab),tmps,len, lval);
708 str_magic(st[sp],stab,magic,tmps,len);
718 do_grep(arg,str,gimme,arglast)
724 STR **st = stack->ary_array;
725 register int dst = arglast[1];
726 register int src = dst + 1;
727 register int sp = arglast[2];
728 register int i = sp - arglast[1];
729 int oldsave = savestack->ary_fill;
731 savesptr(&stab_val(defstab));
732 if ((arg[1].arg_type & A_MASK) != A_EXPR)
734 arg = arg[1].arg_ptr.arg_arg;
736 stab_val(defstab) = st[src];
737 (void)eval(arg,G_SCALAR,sp);
738 st = stack->ary_array;
739 if (str_true(st[sp+1]))
743 restorelist(oldsave);
744 if (gimme != G_ARRAY) {
745 str_sset(str,&str_undef);
747 st[arglast[0]+1] = str;
750 return arglast[0] + (dst - arglast[1]);
754 do_reverse(str,gimme,arglast)
759 STR **st = stack->ary_array;
760 register STR **up = &st[arglast[1]];
761 register STR **down = &st[arglast[2]];
762 register int i = arglast[2] - arglast[1];
764 if (gimme != G_ARRAY) {
765 str_sset(str,&str_undef);
767 st[arglast[0]+1] = str;
775 i = arglast[2] - arglast[1];
776 Copy(down+1,up,i/2,STR*);
777 return arglast[2] - 1;
781 static STAB *firststab = Nullstab;
782 static STAB *secondstab = Nullstab;
785 do_sort(str,stab,gimme,arglast)
791 STR **st = stack->ary_array;
794 register int max = arglast[2] - sp;
801 static ARRAY *sortstack = Null(ARRAY*);
803 if (gimme != G_ARRAY) {
804 str_sset(str,&str_undef);
810 for (i = 0; i < max; i++) {
811 if ((*up = up[1]) && !(*up)->str_pok)
817 if (stab_sub(stab) && (sortcmd = stab_sub(stab)->cmd)) {
818 int oldtmps_base = tmps_base;
821 sortstack = anew(Nullstab);
822 sortstack->ary_flags = 0;
826 tmps_base = tmps_max;
828 firststab = stabent("a",TRUE);
829 secondstab = stabent("b",TRUE);
831 oldfirst = stab_val(firststab);
832 oldsecond = stab_val(secondstab);
834 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
836 qsort(Nullch,max,sizeof(STR*),sortsub);
838 stab_val(firststab) = oldfirst;
839 stab_val(secondstab) = oldsecond;
840 tmps_base = oldtmps_base;
845 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
848 up = &st[arglast[1]];
849 while (max > 0 && !*up)
863 stab_val(firststab) = *str1;
864 stab_val(secondstab) = *str2;
865 cmd_exec(sortcmd,G_SCALAR,-1);
866 return (int)str_gnum(*stack->ary_array);
873 register STR *str1 = *strp1;
874 register STR *str2 = *strp2;
882 if (str1->str_cur < str2->str_cur) {
883 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
888 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
890 else if (str1->str_cur == str2->str_cur)
897 do_range(gimme,arglast)
901 STR **st = stack->ary_array;
902 register int sp = arglast[0];
903 register int i = (int)str_gnum(st[sp+1]);
904 register ARRAY *ary = stack;
906 int max = (int)str_gnum(st[sp+2]);
908 if (gimme != G_ARRAY)
909 fatal("panic: do_range");
912 (void)astore(ary, ++sp, str = str_static(&str_no));
913 str_numset(str,(double)i++);
919 do_tms(str,gimme,arglast)
924 STR **st = stack->ary_array;
925 register int sp = arglast[0];
927 if (gimme != G_ARRAY) {
928 str_sset(str,&str_undef);
933 (void)times(×buf);
940 (void)astore(stack,++sp,
941 str_2static(str_nmake(((double)timesbuf.tms_utime)/HZ)));
942 (void)astore(stack,++sp,
943 str_2static(str_nmake(((double)timesbuf.tms_stime)/HZ)));
944 (void)astore(stack,++sp,
945 str_2static(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
946 (void)astore(stack,++sp,
947 str_2static(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
949 (void)astore(stack,++sp,
950 str_2static(str_nmake(0.0)));
956 do_time(str,tmbuf,gimme,arglast)
962 register ARRAY *ary = stack;
963 STR **st = ary->ary_array;
964 register int sp = arglast[0];
966 if (!tmbuf || gimme != G_ARRAY) {
967 str_sset(str,&str_undef);
972 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_sec)));
973 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_min)));
974 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_hour)));
975 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mday)));
976 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mon)));
977 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_year)));
978 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_wday)));
979 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_yday)));
980 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_isdst)));
985 do_kv(str,hash,kv,gimme,arglast)
992 register ARRAY *ary = stack;
993 STR **st = ary->ary_array;
994 register int sp = arglast[0];
996 register HENT *entry;
999 int dokeys = (kv == O_KEYS || kv == O_HASH);
1000 int dovalues = (kv == O_VALUES || kv == O_HASH);
1002 if (gimme != G_ARRAY) {
1003 str_sset(str,&str_undef);
1008 (void)hiterinit(hash);
1009 while (entry = hiternext(hash)) {
1011 tmps = hiterkey(entry,&i);
1012 (void)astore(ary,++sp,str_2static(str_make(tmps,i)));
1015 tmpstr = Str_new(45,0);
1018 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1019 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1020 str_set(tmpstr,buf);
1024 str_sset(tmpstr,hiterval(hash,entry));
1025 (void)astore(ary,++sp,str_2static(tmpstr));
1032 do_each(str,hash,gimme,arglast)
1038 STR **st = stack->ary_array;
1039 register int sp = arglast[0];
1040 static STR *mystrk = Nullstr;
1041 HENT *entry = hiternext(hash);
1051 if (gimme == G_ARRAY) {
1052 tmps = hiterkey(entry, &i);
1053 st[++sp] = mystrk = str_make(tmps,i);
1056 str_sset(str,hiterval(hash,entry));