diff options
Diffstat (limited to 'do/vec')
-rw-r--r-- | do/vec | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/do/vec b/do/vec new file mode 100644 index 0000000000..37101adc28 --- /dev/null +++ b/do/vec @@ -0,0 +1,58 @@ +int +do_vec(lvalue,astr,arglast) +int lvalue; +STR *astr; +int *arglast; +{ + STR **st = stack->ary_array; + int sp = arglast[0]; + register STR *TARG = st[++sp]; + register int offset = (int)str_gnum(st[++sp]); + register int size = (int)str_gnum(st[++sp]); + unsigned char *s = (unsigned char*)str_get(TARG); + unsigned long retnum; + int len; + + sp = arglast[1]; + offset *= size; /* turn into bit offset */ + len = (offset + size + 7) / 8; + if (offset < 0 || size < 1) + retnum = 0; + else if (!lvalue && len > TARG->str_cur) + retnum = 0; + else { + if (len > TARG->str_cur) { + STR_GROW(TARG,len); + (void)memzero(TARG->str_ptr + TARG->str_cur, len - TARG->str_cur); + TARG->str_cur = len; + } + s = (unsigned char*)str_get(TARG); + if (size < 8) + retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1); + else { + offset >>= 3; + if (size == 8) + retnum = s[offset]; + else if (size == 16) + retnum = ((unsigned long) s[offset] << 8) + s[offset+1]; + else if (size == 32) + retnum = ((unsigned long) s[offset] << 24) + + ((unsigned long) s[offset + 1] << 16) + + (s[offset + 2] << 8) + s[offset+3]; + } + + if (lvalue) { /* it's an lvalue! */ + struct lstring *lstr = (struct lstring*)astr; + + astr->str_magic = TARG; + st[sp]->str_rare = 'v'; + lstr->lstr_offset = offset; + lstr->lstr_len = size; + } + } + + str_numset(astr,(double)retnum); + st[sp] = astr; + return sp; +} + |