summaryrefslogtreecommitdiff
path: root/do/vec
diff options
context:
space:
mode:
Diffstat (limited to 'do/vec')
-rw-r--r--do/vec58
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;
+}
+