1 /* $Header: doarg.c,v 3.0.1.9 90/11/10 01:14:31 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.9 90/11/10 01:14:31 lwall
10 * patch38: random cleanup
11 * patch38: optimized join('',...)
12 * patch38: printf cleaned up
14 * Revision 3.0.1.8 90/10/15 16:04:04 lwall
15 * patch29: @ENV = () now works
16 * patch29: added caller
17 * patch29: tr/// now understands c, d and s options, and handles nulls right
18 * patch29: *foo now prints as *package'foo
19 * patch29: added caller
20 * patch29: local() without initialization now creates undefined values
22 * Revision 3.0.1.7 90/08/13 22:14:15 lwall
23 * patch28: the NSIG hack didn't work on Xenix
24 * patch28: defined(@array) and defined(%array) didn't work right
26 * Revision 3.0.1.6 90/08/09 02:48:38 lwall
27 * patch19: fixed double include of <signal.h>
28 * patch19: pack/unpack can now do native float and double
29 * patch19: pack/unpack can now have absolute and negative positioning
30 * patch19: pack/unpack can now have use * to specify all the rest of input
31 * patch19: unpack can do checksumming
32 * patch19: $< and $> better supported on machines without setreuid
33 * patch19: Added support for linked-in C subroutines
35 * Revision 3.0.1.5 90/03/27 15:39:03 lwall
36 * patch16: MSDOS support
37 * patch16: support for machines that can't cast negative floats to unsigned ints
38 * patch16: sprintf($s,...,$s,...) didn't work
40 * Revision 3.0.1.4 90/03/12 16:28:42 lwall
41 * patch13: pack of ascii strings could call str_ncat() with negative length
42 * patch13: printf("%s", *foo) was busted
44 * Revision 3.0.1.3 90/02/28 16:56:58 lwall
45 * patch9: split now can split into more than 10000 elements
46 * patch9: sped up pack and unpack
47 * patch9: pack of unsigned ints and longs blew up some places
48 * patch9: sun3 can't cast negative float to unsigned int or long
49 * patch9: local($.) didn't work
50 * patch9: grep(s/foo/bar/, @abc = @xyz) modified @xyz rather than @abc
51 * patch9: syscall returned stack size rather than value of system call
53 * Revision 3.0.1.2 89/12/21 19:52:15 lwall
54 * patch7: a pattern wouldn't match a null string before the first character
55 * patch7: certain patterns didn't match correctly at end of string
57 * Revision 3.0.1.1 89/11/11 04:17:20 lwall
58 * patch2: printf %c, %D, %X and %O didn't work right
59 * patch2: printf of unsigned vs signed needed separate casts on some machines
61 * Revision 3.0 89/10/18 15:10:41 lwall
69 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
73 extern unsigned char fold[];
75 extern char **environ;
78 #pragma function(memcmp)
79 #endif /* BUGGY_MSC */
90 register char *s = str_get(str);
91 char *strend = s + str->str_cur;
97 int maxiters = (strend - s) + 10;
103 rspat = spat = arg[2].arg_ptr.arg_spat;
105 fatal("panic: do_subst");
106 else if (spat->spat_runtime) {
108 (void)eval(spat->spat_runtime,G_SCALAR,sp);
109 m = str_get(dstr = stack->ary_array[sp+1]);
111 if (spat->spat_regexp)
112 regfree(spat->spat_regexp);
113 spat->spat_regexp = regcomp(m,m+dstr->str_cur,
114 spat->spat_flags & SPAT_FOLD);
115 if (spat->spat_flags & SPAT_KEEP) {
116 arg_free(spat->spat_runtime); /* it won't change, so */
117 spat->spat_runtime = Nullarg; /* no point compiling again */
122 deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);
125 safebase = ((!spat->spat_regexp || !spat->spat_regexp->nparens) &&
127 if (!*spat->spat_regexp->precomp && lastspat)
131 if (hint < s || hint > strend)
132 fatal("panic: hint in do_match");
135 if (spat->spat_regexp->regback >= 0) {
136 s -= spat->spat_regexp->regback;
143 else if (spat->spat_short) {
144 if (spat->spat_flags & SPAT_SCANFIRST) {
145 if (str->str_pok & SP_STUDIED) {
146 if (screamfirst[spat->spat_short->str_rare] < 0)
148 else if (!(s = screaminstr(str,spat->spat_short)))
152 else if (!(s = fbminstr((unsigned char*)s, (unsigned char*)strend,
156 if (s && spat->spat_regexp->regback >= 0) {
157 ++spat->spat_short->str_u.str_useful;
158 s -= spat->spat_regexp->regback;
165 else if (!multiline && (*spat->spat_short->str_ptr != *s ||
166 bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
168 if (--spat->spat_short->str_u.str_useful < 0) {
169 str_free(spat->spat_short);
170 spat->spat_short = Nullstr; /* opt is being useless */
173 once = ((rspat->spat_flags & SPAT_ONCE) != 0);
174 if (rspat->spat_flags & SPAT_CONST) { /* known replacement string? */
175 if ((rspat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)
176 dstr = rspat->spat_repl[1].arg_ptr.arg_str;
177 else { /* constant over loop, anyway */
178 (void)eval(rspat->spat_repl,G_SCALAR,sp);
179 dstr = stack->ary_array[sp+1];
182 clen = dstr->str_cur;
183 if (clen <= spat->spat_slen + spat->spat_regexp->regback) {
184 /* can do inplace substitution */
185 if (regexec(spat->spat_regexp, s, strend, orig, 0,
186 str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
187 if (spat->spat_regexp->subbase) /* oops, no we can't */
191 str->str_pok = SP_VALID; /* disable possible screamer */
193 m = spat->spat_regexp->startp[0];
194 d = spat->spat_regexp->endp[0];
196 if (m - s > strend - d) { /* faster to shorten from end */
198 (void)bcopy(c, m, clen);
203 (void)bcopy(d, m, i);
207 str->str_cur = m - s;
209 str_numset(arg->arg_ptr.arg_str, 1.0);
210 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
213 else if (i = m - s) { /* faster from front */
221 (void)bcopy(c, m, clen);
223 str_numset(arg->arg_ptr.arg_str, 1.0);
224 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
230 (void)bcopy(c,d,clen);
232 str_numset(arg->arg_ptr.arg_str, 1.0);
233 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
239 str_numset(arg->arg_ptr.arg_str, 1.0);
240 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
246 if (iters++ > maxiters)
247 fatal("Substitution loop");
248 m = spat->spat_regexp->startp[0];
255 (void)bcopy(c,d,clen);
258 s = spat->spat_regexp->endp[0];
259 } while (regexec(spat->spat_regexp, s, strend, orig, s == m,
260 Nullstr, TRUE)); /* (don't match same null twice) */
263 str->str_cur = d - str->str_ptr + i;
264 (void)bcopy(s,d,i+1); /* include the Null */
267 str_numset(arg->arg_ptr.arg_str, (double)iters);
268 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
271 str_numset(arg->arg_ptr.arg_str, 0.0);
272 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
278 if (regexec(spat->spat_regexp, s, strend, orig, 0,
279 str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {
281 dstr = Str_new(25,str_len(str));
282 str_nset(dstr,m,s-m);
283 if (spat->spat_regexp->subbase)
287 if (iters++ > maxiters)
288 fatal("Substitution loop");
289 if (spat->spat_regexp->subbase
290 && spat->spat_regexp->subbase != orig) {
293 orig = spat->spat_regexp->subbase;
295 strend = s + (strend - m);
297 m = spat->spat_regexp->startp[0];
298 str_ncat(dstr,s,m-s);
299 s = spat->spat_regexp->endp[0];
302 str_ncat(dstr,c,clen);
305 (void)eval(rspat->spat_repl,G_SCALAR,sp);
306 str_scat(dstr,stack->ary_array[sp+1]);
310 } while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr,
312 str_ncat(dstr,s,strend - s);
313 str_replace(str,dstr);
315 str_numset(arg->arg_ptr.arg_str, (double)iters);
316 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
319 str_numset(arg->arg_ptr.arg_str, 0.0);
320 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
324 ++spat->spat_short->str_u.str_useful;
325 str_numset(arg->arg_ptr.arg_str, 0.0);
326 stack->ary_array[++sp] = arg->arg_ptr.arg_str;
330 #pragma intrinsic(memcmp)
331 #endif /* BUGGY_MSC */
340 register int matches = 0;
344 register int squash = arg[2].arg_len & 1;
346 tbl = (short*) arg[2].arg_ptr.arg_cval;
348 send = s + str->str_cur;
350 fatal("panic: do_trans");
356 if (!arg[2].arg_len) {
358 if ((ch = tbl[*s & 0377]) >= 0) {
368 if ((ch = tbl[*s & 0377]) >= 0) {
370 if (matches++ && squash) {
379 else if (ch == -1) /* -1 is unmapped character */
380 *d++ = *s; /* -2 is delete character */
383 matches += send - d; /* account for disappeared chars */
385 str->str_cur = d - str->str_ptr;
396 register STR **st = stack->ary_array;
397 register int sp = arglast[1];
398 register int items = arglast[2] - sp;
399 register char *delim = str_get(st[sp]);
400 int delimlen = st[sp]->str_cur;
408 for (; items > 0; items--,st++) {
409 str_ncat(str,delim,delimlen);
414 for (; items > 0; items--,st++)
425 register STR **st = stack->ary_array;
426 register int sp = arglast[1];
428 register char *pat = str_get(st[sp]);
429 register char *patend = pat + st[sp]->str_cur;
433 static char *null10 = "\0\0\0\0\0\0\0\0\0\0";
434 static char *space10 = " ";
436 /* These must not be in registers: */
442 unsigned long aulong;
447 items = arglast[2] - sp;
450 while (pat < patend) {
451 #define NEXTFROM (items-- > 0 ? *st++ : &str_no)
454 len = index("@Xxu",datumtype) ? 0 : items;
457 else if (isdigit(*pat)) {
459 while (isdigit(*pat))
460 len = (len * 10) + (*pat++ - '0');
468 fatal("% may only be used in unpack");
479 if (str->str_cur < len)
480 fatal("X outside of string");
482 str->str_ptr[str->str_cur] = '\0';
487 str_ncat(str,null10,10);
490 str_ncat(str,null10,len);
495 aptr = str_get(fromstr);
497 len = fromstr->str_cur;
498 if (fromstr->str_cur > len)
499 str_ncat(str,aptr,len);
501 str_ncat(str,aptr,fromstr->str_cur);
502 len -= fromstr->str_cur;
503 if (datumtype == 'A') {
505 str_ncat(str,space10,10);
508 str_ncat(str,space10,len);
512 str_ncat(str,null10,10);
515 str_ncat(str,null10,len);
523 aint = (int)str_gnum(fromstr);
525 str_ncat(str,&achar,sizeof(char));
528 /* Float and double added by gnb@melba.bby.oz.au 22/11/89 */
533 afloat = (float)str_gnum(fromstr);
534 str_ncat(str, (char *)&afloat, sizeof (float));
541 adouble = (double)str_gnum(fromstr);
542 str_ncat(str, (char *)&adouble, sizeof (double));
548 ashort = (short)str_gnum(fromstr);
550 ashort = htons(ashort);
552 str_ncat(str,(char*)&ashort,sizeof(short));
559 ashort = (short)str_gnum(fromstr);
560 str_ncat(str,(char*)&ashort,sizeof(short));
566 auint = U_I(str_gnum(fromstr));
567 str_ncat(str,(char*)&auint,sizeof(unsigned int));
573 aint = (int)str_gnum(fromstr);
574 str_ncat(str,(char*)&aint,sizeof(int));
580 along = (long)str_gnum(fromstr);
582 along = htonl(along);
584 str_ncat(str,(char*)&along,sizeof(long));
590 aulong = U_L(str_gnum(fromstr));
591 str_ncat(str,(char*)&aulong,sizeof(unsigned long));
597 along = (long)str_gnum(fromstr);
598 str_ncat(str,(char*)&along,sizeof(long));
604 aptr = str_get(fromstr);
605 str_ncat(str,(char*)&aptr,sizeof(char*));
610 aptr = str_get(fromstr);
611 aint = fromstr->str_cur;
612 STR_GROW(str,aint * 4 / 3);
624 doencodes(str, aptr, todo);
635 doencodes(str, s, len)
643 str_ncat(str, hunk, 1);
646 hunk[0] = ' ' + (077 & (*s >> 2));
647 hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017));
648 hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03));
649 hunk[3] = ' ' + (077 & (s[2] & 077));
650 str_ncat(str, hunk, 4);
654 str_ncat(str, "\n", 1);
658 do_sprintf(str,len,sarg)
668 static STR *sargnull = &str_no;
676 len--; /* don't count pattern string */
677 origs = t = s = str_get(*sarg);
678 send = s + (*sarg)->str_cur;
681 if (len <= 0 || !*sarg) {
685 for ( ; t < send && *t != '%'; t++) ;
687 break; /* end of format string, ignore extra args */
692 for (t++; t < send; t++) {
700 case '0': case '1': case '2': case '3': case '4':
701 case '5': case '6': case '7': case '8': case '9':
702 case '.': case '#': case '-': case '+': case ' ':
710 xlen = (int)str_gnum(*(sarg++));
711 if (strEQ(f,"%c")) { /* some printfs fail on null chars */
716 (void)sprintf(xs,f,xlen);
725 (void)sprintf(xs,f,(long)str_gnum(*(sarg++)));
727 (void)sprintf(xs,f,(int)str_gnum(*(sarg++)));
732 case 'x': case 'o': case 'u':
735 value = str_gnum(*(sarg++));
737 (void)sprintf(xs,f,U_L(value));
739 (void)sprintf(xs,f,U_I(value));
741 case 'E': case 'e': case 'f': case 'G': case 'g':
744 (void)sprintf(xs,f,str_gnum(*(sarg++)));
750 xlen = (*sarg)->str_cur;
751 if (*xs == 'S' && xs[1] == 't' && xs[2] == 'B'
752 && xlen == sizeof(STBP) && strlen(xs) < xlen) {
753 STR *tmpstr = Str_new(24,0);
755 stab_fullname(tmpstr, ((STAB*)(*sarg))); /* a stab value! */
756 sprintf(tokenbuf,"*%s",tmpstr->str_ptr);
757 /* reformat to non-binary */
759 xlen = strlen(tokenbuf);
763 if (strEQ(f,"%s")) { /* some printfs fail on >128 chars */
764 break; /* so handle simple case */
766 strcpy(tokenbuf+64,f); /* sprintf($s,...$s...) */
768 (void)sprintf(buf,tokenbuf+64,xs);
772 /* end of switch, copy results */
775 STR_GROW(str, str->str_cur + (f - s) + len + 1);
776 str_ncat(str, s, f - s);
777 str_ncat(str, xs, xlen);
779 break; /* break from for loop */
782 str_ncat(str, s, t - s);
791 register STR **st = stack->ary_array;
792 register int sp = arglast[1];
793 register int items = arglast[2] - sp;
794 register STR *str = &str_undef;
796 for (st += ++sp; items > 0; items--,st++) {
800 (void)apush(ary,str);
806 do_unshift(ary,arglast)
810 register STR **st = stack->ary_array;
811 register int sp = arglast[1];
812 register int items = arglast[2] - sp;
818 for (st += ++sp; i < items; i++,st++) {
821 (void)astore(ary,i,str);
826 do_subr(arg,gimme,arglast)
831 register STR **st = stack->ary_array;
832 register int sp = arglast[1];
833 register int items = arglast[2] - sp;
837 int oldsave = savestack->ary_fill;
838 int oldtmps_base = tmps_base;
839 int hasargs = ((arg[2].arg_type & A_MASK) != A_NULL);
842 if ((arg[1].arg_type & A_MASK) == A_WORD)
843 stab = arg[1].arg_ptr.arg_stab;
845 STR *tmpstr = stab_val(arg[1].arg_ptr.arg_stab);
848 stab = stabent(str_get(tmpstr),TRUE);
853 fatal("Undefined subroutine called");
854 if (arg->arg_type == O_DBSUBR) {
855 str = stab_val(DBsub);
857 stab_fullname(str,stab);
858 sub = stab_sub(DBsub);
860 fatal("No DBsub routine");
863 if (!(sub = stab_sub(stab))) {
864 STR *tmpstr = arg[0].arg_ptr.arg_str;
866 stab_fullname(tmpstr, stab);
867 fatal("Undefined subroutine \"%s\" called",tmpstr->str_ptr);
870 str = Str_new(15, sizeof(CSV));
871 str->str_state = SS_SCSV;
872 (void)apush(savestack,str);
873 csv = (CSV*)str->str_ptr;
876 csv->curcsv = curcsv;
877 csv->curcmd = curcmd;
878 csv->depth = sub->depth;
879 csv->wantarray = gimme;
880 csv->hasargs = hasargs;
883 st[sp] = arg->arg_ptr.arg_str;
886 return (*sub->usersub)(sub->userindex,sp,items);
889 csv->savearray = stab_xarray(defstab);
890 csv->argarray = afake(defstab, items, &st[sp+1]);
891 stab_xarray(defstab) = csv->argarray;
894 if (sub->depth >= 2) { /* save temporaries on recursion? */
895 if (sub->depth == 100 && dowarn)
896 warn("Deep recursion on subroutine \"%s\"",stab_name(stab));
897 savelist(sub->tosave->ary_array,sub->tosave->ary_fill);
899 tmps_base = tmps_max;
900 sp = cmd_exec(sub->cmd,gimme, --sp); /* so do it already */
901 st = stack->ary_array;
903 tmps_base = oldtmps_base;
904 for (items = arglast[0] + 1; items <= sp; items++)
905 st[items] = str_static(st[items]);
906 /* in case restore wipes old str */
907 restorelist(oldsave);
912 do_assign(arg,gimme,arglast)
918 register STR **st = stack->ary_array;
919 STR **firstrelem = st + arglast[1] + 1;
920 STR **firstlelem = st + arglast[0] + 1;
921 STR **lastrelem = st + arglast[2];
922 STR **lastlelem = st + arglast[1];
923 register STR **relem;
924 register STR **lelem;
928 register int makelocal;
932 makelocal = (arg->arg_flags & AF_LOCAL);
933 localizing = makelocal;
934 delaymagic = DM_DELAY; /* catch simultaneous items */
936 /* If there's a common identifier on both sides we have to take
937 * special care that assigning the identifier on the left doesn't
938 * clobber a value on the right that's used later in the list.
940 if (arg->arg_flags & AF_COMMON) {
941 for (relem = firstrelem; relem <= lastrelem; relem++) {
943 *relem = str_static(str);
950 while (lelem <= lastlelem) {
952 if (str->str_state >= SS_HASH) {
953 if (str->str_state == SS_ARY) {
955 ary = saveary(str->str_u.str_stab);
957 ary = stab_array(str->str_u.str_stab);
961 while (relem <= lastrelem) { /* gobble up all the rest */
964 str_sset(str,*relem);
966 (void)astore(ary,i++,str);
969 else if (str->str_state == SS_HASH) {
973 STAB *tmpstab = str->str_u.str_stab;
976 hash = savehash(str->str_u.str_stab);
978 hash = stab_hash(str->str_u.str_stab);
979 if (tmpstab == envstab) {
983 else if (tmpstab == sigstab) {
988 for (i = 1; i < NSIG; i++)
989 signal(i, SIG_DFL); /* crunch, crunch, crunch */
992 else if (hash->tbl_dbm)
995 hclear(hash, magic == 'D'); /* wipe any dbm file too */
998 while (relem < lastrelem) { /* gobble up all the rest */
1002 str = &str_no, relem++;
1003 tmps = str_get(str);
1004 tmpstr = Str_new(29,0);
1006 str_sset(tmpstr,*relem); /* value */
1007 *(relem++) = tmpstr;
1008 (void)hstore(hash,tmps,str->str_cur,tmpstr,0);
1010 str_magic(tmpstr, tmpstab, magic, tmps, str->str_cur);
1011 stabset(tmpstr->str_magic, tmpstr);
1016 fatal("panic: do_assign");
1021 if (relem <= lastrelem) {
1022 str_sset(str, *relem);
1026 str_sset(str, &str_undef);
1027 if (gimme == G_ARRAY) {
1028 i = ++lastrelem - firstrelem;
1029 relem++; /* tacky, I suppose */
1030 astore(stack,i,str);
1031 if (st != stack->ary_array) {
1032 st = stack->ary_array;
1033 firstrelem = st + arglast[1] + 1;
1034 firstlelem = st + arglast[0] + 1;
1035 lastlelem = st + arglast[1];
1037 relem = lastrelem + 1;
1044 if (delaymagic > 1) {
1045 if (delaymagic & DM_REUID) {
1049 if (uid != euid || setuid(uid) < 0)
1050 fatal("No setreuid available");
1053 if (delaymagic & DM_REGID) {
1057 if (gid != egid || setgid(gid) < 0)
1058 fatal("No setregid available");
1064 if (gimme == G_ARRAY) {
1065 i = lastrelem - firstrelem + 1;
1067 Copy(firstrelem, firstlelem, i, STR*);
1068 return arglast[0] + i;
1071 str_numset(arg->arg_ptr.arg_str,(double)(arglast[2] - arglast[1]));
1072 *firstlelem = arg->arg_ptr.arg_str;
1073 return arglast[0] + 1;
1078 do_study(str,arg,gimme,arglast)
1084 register unsigned char *s;
1085 register int pos = str->str_cur;
1087 register int *sfirst;
1088 register int *snext;
1089 static int maxscream = -1;
1090 static STR *lastscream = Nullstr;
1092 int retarg = arglast[0] + 1;
1095 s = (unsigned char*)(str_get(str));
1097 s = Null(unsigned char*);
1100 lastscream->str_pok &= ~SP_STUDIED;
1106 if (pos > maxscream) {
1107 if (maxscream < 0) {
1108 maxscream = pos + 80;
1109 New(301,screamfirst, 256, int);
1110 New(302,screamnext, maxscream, int);
1113 maxscream = pos + pos / 4;
1114 Renew(screamnext, maxscream, int);
1118 sfirst = screamfirst;
1121 if (!sfirst || !snext)
1122 fatal("do_study: out of memory");
1124 for (ch = 256; ch; --ch)
1128 while (--pos >= 0) {
1130 if (sfirst[ch] >= 0)
1131 snext[pos] = sfirst[ch] - pos;
1136 /* If there were any case insensitive searches, we must assume they
1137 * all are. This speeds up insensitive searches much more than
1138 * it slows down sensitive ones.
1141 sfirst[fold[ch]] = pos;
1144 str->str_pok |= SP_STUDIED;
1147 str_numset(arg->arg_ptr.arg_str,(double)retval);
1148 stack->ary_array[retarg] = arg->arg_ptr.arg_str;
1153 do_defined(str,arg,gimme,arglast)
1160 register int retarg = arglast[0] + 1;
1165 if ((arg[1].arg_type & A_MASK) != A_LEXPR)
1166 fatal("Illegal argument to defined()");
1167 arg = arg[1].arg_ptr.arg_arg;
1168 type = arg->arg_type;
1170 if (type == O_SUBR || type == O_DBSUBR)
1171 retval = stab_sub(arg[1].arg_ptr.arg_stab) != 0;
1172 else if (type == O_ARRAY || type == O_LARRAY ||
1173 type == O_ASLICE || type == O_LASLICE )
1174 retval = ((ary = stab_xarray(arg[1].arg_ptr.arg_stab)) != 0
1175 && ary->ary_max >= 0 );
1176 else if (type == O_HASH || type == O_LHASH ||
1177 type == O_HSLICE || type == O_LHSLICE )
1178 retval = ((hash = stab_xhash(arg[1].arg_ptr.arg_stab)) != 0
1179 && hash->tbl_array);
1182 str_numset(str,(double)retval);
1183 stack->ary_array[retarg] = str;
1188 do_undef(str,arg,gimme,arglast)
1195 register STAB *stab;
1196 int retarg = arglast[0] + 1;
1198 if ((arg[1].arg_type & A_MASK) != A_LEXPR)
1199 fatal("Illegal argument to undef()");
1200 arg = arg[1].arg_ptr.arg_arg;
1201 type = arg->arg_type;
1203 if (type == O_ARRAY || type == O_LARRAY) {
1204 stab = arg[1].arg_ptr.arg_stab;
1205 afree(stab_xarray(stab));
1206 stab_xarray(stab) = Null(ARRAY*);
1208 else if (type == O_HASH || type == O_LHASH) {
1209 stab = arg[1].arg_ptr.arg_stab;
1210 if (stab == envstab)
1211 environ[0] = Nullch;
1212 else if (stab == sigstab) {
1215 for (i = 1; i < NSIG; i++)
1216 signal(i, SIG_DFL); /* munch, munch, munch */
1218 (void)hfree(stab_xhash(stab), TRUE);
1219 stab_xhash(stab) = Null(HASH*);
1221 else if (type == O_SUBR || type == O_DBSUBR) {
1222 stab = arg[1].arg_ptr.arg_stab;
1223 cmd_free(stab_sub(stab)->cmd);
1224 afree(stab_sub(stab)->tosave);
1225 Safefree(stab_sub(stab));
1226 stab_sub(stab) = Null(SUBR*);
1229 fatal("Can't undefine that kind of object");
1230 str_numset(str,0.0);
1231 stack->ary_array[retarg] = str;
1236 do_vec(lvalue,astr,arglast)
1241 STR **st = stack->ary_array;
1242 int sp = arglast[0];
1243 register STR *str = st[++sp];
1244 register int offset = (int)str_gnum(st[++sp]);
1245 register int size = (int)str_gnum(st[++sp]);
1246 unsigned char *s = (unsigned char*)str_get(str);
1247 unsigned long retnum;
1251 offset *= size; /* turn into bit offset */
1252 len = (offset + size + 7) / 8;
1253 if (offset < 0 || size < 1)
1255 else if (!lvalue && len > str->str_cur)
1258 if (len > str->str_cur) {
1260 (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
1263 s = (unsigned char*)str_get(str);
1265 retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
1270 else if (size == 16)
1271 retnum = (s[offset] << 8) + s[offset+1];
1272 else if (size == 32)
1273 retnum = (s[offset] << 24) + (s[offset + 1] << 16) +
1274 (s[offset + 2] << 8) + s[offset+3];
1277 if (lvalue) { /* it's an lvalue! */
1278 struct lstring *lstr = (struct lstring*)astr;
1280 astr->str_magic = str;
1281 st[sp]->str_rare = 'v';
1282 lstr->lstr_offset = offset;
1283 lstr->lstr_len = size;
1287 str_numset(astr,(double)retnum);
1297 struct lstring *lstr = (struct lstring*)str;
1298 register int offset;
1300 register unsigned char *s = (unsigned char*)mstr->str_ptr;
1301 register unsigned long lval = U_L(str_gnum(str));
1305 str->str_magic = Nullstr;
1306 offset = lstr->lstr_offset;
1307 size = lstr->lstr_len;
1309 mask = (1 << size) - 1;
1313 s[offset] &= ~(mask << size);
1314 s[offset] |= lval << size;
1318 s[offset] = lval & 255;
1319 else if (size == 16) {
1320 s[offset] = (lval >> 8) & 255;
1321 s[offset+1] = lval & 255;
1323 else if (size == 32) {
1324 s[offset] = (lval >> 24) & 255;
1325 s[offset+1] = (lval >> 16) & 255;
1326 s[offset+2] = (lval >> 8) & 255;
1327 s[offset+3] = lval & 255;
1336 register char *tmps;
1344 if (str->str_state == SS_ARY) {
1345 ary = stab_array(str->str_u.str_stab);
1346 for (i = 0; i <= ary->ary_fill; i++)
1347 do_chop(astr,ary->ary_array[i]);
1350 if (str->str_state == SS_HASH) {
1351 hash = stab_hash(str->str_u.str_stab);
1352 (void)hiterinit(hash);
1353 while (entry = hiternext(hash))
1354 do_chop(astr,hiterval(hash,entry));
1357 tmps = str_get(str);
1360 tmps += str->str_cur - (str->str_cur != 0);
1361 str_nset(astr,tmps,1); /* remember last char */
1362 *tmps = '\0'; /* wipe it out */
1363 str->str_cur = tmps - str->str_ptr;
1367 do_vop(optype,str,left,right)
1372 register char *s = str_get(str);
1373 register char *l = str_get(left);
1374 register char *r = str_get(right);
1377 len = left->str_cur;
1378 if (len > right->str_cur)
1379 len = right->str_cur;
1380 if (str->str_cur > len)
1382 else if (str->str_cur < len) {
1384 (void)bzero(str->str_ptr + str->str_cur, len - str->str_cur);
1402 if (right->str_cur > len)
1403 str_ncat(str,right->str_ptr+len,right->str_cur - len);
1404 else if (left->str_cur > len)
1405 str_ncat(str,left->str_ptr+len,left->str_cur - len);
1414 register STR **st = stack->ary_array;
1415 register int sp = arglast[1];
1416 register int items = arglast[2] - sp;
1423 for (st += ++sp; items--; st++)
1424 tainted |= (*st)->str_tainted;
1425 st = stack->ary_array;
1427 items = arglast[2] - sp;
1430 taintproper("Insecure dependency in syscall");
1432 /* This probably won't work on machines where sizeof(long) != sizeof(int)
1433 * or where sizeof(long) != sizeof(char*). But such machines will
1434 * not likely have syscall implemented either, so who cares?
1437 if (st[++sp]->str_nok || !i)
1438 arg[i++] = (long)str_gnum(st[sp]);
1441 arg[i++] = (long)st[sp]->str_ptr;
1445 items = arglast[2] - sp;
1448 fatal("Too few args to syscall");
1450 retval = syscall(arg[0]);
1453 retval = syscall(arg[0],arg[1]);
1456 retval = syscall(arg[0],arg[1],arg[2]);
1459 retval = syscall(arg[0],arg[1],arg[2],arg[3]);
1462 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]);
1465 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
1468 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
1471 retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
1477 fatal("syscall() unimplemented");