@@ -91,7 +91,6 @@ int rtapi_app_main(void){
9191 // Parse the config string
9292 for (i = 0 ; i < demux -> num_insts ; i ++ ) {
9393 char c ;
94- int s , p = 0 ;
9594 demux_inst_t * inst = & demux -> insts [i ];
9695 inst -> in_type = -1 ;
9796 inst -> out_type = -1 ;
@@ -176,21 +175,32 @@ int rtapi_app_main(void){
176175 " failed\n" );
177176 goto fail0 ;
178177 }
178+
179179 // Input pins
180-
181- // if the demux size is a power of 2 then create the bit inputs
182- s = inst -> size ;
183- for (inst -> num_bits = 1 ; (!((s >>= 1 ) & 1 )); inst -> num_bits ++ );
184- if (s != 1 ){
185- inst -> num_bits = 0 ;
186- } else { //make the bit pins
187- inst -> sel_bit = hal_malloc (inst -> num_bits * sizeof (* inst -> sel_bit ));
188- for (p = 0 ; p < inst -> num_bits ; p ++ ) {
189- retval = hal_pin_new_bool (comp_id , HAL_IN , & inst -> sel_bit [p ], 0 ,
190- "demux-gen.%02i.sel-bit-%02i" , i , p );
191- if (retval != 0 ) {
192- goto fail0 ;
193- }
180+ inst -> num_bits = 0 ;
181+ // Count the position of the highest bit set in inst->size-1.
182+ // We know that inst->size >= 2 from tests above. This will work
183+ // for any value, regardless whether it is a power of two or not
184+ // because of the -1 on the size and counting until all bits
185+ // have become zero.
186+ for (int s = inst -> size - 1 ; 0 != s ; inst -> num_bits ++ ) {
187+ s >>= 1 ;
188+ }
189+ if (inst -> num_bits < 1 ) {
190+ // This is a safety guard. It should never happen.
191+ rtapi_print_msg (RTAPI_MSG_ERR , "demux_generic: INTERNAL ERROR: num_bits == 0\n" );
192+ goto fail0 ;
193+ }
194+ inst -> sel_bit = hal_malloc (inst -> num_bits * sizeof (* inst -> sel_bit ));
195+ if (!inst -> sel_bit ) {
196+ rtapi_print_msg (RTAPI_MSG_ERR , "demux_generic: ERROR: out of HAL memory\n" );
197+ goto fail0 ;
198+ }
199+ for (int p = 0 ; p < inst -> num_bits ; p ++ ) {
200+ retval = hal_pin_new_bool (comp_id , HAL_IN , & inst -> sel_bit [p ], 0 ,
201+ "demux-gen.%02i.sel-bit-%02i" , i , p );
202+ if (retval != 0 ) {
203+ goto fail0 ;
194204 }
195205 }
196206
@@ -240,7 +250,7 @@ int rtapi_app_main(void){
240250
241251 //output pins
242252 inst -> outputs = hal_malloc (inst -> size * sizeof (* inst -> outputs ));
243- for (p = 0 ; p < inst -> size ; p ++ ) {
253+ for (int p = 0 ; p < inst -> size ; p ++ ) {
244254 retval = rtapi_snprintf (hal_name , sizeof (hal_name ),
245255 "demux-gen.%02i.out-%s-%02i" , i , types [inst -> out_type ], p );
246256 if (retval > HAL_NAME_LEN ) {
@@ -262,40 +272,37 @@ int rtapi_app_main(void){
262272 hal_ready (comp_id );
263273 return 0 ;
264274
265- fail0 :
275+ fail0 :
266276 hal_exit (comp_id );
267277 return -1 ;
268-
269278}
270279
271280// From 'f' to 't' conversion
272281#define FT (f ,t ) ((((f) & 0x0f) << 4) + ((t) & 0x0f))
273282
274283void write_fp (void * arg , long period ) {
275284 demux_inst_t * inst = arg ;
276- int i = 0 ;
277- rtapi_uint s = 0 ;
278- if (inst -> num_bits > 0 ) {
279- while (i < inst -> num_bits ) {
280- s += (hal_get_bool (inst -> sel_bit [i ]) != 0 ) << i ;
281- i ++ ;
282- }
285+ rtapi_sint s = 0 ;
286+ for (int i = 0 ; i < inst -> num_bits ; i ++ ) {
287+ s += (rtapi_sint )hal_get_bool (inst -> sel_bit [i ]) << i ;
283288 }
284289 // if you document it, it's not a bug, it's a feature. Might even be useful
285- s += hal_get_uint (inst -> sel_int );
290+ rtapi_uint u = hal_get_uint (inst -> sel_int );
291+ // The calculation here is to prevent signed/unsigned overflow.
292+ s += u > MAX_SIZE ? MAX_SIZE : u ;
286293
287294 if (hal_get_bool (inst -> suppress ) && s == 0 )
288295 return ;
289296 rtapi_uint timer = hal_get_uint (inst -> timer );
290- if (s != hal_get_uint (inst -> selection ) && timer < hal_get_uint (inst -> debounce )) {
297+ if (( rtapi_uint ) s != hal_get_uint (inst -> selection ) && timer < hal_get_uint (inst -> debounce )) {
291298 hal_set_uint (inst -> timer , timer + period / 1000 );
292299 return ;
293300 }
294301
295302 hal_set_uint (inst -> selection , s );
296303 hal_set_uint (inst -> timer , 0 );
297304
298- if (( rtapi_sint ) s >= inst -> size )
305+ if (s >= inst -> size )
299306 s = inst -> size - 1 ;
300307
301308 switch (FT (inst -> in_type , inst -> out_type )) {
@@ -370,6 +377,6 @@ void write_fp(void *arg, long period) {
370377}
371378
372379void rtapi_app_exit (void ){
373- // everything is hal_malloc-ed which saves a lot of cleanup here
374- hal_exit (comp_id );
380+ // everything is hal_malloc-ed which saves a lot of cleanup here
381+ hal_exit (comp_id );
375382}
0 commit comments