7 /* nice simple functions */
9 int do_hbytes_clockincrement(ClientData cd, Tcl_Interp *ip,
10 HBytes_Var value, int change, int *result) {
14 if (change<-255 || change>255)
15 return staticerr(ip,"clockincrement change must be in range -255..255");
17 len= hbytes_len(value.hb);
18 data= hbytes_data(value.hb) + len;
19 while (len && change) {
24 else if (bv>255) change= +1;
33 int do_ulong_int2ul(ClientData cd, Tcl_Interp *ip, int v,
34 unsigned long *result) {
35 if (v<0) return staticerr(ip,"cannot convert -ve integer to ulong");
40 int do_ulong_ul2int(ClientData cd, Tcl_Interp *ip,
41 unsigned long v, int *result) {
42 if (v>INT_MAX) return staticerr(ip,"ulong too large to fit in an int");
47 int do_ulong_mask(ClientData cd, Tcl_Interp *ip,
48 unsigned long a, unsigned long b, unsigned long *result) {
53 int do_ulong_shift(ClientData cd, Tcl_Interp *ip, int right,
54 unsigned long v, int bits, unsigned long *result) {
55 if (bits > 32) return staticerr(ip,"shift out of range (32) bits");
56 *result= (bits==32 ? 0 :
57 right ? v >> bits : v << bits);
61 int do_ulong_compare(ClientData cd, Tcl_Interp *ip,
62 unsigned long a, unsigned long b,
64 *result= (a==b) ? -1 : (a < b) ? -1 : 1;
73 int (*reader_writer[2])(Tcl_Interp *ip, unsigned long *value_io,
74 int *ok_io, Tcl_Obj *arg);
77 static int bf_zero_read(Tcl_Interp *ip, unsigned long *value_io,
78 int *ok_io, Tcl_Obj *arg) {
79 if (*value_io) *ok_io= 0;
83 static int bf_zero_write(Tcl_Interp *ip, unsigned long *value_io,
84 int *ok_io, Tcl_Obj *arg) {
89 static int bf_ignore(Tcl_Interp *ip, unsigned long *value_io,
90 int *ok_io, Tcl_Obj *arg) {
94 static int bf_fixed_read(Tcl_Interp *ip, unsigned long *value_io,
95 int *ok_io, Tcl_Obj *arg) {
99 rc= pat_ulong(ip, arg, &ul); if (rc) return rc;
100 if (*value_io != ul) *ok_io= 0;
104 static int bf_ulong_write(Tcl_Interp *ip, unsigned long *value_io,
105 int *ok_io, Tcl_Obj *arg) {
109 rc= pat_ulong(ip, arg, &ul); if (rc) return rc;
114 static int bf_var_read(Tcl_Interp *ip, Tcl_Obj *varname, Tcl_Obj *val) {
116 rp= Tcl_ObjSetVar2(ip,varname,0,val,TCL_LEAVE_ERR_MSG);
117 if (!rp) return TCL_ERROR;
121 static int bf_ulong_read(Tcl_Interp *ip, unsigned long *value_io,
122 int *ok_io, Tcl_Obj *arg) {
123 return bf_var_read(ip,arg, ret_ulong(ip,*value_io));
126 static int bf_uint_write(Tcl_Interp *ip, unsigned long *value_io,
127 int *ok_io, Tcl_Obj *arg) {
129 rc= pat_int(ip, arg, &v); if (rc) return rc;
130 if (v<0) return staticerr(ip,"value for bitfield is -ve");
135 static int bf_uint_read(Tcl_Interp *ip, unsigned long *value_io,
136 int *ok_io, Tcl_Obj *arg) {
137 if (*value_io > INT_MAX)
138 return staticerr(ip,"value from bitfield exceeds INT_MAX");
139 return bf_var_read(ip,arg, ret_int(ip,*value_io));
142 #define BFT(t,a) { #t, a, { bf_read_##t, bf_write_##t } }
143 static const BitFieldType bitfieldtypes[]= {
144 { "zero", 0, { bf_zero_read, bf_zero_write } },
145 { "ignore", 0, { bf_ignore, bf_ignore } },
146 { "fixed", 1, { bf_fixed_read, bf_ulong_write } },
147 { "ulong", 1, { bf_ulong_read, bf_ulong_write } },
148 { "uint", 1, { bf_uint_read, bf_uint_write } },
152 static int do_bitfields(Tcl_Interp *ip, int writing, int *ok_r,
153 unsigned long *value_io,
154 int objc, Tcl_Obj *const *objv) {
155 const BitFieldType *ftype;
158 unsigned long value, sz_mask, this_mask, this_field;
165 rc= Tcl_GetIntFromObj(ip,*++objv,&sz); if (rc) return rc;
166 if (!--objc) return staticerr(ip,"wrong # args: missing bitfield type");
168 if (sz<0) return staticerr(ip,"bitfield size is -ve");
169 if (sz>pos) return staticerr(ip,"total size of bitfields >32");
173 sz_mask= ~(~0UL << sz);
174 this_mask= (sz_mask << pos);
175 this_field= (value & this_mask) >> pos;
177 ftype= enum_lookup_cached(ip,*++objv,bitfieldtypes,"bitfield type");
178 if (!ftype) return TCL_ERROR;
180 if (ftype->want_arg) {
182 return staticerr(ip,"wrong # args: missing arg for bitfield");
187 rc= ftype->reader_writer[writing](ip, &this_field, ok_r, arg);
190 if (!*ok_r) return TCL_OK;
192 if (this_field & ~sz_mask)
193 return staticerr(ip,"bitfield value has more bits than bitfield");
196 value |= (this_field << pos);
200 return staticerr(ip,"bitfield sizes add up to <32");
206 int do_ulong_bitfields2ul(ClientData cd, Tcl_Interp *ip,
208 int objc, Tcl_Obj *const *objv,
209 unsigned long *result) {
213 rc= do_bitfields(ip,1,&ok,result,objc,objv);
218 int do_ulong_ul2bitfields(ClientData cd, Tcl_Interp *ip,
220 int objc, Tcl_Obj *const *objv,
222 return do_bitfields(ip,0,result,&value,objc,objv);
225 /* conversion to/from hbytes */
228 DO_SIZE(ulong, 4, 0xffffffffUL, \
233 DO_SIZE(ushort, 2, 0x0000ffffUL, \
237 #define DO_BYTE(index,shift) (data[index] << shift) |
238 #define DO_SIZE(ulongint, len, max, bytes) \
239 int do_hbytes_h2##ulongint(ClientData cd, Tcl_Interp *ip, \
240 HBytes_Value hex, unsigned long *result) { \
242 if (hbytes_len(&hex) != len) \
243 return staticerr(ip, #ulongint " must be " #len " bytes"); \
244 data= hbytes_data(&hex); \
245 *result= (bytes 0); \
252 #define DO_BYTE(index,shift) data[index]= (value >> shift);
253 #define DO_SIZE(ulongint, len, max, bytes) \
254 int do_hbytes_##ulongint##2h(ClientData cd, Tcl_Interp *ip, \
255 unsigned long value, HBytes_Value *result) { \
257 if (value > max) return staticerr(ip, #ulongint " too big"); \
258 data= hbytes_arrayspace(result,len); \
268 int pat_ulong(Tcl_Interp *ip, Tcl_Obj *o, unsigned long *val) {
271 rc= Tcl_ConvertToType(ip,o,&ulong_type);
273 *val= *(const unsigned long*)&o->internalRep.longValue;
277 Tcl_Obj *ret_ulong(Tcl_Interp *ip, unsigned long val) {
281 Tcl_InvalidateStringRep(o);
282 *(unsigned long*)&o->internalRep.longValue= val;
283 o->typePtr= &ulong_type;
289 static void ulong_t_free(Tcl_Obj *o) { }
291 static void ulong_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
292 dup->internalRep= src->internalRep;
293 dup->typePtr= &ulong_type;
296 static void ulong_t_ustr(Tcl_Obj *o) {
300 val= *(const unsigned long*)&o->internalRep.longValue;
302 assert(val <= 0xffffffffUL);
303 snprintf(buf,sizeof(buf), "0x%08lx", val);
305 obj_updatestr_vstringls(o, buf, sizeof(buf)-1, (char*)0);
308 static int ulong_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
313 str= Tcl_GetString(o);
315 if (str[0]=='0' && str[1]=='b' && str[2]) {
316 ul= strtoul(str+2,&ep,2);
318 ul= strtoul(str,&ep,0);
320 if (*ep || errno) return staticerr(ip, "bad unsigned long value");
323 *(unsigned long*)&o->internalRep.longValue= ul;
327 Tcl_ObjType ulong_type = {
329 ulong_t_free, ulong_t_dup, ulong_t_ustr, ulong_t_sfa