@@ -347,9 +347,19 @@ static inline int32_t ladder_get_data_int32(ladder_ctx_t *lctx, uint32_t r, uint
347347 return lctx -> output [mod ].QW [port ];
348348 }
349349 case LADDER_REGISTER_C :
350- return (int32_t ) lctx -> registers .C [val -> value .i32 ];
350+ uint32_t cv = lctx -> registers .C [val -> value .i32 ];
351+ if (cv > (uint32_t ) INT32_MAX ) { // Overflow check for unsigned to signed cast
352+ lctx -> ladder .last .err = LADDER_INS_ERR_OVERFLOW ;
353+ return 0 ;
354+ }
355+ return (int32_t ) cv ;
351356 case LADDER_REGISTER_T :
352- return (int32_t ) lctx -> timers [val -> value .i32 ].acc ; // Truncate u64 to i32 if needed
357+ uint64_t acc = lctx -> timers [val -> value .i32 ].acc ; // Truncate u64 to i32 if needed
358+ if (acc > (uint64_t ) INT32_MAX ) { // Overflow check consistent with ladder_get_data_value
359+ lctx -> ladder .last .err = LADDER_INS_ERR_OVERFLOW ;
360+ return 0 ;
361+ }
362+ return (int32_t ) acc ;
353363 case LADDER_REGISTER_D :
354364 return lctx -> registers .D [val -> value .i32 ];
355365 case LADDER_REGISTER_R :
@@ -458,3 +468,82 @@ static inline void ladder_set_data_value(ladder_ctx_t *ladder_ctx, uint32_t row,
458468 break ;
459469 }
460470}
471+
472+ static inline ladder_data_type_t get_effective_type (ladder_register_t reg_type ) {
473+ switch (reg_type ) {
474+ case LADDER_REGISTER_NONE :
475+ case LADDER_REGISTER_D :
476+ case LADDER_REGISTER_IW :
477+ case LADDER_REGISTER_QW :
478+ return LADDER_DATATYPE_I32 ;
479+ case LADDER_REGISTER_R :
480+ return LADDER_DATATYPE_REAL ;
481+ case LADDER_REGISTER_M :
482+ case LADDER_REGISTER_Q :
483+ case LADDER_REGISTER_I :
484+ case LADDER_REGISTER_Cd :
485+ case LADDER_REGISTER_Cr :
486+ case LADDER_REGISTER_Td :
487+ case LADDER_REGISTER_Tr :
488+ return LADDER_DATATYPE_BOOL ;
489+ case LADDER_REGISTER_C :
490+ case LADDER_REGISTER_T :
491+ return LADDER_DATATYPE_U32 ;
492+ case LADDER_REGISTER_S :
493+ return LADDER_DATATYPE_CSTR ;
494+ default :
495+ return LADDER_DATATYPE_BOOL ; // Default to bool for unknown
496+ }
497+ }
498+
499+ static inline float ladder_get_data_float (ladder_ctx_t * lctx , uint32_t r , uint32_t c , uint32_t i ) {
500+ if (lctx == NULL || lctx -> exec_network == NULL ) {
501+ return 0.0f ; // Safe default on invalid context
502+ }
503+ ladder_network_t * net = lctx -> exec_network ;
504+ if (r >= net -> rows || c >= net -> cols || i >= net -> cells [r ][c ].data_qty ) {
505+ return 0.0f ; // Safe default on OOB
506+ }
507+ ladder_register_t type = net -> cells [r ][c ].data [i ].type ;
508+ ladder_value_t * val = & net -> cells [r ][c ].data [i ];
509+
510+ switch (type ) {
511+ case LADDER_REGISTER_NONE :
512+ return (float ) val -> value .i32 ;
513+ case LADDER_REGISTER_M :
514+ case LADDER_REGISTER_Q :
515+ case LADDER_REGISTER_I :
516+ case LADDER_REGISTER_Cd :
517+ case LADDER_REGISTER_Cr :
518+ case LADDER_REGISTER_Td :
519+ case LADDER_REGISTER_Tr :
520+ return (float ) ladder_get_data_value (lctx , r , c , i );
521+ case LADDER_REGISTER_IW : {
522+ uint32_t mod = val -> value .mp .module ;
523+ uint8_t port = val -> value .mp .port ;
524+ if (mod >= lctx -> hw .io .fn_read_qty )
525+ return 0.0f ;
526+ return (float ) lctx -> input [mod ].IW [port ];
527+ }
528+ case LADDER_REGISTER_QW : {
529+ uint32_t mod = val -> value .mp .module ;
530+ uint8_t port = val -> value .mp .port ;
531+ if (mod >= lctx -> hw .io .fn_write_qty )
532+ return 0.0f ;
533+ return (float ) lctx -> output [mod ].QW [port ];
534+ }
535+ case LADDER_REGISTER_C :
536+ return (float ) lctx -> registers .C [val -> value .i32 ];
537+ case LADDER_REGISTER_T :
538+ return (float ) lctx -> timers [val -> value .i32 ].acc ;
539+ case LADDER_REGISTER_D :
540+ return (float ) lctx -> registers .D [val -> value .i32 ];
541+ case LADDER_REGISTER_R :
542+ return lctx -> registers .R [val -> value .i32 ];
543+ case LADDER_REGISTER_S :
544+ return 0.0f ; // Strings not numeric
545+ case LADDER_REGISTER_INV :
546+ default :
547+ return 0.0f ;
548+ }
549+ }
0 commit comments