stage4/generate_c/generate_c.cc
changeset 1078 81e2a100db14
parent 1077 b37de6a9ad7f
child 1081 d8ed548e2f9b
equal deleted inserted replaced
1077:b37de6a9ad7f 1078:81e2a100db14
   545 /***********************************************************************/
   545 /***********************************************************************/
   546 
   546 
   547 #define MILLISECOND 1
   547 #define MILLISECOND 1
   548 #define SECOND 1000 * MILLISECOND
   548 #define SECOND 1000 * MILLISECOND
   549 
   549 
       
   550 #define ULL_MAX std::numeric_limits<unsigned long long>::max()
       
   551 
       
   552 /* unsigned long long -> multiply and add : time_var += interval * multiplier  */
       
   553 /*  note: multiplier must be <> 0 due to overflow test                         */
       
   554 #define ULL_MUL_ADD(time_var, interval, multiplier, overflow_flag) {                       \
       
   555     /* Test overflow on MUL by pre-condition: If (ULL_MAX / a) < b => overflow! */         \
       
   556     overflow_flag |= ((ULL_MAX / (multiplier)) < GET_CVALUE(uint64, interval));            \
       
   557     /* Test overflow on ADD by pre-condition: If (ULL_MAX - a) < b => overflow! */         \
       
   558     overflow_flag |= ((ULL_MAX - (GET_CVALUE(uint64, interval) * multiplier)) < time_var); \
       
   559     time_var += GET_CVALUE(uint64, interval) * (multiplier);                               \
       
   560 }
       
   561 
       
   562 /* long double -> multiply and add : time_var += interval * multiplier  */
       
   563 #define LDB_MUL_ADD(time_var, interval, multiplier) {  \
       
   564     time_var += GET_CVALUE(real64, interval) * (multiplier);               \
       
   565 }
       
   566 
       
   567 
   550 unsigned long long calculate_time(symbol_c *symbol) {
   568 unsigned long long calculate_time(symbol_c *symbol) {
   551   if (NULL == symbol) return 0;
   569   if (NULL == symbol) return 0;
   552   
   570   
   553   interval_c *interval = dynamic_cast<interval_c *>(symbol);
   571   interval_c *interval = dynamic_cast<interval_c *>(symbol);
   554   duration_c *duration = dynamic_cast<duration_c *>(symbol);
   572   duration_c *duration = dynamic_cast<duration_c *>(symbol);
   565 
   583 
   566   if (NULL != interval) {
   584   if (NULL != interval) {
   567     /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
   585     /* SYM_REF5(interval_c, days, hours, minutes, seconds, milliseconds) */
   568       unsigned long long int time_ull = 0; 
   586       unsigned long long int time_ull = 0; 
   569       long double            time_ld  = 0;
   587       long double            time_ld  = 0;
       
   588       bool                   ovflow   = false;
   570       
   589       
   571       if (NULL != interval->milliseconds) {
   590       if (NULL != interval->milliseconds) {
   572         if      (VALID_CVALUE( int64, interval->milliseconds) &&           GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive!
   591         if      (VALID_CVALUE( int64, interval->milliseconds) &&           GET_CVALUE( int64, interval->milliseconds) < 0) ERROR; // interval elements should always be positive!
   573         if      (VALID_CVALUE( int64, interval->milliseconds)) time_ull += GET_CVALUE( int64, interval->milliseconds) * MILLISECOND;
   592         if      (VALID_CVALUE(uint64, interval->milliseconds)) ULL_MUL_ADD(time_ull, interval->milliseconds,  MILLISECOND, ovflow)
   574         else if (VALID_CVALUE(uint64, interval->milliseconds)) time_ull += GET_CVALUE(uint64, interval->milliseconds) * MILLISECOND;
   593         else if (VALID_CVALUE(real64, interval->milliseconds)) LDB_MUL_ADD(time_ld , interval->milliseconds,  MILLISECOND)
   575         else if (VALID_CVALUE(real64, interval->milliseconds)) time_ld  += GET_CVALUE(real64, interval->milliseconds) * MILLISECOND;
       
   576         else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value!
   594         else ERROR; // if (NULL != interval->milliseconds) is true, then it must have a valid constant value!
   577       }
   595       }
   578    
   596    
   579       if (NULL != interval->seconds     ) {
   597       if (NULL != interval->seconds     ) {
   580         if      (VALID_CVALUE( int64, interval->seconds     ) &&           GET_CVALUE( int64, interval->seconds     ) < 0) ERROR; // interval elements should always be positive!
   598         if      (VALID_CVALUE( int64, interval->seconds     ) &&           GET_CVALUE( int64, interval->seconds     ) < 0) ERROR; // interval elements should always be positive!
   581         if      (VALID_CVALUE( int64, interval->seconds     )) time_ull += GET_CVALUE( int64, interval->seconds     ) * SECOND;
   599         if      (VALID_CVALUE(uint64, interval->seconds     )) ULL_MUL_ADD(time_ull, interval->seconds,       SECOND, ovflow)
   582         else if (VALID_CVALUE(uint64, interval->seconds     )) time_ull += GET_CVALUE(uint64, interval->seconds     ) * SECOND;
   600         else if (VALID_CVALUE(real64, interval->seconds     )) LDB_MUL_ADD(time_ld , interval->seconds,       SECOND)
   583         else if (VALID_CVALUE(real64, interval->seconds     )) time_ld  += GET_CVALUE(real64, interval->seconds     ) * SECOND;
       
   584         else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value!
   601         else ERROR; // if (NULL != interval->seconds) is true, then it must have a valid constant value!
   585       }
   602       }
   586 
   603 
   587       if (NULL != interval->minutes     ) {
   604       if (NULL != interval->minutes     ) {
   588         if      (VALID_CVALUE( int64, interval->minutes     ) &&           GET_CVALUE( int64, interval->minutes     ) < 0) ERROR; // interval elements should always be positive!
   605         if      (VALID_CVALUE( int64, interval->minutes     ) &&           GET_CVALUE( int64, interval->minutes     ) < 0) ERROR; // interval elements should always be positive!
   589         if      (VALID_CVALUE( int64, interval->minutes     )) time_ull += GET_CVALUE( int64, interval->minutes     ) * SECOND * 60;
   606         if      (VALID_CVALUE(uint64, interval->minutes     )) ULL_MUL_ADD(time_ull, interval->minutes,       SECOND * 60, ovflow)
   590         else if (VALID_CVALUE(uint64, interval->minutes     )) time_ull += GET_CVALUE(uint64, interval->minutes     ) * SECOND * 60;
   607         else if (VALID_CVALUE(real64, interval->minutes     )) LDB_MUL_ADD(time_ld , interval->minutes,       SECOND * 60)
   591         else if (VALID_CVALUE(real64, interval->minutes     )) time_ld  += GET_CVALUE(real64, interval->minutes     ) * SECOND * 60;
       
   592         else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value!
   608         else ERROR; // if (NULL != interval->minutes) is true, then it must have a valid constant value!
   593       }
   609       }
   594 
   610 
   595       if (NULL != interval->hours       ) {
   611       if (NULL != interval->hours       ) {
   596         if      (VALID_CVALUE( int64, interval->hours       ) &&           GET_CVALUE( int64, interval->hours       ) < 0) ERROR; // interval elements should always be positive!
   612         if      (VALID_CVALUE( int64, interval->hours       ) &&           GET_CVALUE( int64, interval->hours       ) < 0) ERROR; // interval elements should always be positive!
   597         if      (VALID_CVALUE( int64, interval->hours       )) time_ull += GET_CVALUE( int64, interval->hours       ) * SECOND * 60 * 60;
   613         if      (VALID_CVALUE(uint64, interval->hours       )) ULL_MUL_ADD(time_ull, interval->hours,         SECOND * 60 * 60, ovflow)
   598         else if (VALID_CVALUE(uint64, interval->hours       )) time_ull += GET_CVALUE(uint64, interval->hours       ) * SECOND * 60 * 60;
   614         else if (VALID_CVALUE(real64, interval->hours       )) LDB_MUL_ADD(time_ld , interval->hours,         SECOND * 60 * 60)
   599         else if (VALID_CVALUE(real64, interval->hours       )) time_ld  += GET_CVALUE(real64, interval->hours       ) * SECOND * 60 * 60;
       
   600         else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value!
   615         else ERROR; // if (NULL != interval->hours) is true, then it must have a valid constant value!
   601       }
   616       }
   602 
   617 
   603       if (NULL != interval->days        ) {
   618       if (NULL != interval->days        ) {
   604         if      (VALID_CVALUE( int64, interval->days        ) &&           GET_CVALUE( int64, interval->days        ) < 0) ERROR; // interval elements should always be positive!
   619         if      (VALID_CVALUE( int64, interval->days        ) &&           GET_CVALUE( int64, interval->days        ) < 0) ERROR; // interval elements should always be positive!
   605         if      (VALID_CVALUE( int64, interval->days        )) time_ull += GET_CVALUE( int64, interval->days        ) * SECOND * 60 * 60 * 24;
   620         if      (VALID_CVALUE(uint64, interval->days        )) ULL_MUL_ADD(time_ull, interval->days,          SECOND * 60 * 60 * 24, ovflow)
   606         else if (VALID_CVALUE(uint64, interval->days        )) time_ull += GET_CVALUE(uint64, interval->days        ) * SECOND * 60 * 60 * 24;
   621         else if (VALID_CVALUE(real64, interval->days        )) LDB_MUL_ADD(time_ld , interval->days,          SECOND * 60 * 60 * 24)
   607         else if (VALID_CVALUE(real64, interval->days        )) time_ld  += GET_CVALUE(real64, interval->days        ) * SECOND * 60 * 60 * 24;
       
   608         else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value!
   622         else ERROR; // if (NULL != interval->days) is true, then it must have a valid constant value!
   609       }
   623       }
   610 
   624 
       
   625       /* Test overflow on ADD by pre-condition: If (ULL_MAX - a) < b => overflow! */
       
   626       ovflow |= ((ULL_MAX - time_ull) < (unsigned long long)time_ld);
   611       time_ull += time_ld;
   627       time_ull += time_ld;
       
   628       
       
   629       if (ovflow)
       
   630         STAGE4_ERROR(symbol, symbol, "Internal overflow calculating task interval (must be <= 49 days).");
       
   631 
   612       return time_ull;
   632       return time_ull;
   613   };
   633   };
   614   ERROR; // should never reach this point!
   634   ERROR; // should never reach this point!
   615   return 0; // humour the compiler!
   635   return 0; // humour the compiler!
   616 }
   636 }