summaryrefslogtreecommitdiff
path: root/doop.c
diff options
context:
space:
mode:
authorJarkko Hietaniemi <jhi@iki.fi>1999-08-19 12:49:41 +0000
committerJarkko Hietaniemi <jhi@iki.fi>1999-08-19 12:49:41 +0000
commit81e118e078828ea41cd654ee18f4193484a89cf3 (patch)
tree62637e08be5499f11f20df252b484d835c58e171 /doop.c
parent41bd693c38b93b50972065296573f26c13cc43d1 (diff)
downloadperl-81e118e078828ea41cd654ee18f4193484a89cf3.tar.gz
Removed duplicated code (in pp.c and mg.c) by introducing
do_vecget(). NOTE: the calling convention of do_vecset() changes, too: the `offset' that is assigned to LvTARGOFF(TARG) in pp_vec() is no more multiplied by `size' in pp_vec(), the multiplication is now done in do_vecset(). Also fix a cpp thinko in change #4002. p4raw-link: @4002 on //depot/cfgperl: 24db6c0d56fddf85ee587fc1cb1dbce678fa6a8c p4raw-id: //depot/cfgperl@4004
Diffstat (limited to 'doop.c')
-rw-r--r--doop.c76
1 files changed, 71 insertions, 5 deletions
diff --git a/doop.c b/doop.c
index ad626ca6d3..b06483852c 100644
--- a/doop.c
+++ b/doop.c
@@ -697,6 +697,71 @@ Perl_do_sprintf(pTHX_ SV *sv, I32 len, SV **sarg)
SvTAINTED_on(sv);
}
+UV
+Perl_do_vecget(pTHX_ SV *sv, I32 offset, I32 size)
+{
+ STRLEN srclen, len;
+ unsigned char *s = (unsigned char *) SvPV(sv, srclen);
+ UV retnum = 0;
+
+ if (offset < 0 || size < 1)
+ return retnum;
+ offset *= size; /* turn into bit offset */
+ len = (offset + size + 7) / 8; /* required number of bytes */
+ if (len > srclen) {
+ if (size <= 8)
+ retnum = 0;
+ else {
+ offset >>= 3; /* turn into byte offset */
+ if (size == 16) {
+ if (offset >= srclen)
+ retnum = 0;
+ else
+ retnum = (UV) s[offset] << 8;
+ }
+ else if (size == 32) {
+ if (offset >= srclen)
+ retnum = 0;
+ else if (offset + 1 >= srclen)
+ retnum =
+ ((UV) s[offset ] << 24);
+ else if (offset + 2 >= srclen)
+ retnum =
+ ((UV) s[offset ] << 24) +
+ ((UV) s[offset + 1] << 16);
+ else
+ retnum =
+ ((UV) s[offset ] << 24) +
+ ((UV) s[offset + 1] << 16) +
+ ( s[offset + 2] << 8);
+ }
+ else
+ Perl_croak(aTHX_ "Illegal number of bits in vec");
+ }
+ }
+ else if (size < 8)
+ retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
+ else {
+ offset >>= 3; /* turn into byte offset */
+ if (size == 8)
+ retnum = s[offset];
+ else if (size == 16)
+ retnum =
+ ((UV) s[offset] << 8) +
+ s[offset + 1];
+ else if (size == 32)
+ retnum =
+ ((UV) s[offset ] << 24) +
+ ((UV) s[offset + 1] << 16) +
+ ( s[offset + 2] << 8) +
+ s[offset + 3];
+ else
+ Perl_croak(aTHX_ "Illegal number of bits in vec");
+ }
+
+ return retnum;
+}
+
void
Perl_do_vecset(pTHX_ SV *sv)
{
@@ -704,7 +769,7 @@ Perl_do_vecset(pTHX_ SV *sv)
register I32 offset;
register I32 size;
register unsigned char *s;
- register unsigned long lval;
+ register UV lval;
I32 mask;
STRLEN targlen;
STRLEN len;
@@ -712,11 +777,12 @@ Perl_do_vecset(pTHX_ SV *sv)
if (!targ)
return;
s = (unsigned char*)SvPV_force(targ, targlen);
- lval = U_L(SvNV(sv));
+ lval = SvUV(sv);
offset = LvTARGOFF(sv);
size = LvTARGLEN(sv);
- len = (offset + size + 7) / 8;
+ offset *= size; /* turn into bit offset */
+ len = (offset + size + 7) / 8; /* required number of bytes */
if (len > targlen) {
s = (unsigned char*)SvGROW(targ, len + 1);
(void)memzero(s + targlen, len - targlen + 1);
@@ -727,12 +793,12 @@ Perl_do_vecset(pTHX_ SV *sv)
mask = (1 << size) - 1;
size = offset & 7;
lval &= mask;
- offset >>= 3;
+ offset >>= 3; /* turn into byte offset */
s[offset] &= ~(mask << size);
s[offset] |= lval << size;
}
else {
- offset >>= 3;
+ offset >>= 3; /* turn into byte offset */
if (size == 8)
s[offset] = lval & 255;
else if (size == 16) {