37101adc280a41b338901daff1df1f721d17a93c
[perl.git] / do / vec
1 int
2 do_vec(lvalue,astr,arglast)
3 int lvalue;
4 STR *astr;
5 int *arglast;
6 {
7     STR **st = stack->ary_array;
8     int sp = arglast[0];
9     register STR *TARG = st[++sp];
10     register int offset = (int)str_gnum(st[++sp]);
11     register int size = (int)str_gnum(st[++sp]);
12     unsigned char *s = (unsigned char*)str_get(TARG);
13     unsigned long retnum;
14     int len;
15
16     sp = arglast[1];
17     offset *= size;             /* turn into bit offset */
18     len = (offset + size + 7) / 8;
19     if (offset < 0 || size < 1)
20         retnum = 0;
21     else if (!lvalue && len > TARG->str_cur)
22         retnum = 0;
23     else {
24         if (len > TARG->str_cur) {
25             STR_GROW(TARG,len);
26             (void)memzero(TARG->str_ptr + TARG->str_cur, len - TARG->str_cur);
27             TARG->str_cur = len;
28         }
29         s = (unsigned char*)str_get(TARG);
30         if (size < 8)
31             retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1);
32         else {
33             offset >>= 3;
34             if (size == 8)
35                 retnum = s[offset];
36             else if (size == 16)
37                 retnum = ((unsigned long) s[offset] << 8) + s[offset+1];
38             else if (size == 32)
39                 retnum = ((unsigned long) s[offset] << 24) +
40                         ((unsigned long) s[offset + 1] << 16) +
41                         (s[offset + 2] << 8) + s[offset+3];
42         }
43
44         if (lvalue) {                      /* it's an lvalue! */
45             struct lstring *lstr = (struct lstring*)astr;
46
47             astr->str_magic = TARG;
48             st[sp]->str_rare = 'v';
49             lstr->lstr_offset = offset;
50             lstr->lstr_len = size;
51         }
52     }
53
54     str_numset(astr,(double)retnum);
55     st[sp] = astr;
56     return sp;
57 }
58