home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / perl / Perl / doop.c < prev    next >
C/C++ Source or Header  |  1995-02-13  |  13KB  |  674 lines

  1. /*    doop.c
  2.  *
  3.  *    Copyright (c) 1991-1994, Larry Wall
  4.  *
  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.
  7.  *
  8.  */
  9.  
  10. /*
  11.  * "'So that was the job I felt I had to do when I started,' thought Sam."
  12.  */
  13.  
  14. #include "EXTERN.h"
  15. #include "perl.h"
  16.  
  17. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  18. #include <signal.h>
  19. #endif
  20.  
  21. #ifdef BUGGY_MSC
  22.  #pragma function(memcmp)
  23. #endif /* BUGGY_MSC */
  24.  
  25. #ifdef BUGGY_MSC
  26.  #pragma intrinsic(memcmp)
  27. #endif /* BUGGY_MSC */
  28.  
  29. I32
  30. do_trans(sv,arg)
  31. SV *sv;
  32. OP *arg;
  33. {
  34.     register short *tbl;
  35.     register char *s;
  36.     register I32 matches = 0;
  37.     register I32 ch;
  38.     register char *send;
  39.     register char *d;
  40.     register I32 squash = op->op_private & OPpTRANS_SQUASH;
  41.     STRLEN len;
  42.  
  43.     if (SvREADONLY(sv))
  44.     croak(no_modify);
  45.     tbl = (short*) cPVOP->op_pv;
  46.     s = SvPV(sv, len);
  47.     if (!len)
  48.     return 0;
  49.     if (!SvPOKp(sv))
  50.     s = SvPV_force(sv, len);
  51.     (void)SvPOK_only(sv);
  52.     send = s + len;
  53.     if (!tbl || !s)
  54.     croak("panic: do_trans");
  55.     DEBUG_t( deb("2.TBL\n"));
  56.     if (!op->op_private) {
  57.     while (s < send) {
  58.         if ((ch = tbl[*s & 0377]) >= 0) {
  59.         matches++;
  60.         *s = ch;
  61.         }
  62.         s++;
  63.     }
  64.     }
  65.     else {
  66.     d = s;
  67.     while (s < send) {
  68.         if ((ch = tbl[*s & 0377]) >= 0) {
  69.         *d = ch;
  70.         if (matches++ && squash) {
  71.             if (d[-1] == *d)
  72.             matches--;
  73.             else
  74.             d++;
  75.         }
  76.         else
  77.             d++;
  78.         }
  79.         else if (ch == -1)        /* -1 is unmapped character */
  80.         *d++ = *s;        /* -2 is delete character */
  81.         s++;
  82.     }
  83.     matches += send - d;    /* account for disappeared chars */
  84.     *d = '\0';
  85.     SvCUR_set(sv, d - SvPVX(sv));
  86.     }
  87.     SvSETMAGIC(sv);
  88.     return matches;
  89. }
  90.  
  91. void
  92. do_join(sv,del,mark,sp)
  93. register SV *sv;
  94. SV *del;
  95. register SV **mark;
  96. register SV **sp;
  97. {
  98.     SV **oldmark = mark;
  99.     register I32 items = sp - mark;
  100.     register STRLEN len;
  101.     STRLEN delimlen;
  102.     register char *delim = SvPV(del, delimlen);
  103.     STRLEN tmplen;
  104.  
  105.     mark++;
  106.     len = (items > 0 ? (delimlen * (items - 1) ) : 0);
  107.     if (SvTYPE(sv) < SVt_PV)
  108.     sv_upgrade(sv, SVt_PV);
  109.     if (SvLEN(sv) < len + items) {    /* current length is way too short */
  110.     while (items-- > 0) {
  111.         if (*mark) {
  112.         SvPV(*mark, tmplen);
  113.         len += tmplen;
  114.         }
  115.         mark++;
  116.     }
  117.     SvGROW(sv, len + 1);        /* so try to pre-extend */
  118.  
  119.     mark = oldmark;
  120.     items = sp - mark;;
  121.     ++mark;
  122.     }
  123.  
  124.     if (items-- > 0) {
  125.     char *s;
  126.  
  127.     if (*mark) {
  128.         s = SvPV(*mark, tmplen);
  129.         sv_setpvn(sv, s, tmplen);
  130.     }
  131.     else
  132.         sv_setpv(sv, "");
  133.     mark++;
  134.     }
  135.     else
  136.     sv_setpv(sv,"");
  137.     len = delimlen;
  138.     if (len) {
  139.     for (; items > 0; items--,mark++) {
  140.         sv_catpvn(sv,delim,len);
  141.         sv_catsv(sv,*mark);
  142.     }
  143.     }
  144.     else {
  145.     for (; items > 0; items--,mark++)
  146.         sv_catsv(sv,*mark);
  147.     }
  148.     SvSETMAGIC(sv);
  149. }
  150.  
  151. void
  152. do_sprintf(sv,len,sarg)
  153. register SV *sv;
  154. register I32 len;
  155. register SV **sarg;
  156. {
  157.     register char *s;
  158.     register char *t;
  159.     register char *f;
  160.     bool dolong;
  161. #ifdef HAS_QUAD
  162.     bool doquad;
  163. #endif /* HAS_QUAD */
  164.     char ch;
  165.     register char *send;
  166.     register SV *arg;
  167.     char *xs;
  168.     I32 xlen;
  169.     I32 pre;
  170.     I32 post;
  171.     double value;
  172.     STRLEN arglen;
  173.  
  174.     sv_setpv(sv,"");
  175.     len--;            /* don't count pattern string */
  176.     t = s = SvPV(*sarg, arglen);    /* XXX Don't know t is writeable */
  177.     send = s + arglen;
  178.     sarg++;
  179.     for ( ; ; len--) {
  180.  
  181.     /*SUPPRESS 560*/
  182.     if (len <= 0 || !(arg = *sarg++))
  183.         arg = &sv_no;
  184.  
  185.     /*SUPPRESS 530*/
  186.     for ( ; t < send && *t != '%'; t++) ;
  187.     if (t >= send)
  188.         break;        /* end of run_format string, ignore extra args */
  189.     f = t;
  190.     *buf = '\0';
  191.     xs = buf;
  192. #ifdef HAS_QUAD
  193.     doquad =
  194. #endif /* HAS_QUAD */
  195.     dolong = FALSE;
  196.     pre = post = 0;
  197.     for (t++; t < send; t++) {
  198.         switch (*t) {
  199.         default:
  200.         ch = *(++t);
  201.         *t = '\0';
  202.         (void)sprintf(xs,f);
  203.         len++, sarg--;
  204.         xlen = strlen(xs);
  205.         break;
  206.         case 'n': case '*':
  207.         croak("Use of %c in printf format not supported", *t);
  208.  
  209.         case '0': case '1': case '2': case '3': case '4':
  210.         case '5': case '6': case '7': case '8': case '9': 
  211.         case '.': case '#': case '-': case '+': case ' ':
  212.         continue;
  213.         case 'l':
  214. #ifdef HAS_QUAD
  215.         if (dolong) {
  216.             dolong = FALSE;
  217.             doquad = TRUE;
  218.         } else
  219. #endif
  220.         dolong = TRUE;
  221.         continue;
  222.         case 'c':
  223.         ch = *(++t);
  224.         *t = '\0';
  225.         xlen = SvIV(arg);
  226.         if (strEQ(f,"%c")) { /* some printfs fail on null chars */
  227.             *xs = xlen;
  228.             xs[1] = '\0';
  229.             xlen = 1;
  230.         }
  231.         else {
  232.             (void)sprintf(xs,f,xlen);
  233.             xlen = strlen(xs);
  234.         }
  235.         break;
  236.         case 'D':
  237.         dolong = TRUE;
  238.         /* FALL THROUGH */
  239.         case 'd':
  240.         ch = *(++t);
  241.         *t = '\0';
  242. #ifdef HAS_QUAD
  243.         if (doquad)
  244.             (void)sprintf(buf,s,(Quad_t)SvNV(arg));
  245.         else
  246. #endif
  247.         if (dolong)
  248.             (void)sprintf(xs,f,(long)SvNV(arg));
  249.         else
  250.             (void)sprintf(xs,f,SvIV(arg));
  251.         xlen = strlen(xs);
  252.         break;
  253.         case 'X': case 'O':
  254.         dolong = TRUE;
  255.         /* FALL THROUGH */
  256.         case 'x': case 'o': case 'u':
  257.         ch = *(++t);
  258.         *t = '\0';
  259.         value = SvNV(arg);
  260. #ifdef HAS_QUAD
  261.         if (doquad)
  262.             (void)sprintf(buf,s,(unsigned Quad_t)value);
  263.         else
  264. #endif
  265.         if (dolong)
  266.             (void)sprintf(xs,f,U_L(value));
  267.         else
  268.             (void)sprintf(xs,f,U_I(value));
  269.         xlen = strlen(xs);
  270.         break;
  271.         case 'E': case 'e': case 'f': case 'G': case 'g':
  272.         ch = *(++t);
  273.         *t = '\0';
  274.         (void)sprintf(xs,f,SvNV(arg));
  275.         xlen = strlen(xs);
  276.         break;
  277.         case 's':
  278.         ch = *(++t);
  279.         *t = '\0';
  280.         xs = SvPV(arg, arglen);
  281.         xlen = (I32)arglen;
  282.         if (strEQ(f,"%s")) {    /* some printfs fail on >128 chars */
  283.             break;        /* so handle simple cases */
  284.         }
  285.         else if (f[1] == '-') {
  286.             char *mp = strchr(f, '.');
  287.             I32 min = atoi(f+2);
  288.  
  289.             if (mp) {
  290.             I32 max = atoi(mp+1);
  291.  
  292.             if (xlen > max)
  293.                 xlen = max;
  294.             }
  295.             if (xlen < min)
  296.             post = min - xlen;
  297.             break;
  298.         }
  299.         else if (isDIGIT(f[1])) {
  300.             char *mp = strchr(f, '.');
  301.             I32 min = atoi(f+1);
  302.  
  303.             if (mp) {
  304.             I32 max = atoi(mp+1);
  305.  
  306.             if (xlen > max)
  307.                 xlen = max;
  308.             }
  309.             if (xlen < min)
  310.             pre = min - xlen;
  311.             break;
  312.         }
  313.         strcpy(tokenbuf+64,f);    /* sprintf($s,...$s...) */
  314.         *t = ch;
  315.         (void)sprintf(buf,tokenbuf+64,xs);
  316.         xs = buf;
  317.         xlen = strlen(xs);
  318.         break;
  319.         }
  320.         /* end of switch, copy results */
  321.         *t = ch;
  322.         SvGROW(sv, SvCUR(sv) + (f - s) + xlen + 1 + pre + post);
  323.         sv_catpvn(sv, s, f - s);
  324.         if (pre) {
  325.         repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, pre);
  326.         SvCUR(sv) += pre;
  327.         }
  328.         sv_catpvn(sv, xs, xlen);
  329.         if (post) {
  330.         repeatcpy(SvPVX(sv) + SvCUR(sv), " ", 1, post);
  331.         SvCUR(sv) += post;
  332.         }
  333.         s = t;
  334.         break;        /* break from for loop */
  335.     }
  336.     }
  337.     sv_catpvn(sv, s, t - s);
  338.     SvSETMAGIC(sv);
  339. }
  340.  
  341. void
  342. do_vecset(sv)
  343. SV *sv;
  344. {
  345.     SV *targ = LvTARG(sv);
  346.     register I32 offset;
  347.     register I32 size;
  348.     register unsigned char *s;
  349.     register unsigned long lval;
  350.     I32 mask;
  351.     STRLEN targlen;
  352.     STRLEN len;
  353.  
  354.     if (!targ)
  355.     return;
  356.     s = (unsigned char*)SvPV_force(targ, targlen);
  357.     lval = U_L(SvNV(sv));
  358.     offset = LvTARGOFF(sv);
  359.     size = LvTARGLEN(sv);
  360.     
  361.     len = (offset + size + 7) / 8;
  362.     if (len > targlen) {
  363.     s = (unsigned char*)SvGROW(targ, len + 1);
  364.     (void)memzero(s + targlen, len - targlen + 1);
  365.     SvCUR_set(targ, len);
  366.     }
  367.     
  368.     if (size < 8) {
  369.     mask = (1 << size) - 1;
  370.     size = offset & 7;
  371.     lval &= mask;
  372.     offset >>= 3;
  373.     s[offset] &= ~(mask << size);
  374.     s[offset] |= lval << size;
  375.     }
  376.     else {
  377.     offset >>= 3;
  378.     if (size == 8)
  379.         s[offset] = lval & 255;
  380.     else if (size == 16) {
  381.         s[offset] = (lval >> 8) & 255;
  382.         s[offset+1] = lval & 255;
  383.     }
  384.     else if (size == 32) {
  385.         s[offset] = (lval >> 24) & 255;
  386.         s[offset+1] = (lval >> 16) & 255;
  387.         s[offset+2] = (lval >> 8) & 255;
  388.         s[offset+3] = lval & 255;
  389.     }
  390.     }
  391. }
  392.  
  393. void
  394. do_chop(astr,sv)
  395. register SV *astr;
  396. register SV *sv;
  397. {
  398.     STRLEN len;
  399.     char *s;
  400.     
  401.     if (SvTYPE(sv) == SVt_PVAV) {
  402.     register I32 i;
  403.         I32 max;
  404.     AV* av = (AV*)sv;
  405.         max = AvFILL(av);
  406.         for (i = 0; i <= max; i++) {
  407.         sv = (SV*)av_fetch(av, i, FALSE);
  408.         if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
  409.         do_chop(astr, sv);
  410.     }
  411.         return;
  412.     }
  413.     if (SvTYPE(sv) == SVt_PVHV) {
  414.         HV* hv = (HV*)sv;
  415.     HE* entry;
  416.         (void)hv_iterinit(hv);
  417.         /*SUPPRESS 560*/
  418.         while (entry = hv_iternext(hv))
  419.             do_chop(astr,hv_iterval(hv,entry));
  420.         return;
  421.     }
  422.     s = SvPV(sv, len);
  423.     if (len && !SvPOK(sv))
  424.     s = SvPV_force(sv, len);
  425.     if (s && len) {
  426.     s += --len;
  427.     sv_setpvn(astr, s, 1);
  428.     *s = '\0';
  429.     SvCUR_set(sv, len);
  430.     SvNIOK_off(sv);
  431.     }
  432.     else
  433.     sv_setpvn(astr, "", 0);
  434.     SvSETMAGIC(sv);
  435.  
  436. I32
  437. do_chomp(sv)
  438. register SV *sv;
  439. {
  440.     register I32 count = 0;
  441.     STRLEN len;
  442.     char *s;
  443.     
  444.     if (SvTYPE(sv) == SVt_PVAV) {
  445.     register I32 i;
  446.         I32 max;
  447.     AV* av = (AV*)sv;
  448.         max = AvFILL(av);
  449.         for (i = 0; i <= max; i++) {
  450.         sv = (SV*)av_fetch(av, i, FALSE);
  451.         if (sv && ((sv = *(SV**)sv), sv != &sv_undef))
  452.         count += do_chomp(sv);
  453.     }
  454.         return count;
  455.     }
  456.     if (SvTYPE(sv) == SVt_PVHV) {
  457.         HV* hv = (HV*)sv;
  458.     HE* entry;
  459.         (void)hv_iterinit(hv);
  460.         /*SUPPRESS 560*/
  461.         while (entry = hv_iternext(hv))
  462.             count += do_chomp(hv_iterval(hv,entry));
  463.         return count;
  464.     }
  465.     s = SvPV(sv, len);
  466.     if (len && !SvPOKp(sv))
  467.     s = SvPV_force(sv, len);
  468.     if (s && len) {
  469.     s += --len;
  470.     if (rspara) {
  471.         if (*s != '\n')
  472.         goto nope;
  473.         ++count;
  474.         while (len && s[-1] == '\n') {
  475.         --len;
  476.         --s;
  477.         ++count;
  478.         }
  479.     }
  480.     else if (rslen == 1) {
  481.         if (*s != rschar)
  482.         goto nope;
  483.         ++count;
  484.     } 
  485.     else {
  486.         if (len < rslen - 1)
  487.         goto nope;
  488.         len -= rslen - 1;
  489.         s -= rslen - 1;
  490.         if (bcmp(s, rs, rslen))
  491.         goto nope;
  492.         count += rslen;
  493.     }
  494.  
  495.     *s = '\0';
  496.     SvCUR_set(sv, len);
  497.     SvNIOK_off(sv);
  498.     }
  499.   nope:
  500.     SvSETMAGIC(sv);
  501.     return count;
  502.  
  503. void
  504. do_vop(optype,sv,left,right)
  505. I32 optype;
  506. SV *sv;
  507. SV *left;
  508. SV *right;
  509. {
  510. #ifdef LIBERAL
  511.     register long *dl;
  512.     register long *ll;
  513.     register long *rl;
  514. #endif
  515.     register char *dc;
  516.     STRLEN leftlen;
  517.     STRLEN rightlen;
  518.     register char *lc = SvPV(left, leftlen);
  519.     register char *rc = SvPV(right, rightlen);
  520.     register I32 len;
  521.     I32 lensave;
  522.  
  523.     dc = SvPV_force(sv,na);
  524.     len = leftlen < rightlen ? leftlen : rightlen;
  525.     lensave = len;
  526.     if (SvCUR(sv) < len) {
  527.     dc = SvGROW(sv,len + 1);
  528.     (void)memzero(dc + SvCUR(sv), len - SvCUR(sv) + 1);
  529.     }
  530.     SvCUR_set(sv, len);
  531.     *SvEND(sv) = '\0';
  532.     (void)SvPOK_only(sv);
  533. #ifdef LIBERAL
  534.     if (len >= sizeof(long)*4 &&
  535.     !((long)dc % sizeof(long)) &&
  536.     !((long)lc % sizeof(long)) &&
  537.     !((long)rc % sizeof(long)))    /* It's almost always aligned... */
  538.     {
  539.     I32 remainder = len % (sizeof(long)*4);
  540.     len /= (sizeof(long)*4);
  541.  
  542.     dl = (long*)dc;
  543.     ll = (long*)lc;
  544.     rl = (long*)rc;
  545.  
  546.     switch (optype) {
  547.     case OP_BIT_AND:
  548.         while (len--) {
  549.         *dl++ = *ll++ & *rl++;
  550.         *dl++ = *ll++ & *rl++;
  551.         *dl++ = *ll++ & *rl++;
  552.         *dl++ = *ll++ & *rl++;
  553.         }
  554.         break;
  555.     case OP_BIT_XOR:
  556.         while (len--) {
  557.         *dl++ = *ll++ ^ *rl++;
  558.         *dl++ = *ll++ ^ *rl++;
  559.         *dl++ = *ll++ ^ *rl++;
  560.         *dl++ = *ll++ ^ *rl++;
  561.         }
  562.         break;
  563.     case OP_BIT_OR:
  564.         while (len--) {
  565.         *dl++ = *ll++ | *rl++;
  566.         *dl++ = *ll++ | *rl++;
  567.         *dl++ = *ll++ | *rl++;
  568.         *dl++ = *ll++ | *rl++;
  569.         }
  570.     }
  571.  
  572.     dc = (char*)dl;
  573.     lc = (char*)ll;
  574.     rc = (char*)rl;
  575.  
  576.     len = remainder;
  577.     }
  578. #endif
  579.     {
  580.     char *lsave = lc;
  581.     char *rsave = rc;
  582.     
  583.     switch (optype) {
  584.     case OP_BIT_AND:
  585.         while (len--)
  586.         *dc++ = *lc++ & *rc++;
  587.         break;
  588.     case OP_BIT_XOR:
  589.         while (len--)
  590.         *dc++ = *lc++ ^ *rc++;
  591.         goto mop_up;
  592.     case OP_BIT_OR:
  593.         while (len--)
  594.         *dc++ = *lc++ | *rc++;
  595.       mop_up:
  596.         len = lensave;
  597.         if (rightlen > len)
  598.         sv_catpvn(sv, rsave + len, rightlen - len);
  599.         else if (leftlen > len)
  600.         sv_catpvn(sv, lsave + len, leftlen - len);
  601.         break;
  602.     }
  603.     }
  604. }
  605.  
  606. OP *
  607. do_kv(ARGS)
  608. dARGS
  609. {
  610.     dSP;
  611.     HV *hv = (HV*)POPs;
  612.     I32 i;
  613.     register HE *entry;
  614.     char *tmps;
  615.     SV *tmpstr;
  616.     I32 dokeys =   (op->op_type == OP_KEYS);
  617.     I32 dovalues = (op->op_type == OP_VALUES);
  618.  
  619.     if (op->op_type == OP_RV2HV || op->op_type == OP_PADHV) 
  620.     dokeys = dovalues = TRUE;
  621.  
  622.     if (!hv)
  623.     RETURN;
  624.  
  625.     (void)hv_iterinit(hv);    /* always reset iterator regardless */
  626.  
  627.     if (GIMME != G_ARRAY) {
  628.     dTARGET;
  629.  
  630.     if (!SvRMAGICAL(hv) || !mg_find((SV*)hv,'P'))
  631.         i = HvKEYS(hv);
  632.     else {
  633.         i = 0;
  634.         /*SUPPRESS 560*/
  635.         while (entry = hv_iternext(hv)) {
  636.         i++;
  637.         }
  638.     }
  639.     PUSHi( i );
  640.     RETURN;
  641.     }
  642.  
  643.     /* Guess how much room we need.  hv_max may be a few too many.  Oh well. */
  644.     EXTEND(sp, HvMAX(hv) * (dokeys + dovalues));
  645.  
  646.     PUTBACK;    /* hv_iternext and hv_iterval might clobber stack_sp */
  647.     while (entry = hv_iternext(hv)) {
  648.     SPAGAIN;
  649.     if (dokeys) {
  650.         tmps = hv_iterkey(entry,&i);    /* won't clobber stack_sp */
  651.         if (!i)
  652.         tmps = "";
  653.         XPUSHs(sv_2mortal(newSVpv(tmps,i)));
  654.     }
  655.     if (dovalues) {
  656.         tmpstr = NEWSV(45,0);
  657.         PUTBACK;
  658.         sv_setsv(tmpstr,hv_iterval(hv,entry));
  659.         SPAGAIN;
  660.         DEBUG_H( {
  661.         sprintf(buf,"%d%%%d=%d\n",entry->hent_hash,
  662.             HvMAX(hv)+1,entry->hent_hash & HvMAX(hv));
  663.         sv_setpv(tmpstr,buf);
  664.         } )
  665.         XPUSHs(sv_2mortal(tmpstr));
  666.     }
  667.     PUTBACK;
  668.     }
  669.     return NORMAL;
  670. }
  671.  
  672.