1 /* $Header: dolist.c,v 3.0.1.2 89/11/11 04:28:17 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.2 89/11/11 04:28:17 lwall
10 * patch2: non-existent slice values are now undefined rather than null
12 * Revision 3.0.1.1 89/10/26 23:11:51 lwall
13 * patch1: split in a subroutine wrongly freed referenced arguments
14 * patch1: reverse didn't work
16 * Revision 3.0 89/10/18 15:11:02 lwall
26 do_match(str,arg,gimme,arglast)
32 register STR **st = stack->ary_array;
33 register SPAT *spat = arg[2].arg_ptr.arg_spat;
35 register int sp = arglast[0] + 1;
36 STR *srchstr = st[sp];
37 register char *s = str_get(st[sp]);
38 char *strend = s + st[sp]->str_cur;
50 fatal("panic: do_match");
51 if (spat->spat_flags & SPAT_USED) {
64 if (spat->spat_runtime) {
66 sp = eval(spat->spat_runtime,G_SCALAR,sp);
67 st = stack->ary_array;
68 t = str_get(tmpstr = st[sp--]);
72 deb("2.SPAT /%s/\n",t);
74 if (spat->spat_regexp)
75 regfree(spat->spat_regexp);
76 spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
77 spat->spat_flags & SPAT_FOLD,1);
78 if (!*spat->spat_regexp->precomp && lastspat)
80 if (spat->spat_flags & SPAT_KEEP) {
81 arg_free(spat->spat_runtime); /* it won't change, so */
82 spat->spat_runtime = Nullarg; /* no point compiling again */
84 if (!spat->spat_regexp->nparens)
85 gimme = G_SCALAR; /* accidental array context? */
86 if (regexec(spat->spat_regexp, s, strend, s, 0,
87 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
89 if (spat->spat_regexp->subbase)
97 str_sset(str,&str_no);
108 if (spat->spat_flags & SPAT_ONCE)
112 deb("2.SPAT %c%s%c\n",ch,spat->spat_regexp->precomp,ch);
115 if (!*spat->spat_regexp->precomp && lastspat)
119 if (hint < s || hint > strend)
120 fatal("panic: hint in do_match");
123 if (spat->spat_regexp->regback >= 0) {
124 s -= spat->spat_regexp->regback;
131 else if (spat->spat_short) {
132 if (spat->spat_flags & SPAT_SCANFIRST) {
133 if (srchstr->str_pok & SP_STUDIED) {
134 if (screamfirst[spat->spat_short->str_rare] < 0)
136 else if (!(s = screaminstr(srchstr,spat->spat_short)))
138 else if (spat->spat_flags & SPAT_ALL)
142 else if (!(s = fbminstr((unsigned char*)s,
143 (unsigned char*)strend, spat->spat_short)))
146 else if (spat->spat_flags & SPAT_ALL)
148 if (s && spat->spat_regexp->regback >= 0) {
149 ++spat->spat_short->str_u.str_useful;
150 s -= spat->spat_regexp->regback;
157 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
158 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
160 if (--spat->spat_short->str_u.str_useful < 0) {
161 str_free(spat->spat_short);
162 spat->spat_short = Nullstr; /* opt is being useless */
165 if (!spat->spat_regexp->nparens)
166 gimme = G_SCALAR; /* accidental array context? */
167 if (regexec(spat->spat_regexp, s, strend, t, 0,
168 srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
170 if (spat->spat_regexp->subbase)
173 if (spat->spat_flags & SPAT_ONCE)
174 spat->spat_flags |= SPAT_USED;
178 if (gimme == G_ARRAY)
180 str_sset(str,&str_no);
189 if (gimme == G_ARRAY) {
192 iters = spat->spat_regexp->nparens;
193 if (sp + iters >= stack->ary_max) {
194 astore(stack,sp + iters, Nullstr);
195 st = stack->ary_array; /* possibly realloced */
198 for (i = 1; i <= iters; i++) {
199 st[++sp] = str_static(&str_no);
200 if (s = spat->spat_regexp->startp[i]) {
201 len = spat->spat_regexp->endp[i] - s;
203 str_nset(st[sp],s,len);
209 str_sset(str,&str_yes);
216 ++spat->spat_short->str_u.str_useful;
218 if (spat->spat_flags & SPAT_ONCE)
219 spat->spat_flags |= SPAT_USED;
223 tmps = spat->spat_regexp->subbase = nsavestr(t,strend-t);
224 tmps = spat->spat_regexp->startp[0] = tmps + (s - t);
225 spat->spat_regexp->endp[0] = tmps + spat->spat_short->str_cur;
228 str_sset(str,&str_yes);
234 ++spat->spat_short->str_u.str_useful;
235 if (gimme == G_ARRAY)
237 str_sset(str,&str_no);
244 do_split(str,spat,limit,gimme,arglast)
251 register ARRAY *ary = stack;
252 STR **st = ary->ary_array;
253 register int sp = arglast[0] + 1;
254 register char *s = str_get(st[sp]);
255 char *strend = s + st[sp--]->str_cur;
261 int origlimit = limit;
265 fatal("panic: do_split");
266 else if (spat->spat_runtime) {
268 sp = eval(spat->spat_runtime,G_SCALAR,sp);
269 st = stack->ary_array;
270 m = str_get(dstr = st[sp--]);
272 if (!dstr->str_cur || (*m == ' ' && dstr->str_cur == 1)) {
273 str_set(dstr,"\\s+");
275 spat->spat_flags |= SPAT_SKIPWHITE;
277 if (spat->spat_regexp)
278 regfree(spat->spat_regexp);
279 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
280 spat->spat_flags & SPAT_FOLD,1);
281 if (spat->spat_flags & SPAT_KEEP ||
282 (spat->spat_runtime->arg_type == O_ITEM &&
283 (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {
284 arg_free(spat->spat_runtime); /* it won't change, so */
285 spat->spat_runtime = Nullarg; /* no point compiling again */
290 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
293 ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);
294 if (ary && ((ary->ary_flags & ARF_REAL) || gimme != G_ARRAY)) {
296 if (!(ary->ary_flags & ARF_REAL)) {
297 ary->ary_flags |= ARF_REAL;
298 for (i = ary->ary_fill; i >= 0; i--)
299 ary->ary_array[i] = Nullstr; /* don't free mere refs */
302 sp = -1; /* temporarily switch stacks */
307 if (spat->spat_flags & SPAT_SKIPWHITE) {
313 if (spat->spat_short) {
314 i = spat->spat_short->str_cur;
316 i = *spat->spat_short->str_ptr;
318 for (m = s; m < strend && *m != i; m++) ;
322 dstr = Str_new(30,m-s);
324 dstr = str_static(&str_undef);
325 str_nset(dstr,s,m-s);
326 (void)astore(ary, ++sp, dstr);
332 while (s < strend && --limit &&
333 (m=fbminstr((unsigned char*)s, (unsigned char*)strend,
338 dstr = Str_new(31,m-s);
340 dstr = str_static(&str_undef);
341 str_nset(dstr,s,m-s);
342 (void)astore(ary, ++sp, dstr);
348 while (s < strend && --limit &&
349 regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {
350 if (spat->spat_regexp->subbase
351 && spat->spat_regexp->subbase != orig) {
354 orig = spat->spat_regexp->subbase;
356 strend = s + (strend - m);
358 m = spat->spat_regexp->startp[0];
360 dstr = Str_new(32,m-s);
362 dstr = str_static(&str_undef);
363 str_nset(dstr,s,m-s);
364 (void)astore(ary, ++sp, dstr);
365 if (spat->spat_regexp->nparens) {
366 for (i = 1; i <= spat->spat_regexp->nparens; i++) {
367 s = spat->spat_regexp->startp[i];
368 m = spat->spat_regexp->endp[i];
370 dstr = Str_new(33,m-s);
372 dstr = str_static(&str_undef);
373 str_nset(dstr,s,m-s);
374 (void)astore(ary, ++sp, dstr);
377 s = spat->spat_regexp->endp[0];
383 iters = sp - arglast[0];
386 if (s < strend || origlimit) { /* keep field after final delim? */
388 dstr = Str_new(34,strend-s);
390 dstr = str_static(&str_undef);
391 str_nset(dstr,s,strend-s);
392 (void)astore(ary, ++sp, dstr);
397 while (iters > 0 && ary->ary_array[sp]->str_cur == 0)
404 zaps = str_get(afetch(ary,sp,FALSE));
408 while (iters > 0 && (!zapb)) {
411 zaps = str_get(afetch(ary,iters-1,FALSE));
419 if (gimme == G_ARRAY) {
421 astore(stack, arglast[0] + 1 + sp, Nullstr);
422 Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);
423 return arglast[0] + sp;
427 if (gimme == G_ARRAY)
431 str_numset(str,(double)iters);
438 do_unpack(str,gimme,arglast)
443 STR **st = stack->ary_array;
444 register int sp = arglast[0] + 1;
445 register char *pat = str_get(st[sp++]);
446 register char *s = str_get(st[sp]);
447 char *strend = s + st[sp--]->str_cur;
448 register char *patend = pat + st[sp]->str_cur;
452 /* These must not be in registers: */
457 unsigned char auchar;
458 unsigned short aushort;
460 unsigned long aulong;
463 if (gimme != G_ARRAY) {
464 str_sset(str,&str_undef);
470 while (pat < patend) {
474 while (isdigit(*pat))
487 if (s + len > strend)
489 str = Str_new(35,len);
492 if (datumtype == 'A') {
493 aptr = s; /* borrow register */
494 s = str->str_ptr + len - 1;
495 while (s >= str->str_ptr && (!*s || isspace(*s)))
498 str->str_cur = s - str->str_ptr;
499 s = aptr; /* unborrow register */
501 (void)astore(stack, ++sp, str_2static(str));
505 if (s + sizeof(char) > strend)
508 bcopy(s,(char*)&achar,sizeof(char));
513 if (aint >= 128) /* fake up signed chars */
515 str_numset(str,(double)aint);
516 (void)astore(stack, ++sp, str_2static(str));
521 if (s + sizeof(unsigned char) > strend)
524 bcopy(s,(char*)&auchar,sizeof(unsigned char));
525 s += sizeof(unsigned char);
528 auint = auchar; /* some can't cast uchar to double */
529 str_numset(str,(double)auint);
530 (void)astore(stack, ++sp, str_2static(str));
535 if (s + sizeof(short) > strend)
538 bcopy(s,(char*)&ashort,sizeof(short));
542 str_numset(str,(double)ashort);
543 (void)astore(stack, ++sp, str_2static(str));
549 if (s + sizeof(unsigned short) > strend)
552 bcopy(s,(char*)&aushort,sizeof(unsigned short));
553 s += sizeof(unsigned short);
557 if (datumtype == 'n')
558 aushort = ntohs(aushort);
560 str_numset(str,(double)aushort);
561 (void)astore(stack, ++sp, str_2static(str));
566 if (s + sizeof(int) > strend)
569 bcopy(s,(char*)&aint,sizeof(int));
573 str_numset(str,(double)aint);
574 (void)astore(stack, ++sp, str_2static(str));
579 if (s + sizeof(unsigned int) > strend)
582 bcopy(s,(char*)&auint,sizeof(unsigned int));
583 s += sizeof(unsigned int);
586 str_numset(str,(double)auint);
587 (void)astore(stack, ++sp, str_2static(str));
592 if (s + sizeof(long) > strend)
595 bcopy(s,(char*)&along,sizeof(long));
599 str_numset(str,(double)along);
600 (void)astore(stack, ++sp, str_2static(str));
606 if (s + sizeof(unsigned long) > strend)
609 bcopy(s,(char*)&aulong,sizeof(unsigned long));
610 s += sizeof(unsigned long);
614 if (datumtype == 'N')
615 aulong = ntohl(aulong);
617 str_numset(str,(double)aulong);
618 (void)astore(stack, ++sp, str_2static(str));
623 if (s + sizeof(char*) > strend)
626 bcopy(s,(char*)&aptr,sizeof(char*));
632 (void)astore(stack, ++sp, str_2static(str));
641 do_slice(stab,numarray,lval,gimme,arglast)
648 register STR **st = stack->ary_array;
649 register int sp = arglast[1];
650 register int max = arglast[2];
653 register int magic = 0;
655 if (lval && !numarray) {
658 else if (stab == sigstab)
661 else if (stab_hash(stab)->tbl_dbm)
663 #endif /* SOME_DBM */
666 if (gimme == G_ARRAY) {
670 st[sp-1] = afetch(stab_array(stab),(int)str_gnum(st[sp]),
674 st[sp-1] = &str_undef;
680 tmps = str_get(st[sp]);
681 len = st[sp]->str_cur;
682 st[sp-1] = hfetch(stab_hash(stab),tmps,len, lval);
684 str_magic(st[sp-1],stab,magic,tmps,len);
687 st[sp-1] = &str_undef;
695 st[sp] = afetch(stab_array(stab),(int)str_gnum(st[max]), lval);
701 tmps = str_get(st[max]);
702 len = st[max]->str_cur;
703 st[sp] = hfetch(stab_hash(stab),tmps,len, lval);
705 str_magic(st[sp],stab,magic,tmps,len);
715 do_grep(arg,str,gimme,arglast)
721 STR **st = stack->ary_array;
722 register STR **dst = &st[arglast[1]];
723 register STR **src = dst + 1;
724 register int sp = arglast[2];
725 register int i = sp - arglast[1];
726 int oldsave = savestack->ary_fill;
728 savesptr(&stab_val(defstab));
729 if ((arg[1].arg_type & A_MASK) != A_EXPR)
731 arg = arg[1].arg_ptr.arg_arg;
733 stab_val(defstab) = *src;
734 (void)eval(arg,G_SCALAR,sp);
735 if (str_true(st[sp+1]))
739 restorelist(oldsave);
740 if (gimme != G_ARRAY) {
741 str_sset(str,&str_undef);
743 st[arglast[0]+1] = str;
746 return arglast[0] + (dst - &st[arglast[1]]);
750 do_reverse(str,gimme,arglast)
755 STR **st = stack->ary_array;
756 register STR **up = &st[arglast[1]];
757 register STR **down = &st[arglast[2]];
758 register int i = arglast[2] - arglast[1];
760 if (gimme != G_ARRAY) {
761 str_sset(str,&str_undef);
763 st[arglast[0]+1] = str;
771 i = arglast[2] - arglast[1];
772 Copy(down+1,up,i/2,STR*);
773 return arglast[2] - 1;
777 static STAB *firststab = Nullstab;
778 static STAB *secondstab = Nullstab;
781 do_sort(str,stab,gimme,arglast)
787 STR **st = stack->ary_array;
790 register int max = arglast[2] - sp;
797 static ARRAY *sortstack = Null(ARRAY*);
799 if (gimme != G_ARRAY) {
800 str_sset(str,&str_undef);
806 for (i = 0; i < max; i++) {
807 if ((*up = up[1]) && !(*up)->str_pok)
813 if (stab_sub(stab) && (sortcmd = stab_sub(stab)->cmd)) {
814 int oldtmps_base = tmps_base;
817 sortstack = anew(Nullstab);
818 sortstack->ary_flags = 0;
822 tmps_base = tmps_max;
824 firststab = stabent("a",TRUE);
825 secondstab = stabent("b",TRUE);
827 oldfirst = stab_val(firststab);
828 oldsecond = stab_val(secondstab);
830 qsort((char*)(st+sp+1),max,sizeof(STR*),sortsub);
832 qsort(Nullch,max,sizeof(STR*),sortsub);
834 stab_val(firststab) = oldfirst;
835 stab_val(secondstab) = oldsecond;
836 tmps_base = oldtmps_base;
841 qsort((char*)(st+sp+1),max,sizeof(STR*),sortcmp);
844 up = &st[arglast[1]];
845 while (max > 0 && !*up)
859 stab_val(firststab) = *str1;
860 stab_val(secondstab) = *str2;
861 cmd_exec(sortcmd,G_SCALAR,-1);
862 return (int)str_gnum(*stack->ary_array);
869 register STR *str1 = *strp1;
870 register STR *str2 = *strp2;
878 if (str1->str_cur < str2->str_cur) {
879 if (retval = memcmp(str1->str_ptr, str2->str_ptr, str1->str_cur))
884 else if (retval = memcmp(str1->str_ptr, str2->str_ptr, str2->str_cur))
886 else if (str1->str_cur == str2->str_cur)
893 do_range(gimme,arglast)
897 STR **st = stack->ary_array;
898 register int sp = arglast[0];
899 register int i = (int)str_gnum(st[sp+1]);
900 register ARRAY *ary = stack;
902 int max = (int)str_gnum(st[sp+2]);
904 if (gimme != G_ARRAY)
905 fatal("panic: do_range");
908 (void)astore(ary, ++sp, str = str_static(&str_no));
909 str_numset(str,(double)i++);
915 do_tms(str,gimme,arglast)
920 STR **st = stack->ary_array;
921 register int sp = arglast[0];
923 if (gimme != G_ARRAY) {
924 str_sset(str,&str_undef);
929 (void)times(×buf);
936 (void)astore(stack,++sp,
937 str_2static(str_nmake(((double)timesbuf.tms_utime)/HZ)));
938 (void)astore(stack,++sp,
939 str_2static(str_nmake(((double)timesbuf.tms_stime)/HZ)));
940 (void)astore(stack,++sp,
941 str_2static(str_nmake(((double)timesbuf.tms_cutime)/HZ)));
942 (void)astore(stack,++sp,
943 str_2static(str_nmake(((double)timesbuf.tms_cstime)/HZ)));
945 (void)astore(stack,++sp,
946 str_2static(str_nmake(0.0)));
952 do_time(str,tmbuf,gimme,arglast)
958 register ARRAY *ary = stack;
959 STR **st = ary->ary_array;
960 register int sp = arglast[0];
962 if (!tmbuf || gimme != G_ARRAY) {
963 str_sset(str,&str_undef);
968 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_sec)));
969 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_min)));
970 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_hour)));
971 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mday)));
972 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_mon)));
973 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_year)));
974 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_wday)));
975 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_yday)));
976 (void)astore(ary,++sp,str_2static(str_nmake((double)tmbuf->tm_isdst)));
981 do_kv(str,hash,kv,gimme,arglast)
988 register ARRAY *ary = stack;
989 STR **st = ary->ary_array;
990 register int sp = arglast[0];
992 register HENT *entry;
995 int dokeys = (kv == O_KEYS || kv == O_HASH);
996 int dovalues = (kv == O_VALUES || kv == O_HASH);
998 if (gimme != G_ARRAY) {
999 str_sset(str,&str_undef);
1004 (void)hiterinit(hash);
1005 while (entry = hiternext(hash)) {
1007 tmps = hiterkey(entry,&i);
1008 (void)astore(ary,++sp,str_2static(str_make(tmps,i)));
1011 tmpstr = Str_new(45,0);
1014 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
1015 hash->tbl_max+1,entry->hent_hash & hash->tbl_max);
1016 str_set(tmpstr,buf);
1020 str_sset(tmpstr,hiterval(hash,entry));
1021 (void)astore(ary,++sp,str_2static(tmpstr));
1028 do_each(str,hash,gimme,arglast)
1034 STR **st = stack->ary_array;
1035 register int sp = arglast[0];
1036 static STR *mystrk = Nullstr;
1037 HENT *entry = hiternext(hash);
1047 if (gimme == G_ARRAY) {
1048 tmps = hiterkey(entry, &i);
1049 st[++sp] = mystrk = str_make(tmps,i);
1052 str_sset(str,hiterval(hash,entry));