1 /* $RCSfile: doarg.c,v $$Revision: 4.1 $$Date: 92/08/07 17:19:37 $
3 * Copyright (c) 1991, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
9 * Revision 4.1 92/08/07 17:19:37 lwall
12 * Revision 4.0.1.7 92/06/11 21:07:11 lwall
13 * patch34: join with null list attempted negative allocation
14 * patch34: sprintf("%6.4s", "abcdefg") didn't print "abcd "
16 * Revision 4.0.1.6 92/06/08 12:34:30 lwall
17 * patch20: removed implicit int declarations on funcions
18 * patch20: pattern modifiers i and o didn't interact right
19 * patch20: join() now pre-extends target string to avoid excessive copying
20 * patch20: fixed confusion between a *var's real name and its effective name
21 * patch20: subroutines didn't localize $`, $&, $', $1 et al correctly
22 * patch20: usersub routines didn't reclaim temp values soon enough
23 * patch20: ($<,$>) = ... didn't work on some architectures
24 * patch20: added Atari ST portability
26 * Revision 4.0.1.5 91/11/11 16:31:58 lwall
27 * patch19: added little-endian pack/unpack options
29 * Revision 4.0.1.4 91/11/05 16:35:06 lwall
30 * patch11: /$foo/o optimizer could access deallocated data
31 * patch11: minimum match length calculation in regexp is now cumulative
32 * patch11: added some support for 64-bit integers
33 * patch11: prepared for ctype implementations that don't define isascii()
34 * patch11: sprintf() now supports any length of s field
35 * patch11: indirect subroutine calls through magic vars (e.g. &$1) didn't work
36 * patch11: defined(&$foo) and undef(&$foo) didn't work
38 * Revision 4.0.1.3 91/06/10 01:18:41 lwall
39 * patch10: pack(hh,1) dumped core
41 * Revision 4.0.1.2 91/06/07 10:42:17 lwall
42 * patch4: new copyright notice
43 * patch4: // wouldn't use previous pattern if it started with a null character
44 * patch4: //o and s///o now optimize themselves fully at runtime
45 * patch4: added global modifier for pattern matches
46 * patch4: undef @array disabled "@array" interpolation
47 * patch4: chop("") was returning "\0" rather than ""
48 * patch4: vector logical operations &, | and ^ sometimes returned null string
49 * patch4: syscall couldn't pass numbers with most significant bit set on sparcs
51 * Revision 4.0.1.1 91/04/11 17:40:14 lwall
52 * patch1: fixed undefined environ problem
53 * patch1: fixed debugger coredump on subroutines
55 * Revision 4.0 91/03/20 01:06:42 lwall
63 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
68 #pragma function(memcmp)
69 #endif /* BUGGY_MSC */
71 static void doencodes();
74 #pragma intrinsic(memcmp)
75 #endif /* BUGGY_MSC */
84 register I32 matches = 0;
88 register I32 squash = op->op_private & OPpTRANS_SQUASH;
91 tbl = (short*) cPVOP->op_pv;
95 croak("panic: do_trans");
96 DEBUG_t( deb("2.TBL\n"));
97 if (!op->op_private) {
99 if ((ch = tbl[*s & 0377]) >= 0) {
109 if ((ch = tbl[*s & 0377]) >= 0) {
111 if (matches++ && squash) {
120 else if (ch == -1) /* -1 is unmapped character */
121 *d++ = *s; /* -2 is delete character */
124 matches += send - d; /* account for disappeared chars */
126 SvCUR_set(sv, d - SvPVX(sv));
133 do_join(sv,del,mark,sp)
140 register I32 items = sp - mark;
143 register char *delim = SvPV(del, delimlen);
147 len = (items > 0 ? (delimlen * (items - 1) ) : 0);
148 if (SvTYPE(sv) < SVt_PV)
149 sv_upgrade(sv, SVt_PV);
150 if (SvLEN(sv) < len + items) { /* current length is way too short */
151 while (items-- > 0) {
158 SvGROW(sv, len + 1); /* so try to pre-extend */
169 s = SvPV(*mark, tmplen);
170 sv_setpvn(sv, s, tmplen);
180 for (; items > 0; items--,mark++) {
181 sv_catpvn(sv,delim,len);
186 for (; items > 0; items--,mark++)
193 do_sprintf(sv,len,sarg)
216 len--; /* don't count pattern string */
217 t = s = SvPV(*sarg, arglen);
223 if (len <= 0 || !(arg = *sarg++))
227 for ( ; t < send && *t != '%'; t++) ;
229 break; /* end of run_format string, ignore extra args */
238 for (t++; t < send; t++) {
247 case '0': case '1': case '2': case '3': case '4':
248 case '5': case '6': case '7': case '8': case '9':
249 case '.': case '#': case '-': case '+': case ' ':
264 if (strEQ(f,"%c")) { /* some printfs fail on null chars */
270 (void)sprintf(xs,f,xlen);
282 (void)sprintf(buf,s,(quad)SvNV(arg));
286 (void)sprintf(xs,f,(long)SvNV(arg));
288 (void)sprintf(xs,f,SvIV(arg));
294 case 'x': case 'o': case 'u':
300 (void)sprintf(buf,s,(unsigned quad)value);
304 (void)sprintf(xs,f,U_L(value));
306 (void)sprintf(xs,f,U_I(value));
309 case 'E': case 'e': case 'f': case 'G': case 'g':
312 (void)sprintf(xs,f,SvNV(arg));
318 xs = SvPV(arg, arglen);
320 if (strEQ(f,"%s")) { /* some printfs fail on >128 chars */
321 break; /* so handle simple cases */
323 else if (f[1] == '-') {
324 char *mp = strchr(f, '.');
328 I32 max = atoi(mp+1);
337 else if (isDIGIT(f[1])) {
338 char *mp = strchr(f, '.');
342 I32 max = atoi(mp+1);
351 strcpy(tokenbuf+64,f); /* sprintf($s,...$s...) */
353 (void)sprintf(buf,tokenbuf+64,xs);
358 /* end of switch, copy results */
360 SvGROW(sv, SvCUR(sv) + (f - s) + xlen + 1 + pre + post);
361 sv_catpvn(sv, s, f - s);
363 repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, pre);
366 sv_catpvn(sv, xs, xlen);
368 repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, post);
372 break; /* break from for loop */
375 sv_catpvn(sv, s, t - s);
383 SV *targ = LvTARG(sv);
386 register unsigned char *s;
387 register unsigned long lval;
392 s = (unsigned char*)SvPVX(targ);
393 lval = U_L(SvNV(sv));
394 offset = LvTARGOFF(sv);
395 size = LvTARGLEN(sv);
397 mask = (1 << size) - 1;
401 s[offset] &= ~(mask << size);
402 s[offset] |= lval << size;
406 s[offset] = lval & 255;
407 else if (size == 16) {
408 s[offset] = (lval >> 8) & 255;
409 s[offset+1] = lval & 255;
411 else if (size == 32) {
412 s[offset] = (lval >> 24) & 255;
413 s[offset+1] = (lval >> 16) & 255;
414 s[offset+2] = (lval >> 8) & 255;
415 s[offset+3] = lval & 255;
434 if (SvTHINKFIRST(sv)) {
436 croak("Can't chop readonly value");
440 if (SvTYPE(sv) == SVt_PVAV) {
442 SV **array = AvARRAY(sv);
444 for (i = 0; i <= max; i++)
445 do_chop(astr,array[i]);
448 if (SvTYPE(sv) == SVt_PVHV) {
450 (void)hv_iterinit(hv);
452 while (entry = hv_iternext(hv))
453 do_chop(astr,hv_iterval(hv,entry));
456 tmps = SvPV(sv, len);
459 sv_setpvn(astr,tmps,1); /* remember last char */
460 *tmps = '\0'; /* wipe it out */
461 SvCUR_set(sv, tmps - SvPVX(sv));
466 sv_setpvn(astr,"",0);
470 do_vop(optype,sv,left,right)
484 register char *lc = SvPV(left, leftlen);
485 register char *rc = SvPV(right, rightlen);
488 if (SvTHINKFIRST(sv)) {
490 croak("Can't do %s to readonly value", op_name[optype]);
494 len = leftlen < rightlen ? leftlen : rightlen;
495 if (SvTYPE(sv) < SVt_PV)
496 sv_upgrade(sv, SVt_PV);
499 else if (SvCUR(sv) < len) {
501 (void)memzero(SvPVX(sv) + SvCUR(sv), len - SvCUR(sv));
511 if (len >= sizeof(long)*4 &&
512 !((long)dc % sizeof(long)) &&
513 !((long)lc % sizeof(long)) &&
514 !((long)rc % sizeof(long))) /* It's almost always aligned... */
516 I32 remainder = len % (sizeof(long)*4);
517 len /= (sizeof(long)*4);
526 *dl++ = *ll++ & *rl++;
527 *dl++ = *ll++ & *rl++;
528 *dl++ = *ll++ & *rl++;
529 *dl++ = *ll++ & *rl++;
534 *dl++ = *ll++ ^ *rl++;
535 *dl++ = *ll++ ^ *rl++;
536 *dl++ = *ll++ ^ *rl++;
537 *dl++ = *ll++ ^ *rl++;
542 *dl++ = *ll++ | *rl++;
543 *dl++ = *ll++ | *rl++;
544 *dl++ = *ll++ | *rl++;
545 *dl++ = *ll++ | *rl++;
559 *dc++ = *lc++ & *rc++;
563 *dc++ = *lc++ ^ *rc++;
567 *dc++ = *lc++ | *rc++;
571 sv_catpvn(sv, SvPVX(right) + len, rightlen - len);
572 else if (leftlen > len)
573 sv_catpvn(sv, SvPVX(left) + len, leftlen - len);
584 register AV *ary = stack;
589 I32 dokeys = (op->op_type == OP_KEYS || op->op_type == OP_RV2HV);
590 I32 dovalues = (op->op_type == OP_VALUES || op->op_type == OP_RV2HV);
594 if (GIMME != G_ARRAY) {
597 if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
601 (void)hv_iterinit(hv);
603 while (entry = hv_iternext(hv)) {
611 /* Guess how much room we need. hv_max may be a few too many. Oh well. */
612 EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
614 (void)hv_iterinit(hv);
616 PUTBACK; /* hv_iternext and hv_iterval might clobber stack_sp */
617 while (entry = hv_iternext(hv)) {
620 tmps = hv_iterkey(entry,&i); /* won't clobber stack_sp */
623 XPUSHs(sv_2mortal(newSVpv(tmps,i)));
626 tmpstr = NEWSV(45,0);
628 sv_setsv(tmpstr,hv_iterval(hv,entry));
631 sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
632 HvMAX(hv)+1,entry->hent_hash & HvMAX(hv));
633 sv_setpv(tmpstr,buf);
635 XPUSHs(sv_2mortal(tmpstr));