lib/iec_std_lib.h
changeset 258 d7d92b2f87e9
parent 217 f5dfadf5de54
child 254 28bd86c56793
child 280 69a307407f7b
equal deleted inserted replaced
257:90782e241346 258:d7d92b2f87e9
    77 #define __LREAL_LITERAL(value) __literal(LREAL,value,__64b_sufix)
    77 #define __LREAL_LITERAL(value) __literal(LREAL,value,__64b_sufix)
    78 #define __TIME_LITERAL(value) __literal(TIME,value,)
    78 #define __TIME_LITERAL(value) __literal(TIME,value,)
    79 #define __DATE_LITERAL(value) __literal(DATE,value,)
    79 #define __DATE_LITERAL(value) __literal(DATE,value,)
    80 #define __TOD_LITERAL(value) __literal(TOD,value,)
    80 #define __TOD_LITERAL(value) __literal(TOD,value,)
    81 #define __DT_LITERAL(value) __literal(DT,value,)
    81 #define __DT_LITERAL(value) __literal(DT,value,)
    82 #define __STRING_LITERAL(value) __literal(STRING,value,)
    82 #define __STRING_LITERAL(count,value) (STRING){count,value}
    83 #define __BYTE_LITERAL(value) __literal(BYTE,value,)
    83 #define __BYTE_LITERAL(value) __literal(BYTE,value,)
    84 #define __WORD_LITERAL(value) __literal(WORD,value,)
    84 #define __WORD_LITERAL(value) __literal(WORD,value,)
    85 #define __DWORD_LITERAL(value) __literal(DWORD,value,__32b_sufix)
    85 #define __DWORD_LITERAL(value) __literal(DWORD,value,__32b_sufix)
    86 #define __LWORD_LITERAL(value) __literal(LWORD,value,__32b_sufix)
    86 #define __LWORD_LITERAL(value) __literal(LWORD,value,__32b_sufix)
    87 
    87 
   183 }
   183 }
   184 
   184 
   185 static inline struct timespec __date_to_timespec(int day, int month, int year) {
   185 static inline struct timespec __date_to_timespec(int day, int month, int year) {
   186   struct timespec ts;
   186   struct timespec ts;
   187   struct tm broken_down_time;
   187   struct tm broken_down_time;
       
   188   time_t epoch_seconds;
   188 
   189 
   189   broken_down_time.tm_sec = 0;
   190   broken_down_time.tm_sec = 0;
   190   broken_down_time.tm_min = 0;
   191   broken_down_time.tm_min = 0;
   191   broken_down_time.tm_hour = 0;
   192   broken_down_time.tm_hour = 0;
   192   broken_down_time.tm_mday = day;  /* day of month, from 1 to 31 */
   193   broken_down_time.tm_mday = day;  /* day of month, from 1 to 31 */
   193   broken_down_time.tm_mon = month - 1;   /* month since January, in the range 0 to 11 */
   194   broken_down_time.tm_mon = month - 1;   /* month since January, in the range 0 to 11 */
   194   broken_down_time.tm_year = year - 1900;  /* number of years since 1900 */
   195   broken_down_time.tm_year = year - 1900;  /* number of years since 1900 */
   195 
   196 
   196   time_t epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */
   197   epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */
   197 
   198 
   198   if ((time_t)(-1) == epoch_seconds)
   199   if ((time_t)(-1) == epoch_seconds)
   199     IEC_error();
   200     IEC_error();
   200 
   201 
   201   ts.tv_sec = epoch_seconds;
   202   ts.tv_sec = epoch_seconds;
   204   return ts;
   205   return ts;
   205 }
   206 }
   206 
   207 
   207 static inline struct timespec __dt_to_timespec(double seconds,  double minutes, double hours, int day, int month, int year) {
   208 static inline struct timespec __dt_to_timespec(double seconds,  double minutes, double hours, int day, int month, int year) {
   208   struct timespec ts;
   209   struct timespec ts;
       
   210   struct tm broken_down_time;
       
   211   time_t epoch_seconds;
   209 
   212 
   210   long double total_sec = (hours*60 + minutes)*60 + seconds;
   213   long double total_sec = (hours*60 + minutes)*60 + seconds;
   211   ts.tv_sec = (long int)total_sec;
   214   ts.tv_sec = (long int)total_sec;
   212   ts.tv_nsec = (long int)((total_sec - ts.tv_sec)*1e9);
   215   ts.tv_nsec = (long int)((total_sec - ts.tv_sec)*1e9);
   213 
   216 
   214   struct tm broken_down_time;
       
   215   broken_down_time.tm_sec = 0;
   217   broken_down_time.tm_sec = 0;
   216   broken_down_time.tm_min = 0;
   218   broken_down_time.tm_min = 0;
   217   broken_down_time.tm_hour = 0;
   219   broken_down_time.tm_hour = 0;
   218   broken_down_time.tm_mday = day;  /* day of month, from 1 to 31 */
   220   broken_down_time.tm_mday = day;  /* day of month, from 1 to 31 */
   219   broken_down_time.tm_mon = month - 1;   /* month since January, in the range 0 to 11 */
   221   broken_down_time.tm_mon = month - 1;   /* month since January, in the range 0 to 11 */
   220   broken_down_time.tm_year = year - 1900;  /* number of years since 1900 */
   222   broken_down_time.tm_year = year - 1900;  /* number of years since 1900 */
   221 
   223 
   222   time_t epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */
   224   epoch_seconds = mktime(&broken_down_time); /* determine number of seconds since the epoch, i.e. Jan 1st 1970 */
   223   if ((time_t)(-1) == epoch_seconds)
   225   if ((time_t)(-1) == epoch_seconds)
   224     IEC_error();
   226     IEC_error();
   225 
   227 
   226   ts.tv_sec += epoch_seconds;
   228   ts.tv_sec += epoch_seconds;
   227   if (ts.tv_sec < epoch_seconds)
   229   if (ts.tv_sec < epoch_seconds)
   321 static inline __strlen_t __len(EN_ENO_PARAMS, STRING IN){
   323 static inline __strlen_t __len(EN_ENO_PARAMS, STRING IN){
   322     TEST_EN(UINT)
   324     TEST_EN(UINT)
   323     return IN.len;
   325     return IN.len;
   324 }
   326 }
   325 static inline STRING __left(EN_ENO_PARAMS, STRING IN, __strlen_t L){
   327 static inline STRING __left(EN_ENO_PARAMS, STRING IN, __strlen_t L){
       
   328     STRING res;
   326     TEST_EN_COND(STRING, L < 0)
   329     TEST_EN_COND(STRING, L < 0)
   327     STRING res = __INIT_STRING;
   330     res = __INIT_STRING;
   328     L = L < IN.len ? L : IN.len;
   331     L = L < IN.len ? L : IN.len;
   329     memcpy(&res.body, &IN.body, L);
   332     memcpy(&res.body, &IN.body, L);
   330     res.len = L;
   333     res.len = L;
   331     return res;
   334     return res;
   332 }
   335 }
   333 static inline STRING __right(EN_ENO_PARAMS, STRING IN, __strlen_t L){
   336 static inline STRING __right(EN_ENO_PARAMS, STRING IN, __strlen_t L){
       
   337     STRING res;
   334     TEST_EN_COND(STRING, L < 0)
   338     TEST_EN_COND(STRING, L < 0)
   335     STRING res = __INIT_STRING;
   339     res = __INIT_STRING;
   336     L = L < IN.len ? L : IN.len;
   340     L = L < IN.len ? L : IN.len;
   337     memcpy(&res.body, &IN.body[IN.len - L], L);
   341     memcpy(&res.body, &IN.body[IN.len - L], L);
   338     res.len = L;
   342     res.len = L;
   339     return res;
   343     return res;
   340 }
   344 }
   341 static inline STRING __mid(EN_ENO_PARAMS, STRING IN, __strlen_t L, __strlen_t P){
   345 static inline STRING __mid(EN_ENO_PARAMS, STRING IN, __strlen_t L, __strlen_t P){
       
   346     STRING res;
   342     TEST_EN_COND(STRING, L < 0 || P < 0)
   347     TEST_EN_COND(STRING, L < 0 || P < 0)
   343     STRING res = __INIT_STRING;
   348     res = __INIT_STRING;
   344     if(P <= IN.len){
   349     if(P <= IN.len){
   345 	    P -= 1; /* now can be used as [index]*/
   350 	    P -= 1; /* now can be used as [index]*/
   346 	    L = L + P <= IN.len ? L : IN.len - P;
   351 	    L = L + P <= IN.len ? L : IN.len - P;
   347 	    memcpy(&res.body, &IN.body[P] , L);
   352 	    memcpy(&res.body, &IN.body[P] , L);
   348         res.len = L;
   353         res.len = L;
   349     }
   354     }
   350     return res;
   355     return res;
   351 }
   356 }
   352 static inline STRING __concat(EN_ENO_PARAMS, UINT param_count, ...){
   357 static inline STRING __concat(EN_ENO_PARAMS, UINT param_count, ...){
       
   358   UINT i;
       
   359   STRING res;
       
   360   va_list ap;
       
   361   __strlen_t charcount;
   353   TEST_EN(STRING)
   362   TEST_EN(STRING)
   354   va_list ap;
   363   charcount = 0;
   355   UINT i;
   364   res = __INIT_STRING;
   356   __strlen_t charcount = 0;
       
   357   STRING res = __INIT_STRING;
       
   358 
   365 
   359   va_start (ap, param_count);         /* Initialize the argument list.  */
   366   va_start (ap, param_count);         /* Initialize the argument list.  */
   360 
   367 
   361   for (i = 0; i < param_count && charcount < STR_MAX_LEN; i++)
   368   for (i = 0; i < param_count && charcount < STR_MAX_LEN; i++)
   362   {
   369   {
   371 
   378 
   372   va_end (ap);                  /* Clean up.  */
   379   va_end (ap);                  /* Clean up.  */
   373   return res;
   380   return res;
   374 }
   381 }
   375 static inline STRING __insert(EN_ENO_PARAMS, STRING IN1, STRING IN2, __strlen_t P){
   382 static inline STRING __insert(EN_ENO_PARAMS, STRING IN1, STRING IN2, __strlen_t P){
       
   383     STRING res;
       
   384     __strlen_t to_copy;
   376     TEST_EN_COND(STRING, P < 0)
   385     TEST_EN_COND(STRING, P < 0)
   377     STRING res = __INIT_STRING;
   386     res = __INIT_STRING;
   378     __strlen_t to_copy;
       
   379 
   387 
   380     to_copy = P > IN1.len ? IN1.len : P - 1;
   388     to_copy = P > IN1.len ? IN1.len : P - 1;
   381     memcpy(&res.body, &IN1.body , to_copy);
   389     memcpy(&res.body, &IN1.body , to_copy);
   382     P = res.len = to_copy;
   390     P = res.len = to_copy;
   383 
   391 
   390     res.len += to_copy;
   398     res.len += to_copy;
   391 
   399 
   392     return res;
   400     return res;
   393 }
   401 }
   394 static inline STRING __delete(EN_ENO_PARAMS, STRING IN, __strlen_t L, __strlen_t P){
   402 static inline STRING __delete(EN_ENO_PARAMS, STRING IN, __strlen_t L, __strlen_t P){
       
   403     STRING res;
       
   404     __strlen_t to_copy;
   395     TEST_EN_COND(STRING, L < 0 || P < 0)
   405     TEST_EN_COND(STRING, L < 0 || P < 0)
   396     STRING res = __INIT_STRING;
   406     res = __INIT_STRING;
   397     __strlen_t to_copy;
       
   398 
   407 
   399     to_copy = P > IN.len ? IN.len : P-1;
   408     to_copy = P > IN.len ? IN.len : P-1;
   400     memcpy(&res.body, &IN.body , to_copy);
   409     memcpy(&res.body, &IN.body , to_copy);
   401     P = res.len = to_copy;
   410     P = res.len = to_copy;
   402 
   411 
   407     }
   416     }
   408 
   417 
   409     return res;
   418     return res;
   410 }
   419 }
   411 static inline STRING __replace(EN_ENO_PARAMS, STRING IN1, STRING IN2, __strlen_t L, __strlen_t P){
   420 static inline STRING __replace(EN_ENO_PARAMS, STRING IN1, STRING IN2, __strlen_t L, __strlen_t P){
       
   421     STRING res;
       
   422     __strlen_t to_copy;
   412     TEST_EN_COND(STRING, L < 0 || P < 0)
   423     TEST_EN_COND(STRING, L < 0 || P < 0)
   413     STRING res = __INIT_STRING;
   424     res = __INIT_STRING;
   414     __strlen_t to_copy;
       
   415 
   425 
   416     to_copy = P > IN1.len ? IN1.len : P-1;
   426     to_copy = P > IN1.len ? IN1.len : P-1;
   417     memcpy(&res.body, &IN1.body , to_copy);
   427     memcpy(&res.body, &IN1.body , to_copy);
   418     P = res.len = to_copy;
   428     P = res.len = to_copy;
   419 
   429 
   441 static inline __strlen_t __pfind(STRING* IN1, STRING* IN2){
   451 static inline __strlen_t __pfind(STRING* IN1, STRING* IN2){
   442     UINT count1 = 0; /* offset of first matching char in IN1 */
   452     UINT count1 = 0; /* offset of first matching char in IN1 */
   443     UINT count2 = 0; /* count of matching char */
   453     UINT count2 = 0; /* count of matching char */
   444     while(count1 + count2 < IN1->len && count2 < IN2->len)
   454     while(count1 + count2 < IN1->len && count2 < IN2->len)
   445     {
   455     {
   446         if(IN1->body[count1 + count2] != IN2->body[count2++]){
   456         if(IN1->body[count1 + count2] != IN2->body[count2]){
   447             count1 += count2;
   457             count1 += count2 + 1;
   448             count2 = 0;
   458             count2 = 0;
       
   459         }
       
   460         else {
       
   461             count2++;
   449         }
   462         }
   450     }
   463     }
   451     return count2 == IN2->len -1 ? 0 : count1 + 1;
   464     return count2 == IN2->len -1 ? 0 : count1 + 1;
   452 }
   465 }
   453 static inline __strlen_t __find(EN_ENO_PARAMS, STRING IN1, STRING IN2){
   466 static inline __strlen_t __find(EN_ENO_PARAMS, STRING IN1, STRING IN2){
   467     if(IN)
   480     if(IN)
   468         return (STRING){4, "TRUE"};
   481         return (STRING){4, "TRUE"};
   469     return (STRING){5,"FALSE"};
   482     return (STRING){5,"FALSE"};
   470 }
   483 }
   471 static inline STRING __bit_to_string(EN_ENO_PARAMS, LWORD IN){
   484 static inline STRING __bit_to_string(EN_ENO_PARAMS, LWORD IN){
       
   485     STRING res;
   472     TEST_EN(STRING)
   486     TEST_EN(STRING)
   473     STRING res = __INIT_STRING;
   487     res = __INIT_STRING;
   474     res.len = snprintf((char*)res.body, STR_MAX_LEN, "16#%llx", IN);
   488     res.len = snprintf((char*)res.body, STR_MAX_LEN, "16#%llx", IN);
   475     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   489     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   476     return res;
   490     return res;
   477 }
   491 }
   478 static inline STRING __real_to_string(EN_ENO_PARAMS, LREAL IN){
   492 static inline STRING __real_to_string(EN_ENO_PARAMS, LREAL IN){
       
   493     STRING res;
   479     TEST_EN(STRING)
   494     TEST_EN(STRING)
   480     STRING res = __INIT_STRING;
   495     res = __INIT_STRING;
   481     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%.10g", IN);
   496     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%.10g", IN);
   482     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   497     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   483     return res;
   498     return res;
   484 }
   499 }
   485 static inline STRING __sint_to_string(EN_ENO_PARAMS, LINT IN){
   500 static inline STRING __sint_to_string(EN_ENO_PARAMS, LINT IN){
       
   501     STRING res;
   486     TEST_EN(STRING)
   502     TEST_EN(STRING)
   487     STRING res = __INIT_STRING;
   503     res = __INIT_STRING;
   488     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%lld", IN);
   504     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%lld", IN);
   489     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   505     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   490     return res;
   506     return res;
   491 }
   507 }
   492 static inline STRING __uint_to_string(EN_ENO_PARAMS, ULINT IN){
   508 static inline STRING __uint_to_string(EN_ENO_PARAMS, ULINT IN){
       
   509     STRING res;
   493     TEST_EN(STRING)
   510     TEST_EN(STRING)
   494     STRING res = __INIT_STRING;
   511     res = __INIT_STRING;
   495     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%llu", IN);
   512     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%llu", IN);
   496     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   513     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   497     return res;
   514     return res;
   498 }
   515 }
   499     /***************/
   516     /***************/
   504     return IN.len == 5 ? !memcmp(&IN.body,"TRUE", IN.len) : 0;
   521     return IN.len == 5 ? !memcmp(&IN.body,"TRUE", IN.len) : 0;
   505 }
   522 }
   506 
   523 
   507 static inline LINT __pstring_to_sint(STRING* IN){
   524 static inline LINT __pstring_to_sint(STRING* IN){
   508     LINT res = 0;
   525     LINT res = 0;
   509     char tmp[STR_MAX_LEN];
       
   510     char tmp2[STR_MAX_LEN];
       
   511     __strlen_t l;
   526     __strlen_t l;
   512     unsigned int shift = 0;
   527     unsigned int shift = 0;
   513 
   528 
   514     if(IN->body[0]=='2' && IN->body[1]=='#'){
   529     if(IN->body[0]=='2' && IN->body[1]=='#'){
   515         /* 2#0101_1010_1011_1111 */
   530         /* 2#0101_1010_1011_1111 */
   578 static inline ULINT __string_to_uint(EN_ENO_PARAMS, STRING IN){
   593 static inline ULINT __string_to_uint(EN_ENO_PARAMS, STRING IN){
   579     TEST_EN(ULINT)
   594     TEST_EN(ULINT)
   580     return (ULINT)__pstring_to_sint(&IN);
   595     return (ULINT)__pstring_to_sint(&IN);
   581 }
   596 }
   582 static inline LREAL __string_to_real(EN_ENO_PARAMS, STRING IN){
   597 static inline LREAL __string_to_real(EN_ENO_PARAMS, STRING IN){
   583     TEST_EN(LREAL)
   598 	__strlen_t l;
       
   599 	TEST_EN(LREAL)
       
   600 	l = IN.len;
   584     /* search the dot */
   601     /* search the dot */
   585     __strlen_t l = IN.len;
       
   586     while(--l > 0 && IN.body[l] != '.');
   602     while(--l > 0 && IN.body[l] != '.');
   587     if(l != 0){
   603     if(l != 0){
   588         return atof((const char *)&IN.body);
   604         return atof((const char *)&IN.body);
   589     }else{
   605     }else{
   590         return (LREAL)__pstring_to_sint(&IN);
   606         return (LREAL)__pstring_to_sint(&IN);
   602 static inline TIME __real_to_time(EN_ENO_PARAMS, LREAL IN){
   618 static inline TIME __real_to_time(EN_ENO_PARAMS, LREAL IN){
   603     TEST_EN(TIME)
   619     TEST_EN(TIME)
   604     return (TIME){IN, (IN - (LINT)IN) * 1000000000};
   620     return (TIME){IN, (IN - (LINT)IN) * 1000000000};
   605 }
   621 }
   606 static inline TIME __string_to_time(EN_ENO_PARAMS, STRING IN){
   622 static inline TIME __string_to_time(EN_ENO_PARAMS, STRING IN){
   607     TEST_EN(TIME)
   623 	__strlen_t l;
       
   624 	TEST_EN(TIME)
   608     /* TODO :
   625     /* TODO :
   609      *
   626      *
   610      *  Duration literals without underlines: T#14ms    T#-14ms   T#14.7s   T#14.7m
   627      *  Duration literals without underlines: T#14ms    T#-14ms   T#14.7s   T#14.7m
   611      *                short prefix            T#14.7h    t#14.7d   t#25h15m
   628      *                short prefix            T#14.7h    t#14.7d   t#25h15m
   612      *                                        t#5d14h12m18s3.5ms
   629      *                                        t#5d14h12m18s3.5ms
   625      *  date_and_time#1984-06-25-15:36:55.36 dt#1984-06-25-15:36:55.36
   642      *  date_and_time#1984-06-25-15:36:55.36 dt#1984-06-25-15:36:55.36
   626      *
   643      *
   627      */
   644      */
   628     /* Quick hack : only transform seconds */
   645     /* Quick hack : only transform seconds */
   629     /* search the dot */
   646     /* search the dot */
   630     __strlen_t l = IN.len;
   647 	l = IN.len;
   631     while(--l > 0 && IN.body[l] != '.');
   648     while(--l > 0 && IN.body[l] != '.');
   632     if(l != 0){
   649     if(l != 0){
   633         LREAL IN_val = atof((const char *)&IN.body);
   650         LREAL IN_val = atof((const char *)&IN.body);
   634         return  (TIME){IN_val, (IN_val - (LINT)IN_val)*1000000000};
   651         return  (TIME){IN_val, (IN_val - (LINT)IN_val)*1000000000};
   635     }else{
   652     }else{
   647 static inline LINT __time_to_int(EN_ENO_PARAMS, TIME IN){
   664 static inline LINT __time_to_int(EN_ENO_PARAMS, TIME IN){
   648     TEST_EN(LINT)
   665     TEST_EN(LINT)
   649     return IN.tv_sec;
   666     return IN.tv_sec;
   650 }
   667 }
   651 static inline STRING __time_to_string(EN_ENO_PARAMS, TIME IN){
   668 static inline STRING __time_to_string(EN_ENO_PARAMS, TIME IN){
       
   669     STRING res;
       
   670     div_t days;
   652     TEST_EN(STRING)
   671     TEST_EN(STRING)
   653     /*t#5d14h12m18s3.5ms*/
   672     /*t#5d14h12m18s3.5ms*/
   654     STRING res = __INIT_STRING;
   673     res = __INIT_STRING;
   655     div_t days = div(IN.tv_sec ,86400);
   674     days = div(IN.tv_sec ,86400);
   656     if(!days.rem && IN.tv_nsec == 0){
   675     if(!days.rem && IN.tv_nsec == 0){
   657         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "T#%dd", days.quot);
   676         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "T#%dd", days.quot);
   658     }else{
   677     }else{
   659         div_t hours = div(days.rem, 3600);
   678         div_t hours = div(days.rem, 3600);
   660         if(!hours.rem && IN.tv_nsec == 0){
   679         if(!hours.rem && IN.tv_nsec == 0){
   674     }
   693     }
   675     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   694     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   676     return res;
   695     return res;
   677 }
   696 }
   678 static inline STRING __date_to_string(EN_ENO_PARAMS, DATE IN){
   697 static inline STRING __date_to_string(EN_ENO_PARAMS, DATE IN){
   679     TEST_EN(STRING)
   698     STRING res;
       
   699     struct tm* broken_down_time;
       
   700     time_t seconds;
       
   701 	TEST_EN(STRING)
   680     /* D#1984-06-25 */
   702     /* D#1984-06-25 */
   681     STRING res = __INIT_STRING;
   703     res = __INIT_STRING;
   682     struct tm* broken_down_time;
   704     seconds = IN.tv_sec;
   683     time_t seconds = IN.tv_sec;
       
   684     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   705     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   685         IEC_error();
   706         IEC_error();
   686         return (STRING){7,"D#ERROR"};
   707         return (STRING){7,"D#ERROR"};
   687     }
   708     }
   688     res.len = snprintf((char*)&res.body, STR_MAX_LEN, "D#%d-%2.2d-%2.2d", broken_down_time->tm_year + 1900, broken_down_time->tm_mon + 1, broken_down_time->tm_mday);
   709     res.len = snprintf((char*)&res.body, STR_MAX_LEN, "D#%d-%2.2d-%2.2d", broken_down_time->tm_year + 1900, broken_down_time->tm_mon + 1, broken_down_time->tm_mday);
   689     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   710     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   690     return res;
   711     return res;
   691 }
   712 }
   692 static inline STRING __tod_to_string(EN_ENO_PARAMS, TOD IN){
   713 static inline STRING __tod_to_string(EN_ENO_PARAMS, TOD IN){
       
   714     STRING res;
       
   715     struct tm* broken_down_time;
       
   716     time_t seconds;
   693     TEST_EN(STRING)
   717     TEST_EN(STRING)
   694     /* TOD#15:36:55.36 */
   718     /* TOD#15:36:55.36 */
   695     STRING res = __INIT_STRING;
   719     res = __INIT_STRING;
   696     struct tm* broken_down_time;
   720     seconds = IN.tv_sec;
   697     time_t seconds = IN.tv_sec;
       
   698     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   721     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   699         IEC_error();
   722         IEC_error();
   700         return (STRING){9,"TOD#ERROR"};
   723         return (STRING){9,"TOD#ERROR"};
   701     }
   724     }
   702     if(IN.tv_nsec == 0){
   725     if(IN.tv_nsec == 0){
   706     }
   729     }
   707     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   730     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   708     return res;
   731     return res;
   709 }
   732 }
   710 static inline STRING __dt_to_string(EN_ENO_PARAMS, DT IN){
   733 static inline STRING __dt_to_string(EN_ENO_PARAMS, DT IN){
       
   734     STRING res;
       
   735     struct tm* broken_down_time;
       
   736     time_t seconds;
   711     TEST_EN(STRING)
   737     TEST_EN(STRING)
   712     /* DT#1984-06-25-15:36:55.36 */
   738     /* DT#1984-06-25-15:36:55.36 */
   713     STRING res;
   739     seconds = IN.tv_sec;
   714     struct tm* broken_down_time;
       
   715     time_t seconds = IN.tv_sec;
       
   716     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   740     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   717         IEC_error();
   741         IEC_error();
   718         return (STRING){8,"DT#ERROR"};
   742         return (STRING){8,"DT#ERROR"};
   719     }
   743     }
   720     if(IN.tv_nsec == 0){
   744     if(IN.tv_nsec == 0){
   738     return res;
   762     return res;
   739 }
   763 }
   740     /* BCD */
   764     /* BCD */
   741 #define __bcd_digit(fac)
   765 #define __bcd_digit(fac)
   742 static inline ULINT __bcd_to_uint(EN_ENO_PARAMS, LWORD IN){
   766 static inline ULINT __bcd_to_uint(EN_ENO_PARAMS, LWORD IN){
       
   767     ULINT res;
       
   768     ULINT i;
   743     TEST_EN(ULINT)
   769     TEST_EN(ULINT)
   744     return IN & 0xf +
   770 
   745            !(IN >>= 4) ? 0 : IN & 0xf * 10ULL +
   771     res = IN & 0xf;
   746            !(IN >>= 4) ? 0 : IN & 0xf * 100ULL +
   772     for(i = 10ULL; i <= 1000000000000000ULL; i *= 10){
   747            !(IN >>= 4) ? 0 : IN & 0xf * 1000ULL +
   773         if(!(IN >>= 4))
   748            !(IN >>= 4) ? 0 : IN & 0xf * 10000ULL +
   774             break;
   749            !(IN >>= 4) ? 0 : IN & 0xf * 100000ULL +
   775         res += (IN & 0xf) * i;
   750            !(IN >>= 4) ? 0 : IN & 0xf * 1000000ULL +
   776     }
   751            !(IN >>= 4) ? 0 : IN & 0xf * 10000000ULL +
   777     return res;
   752            !(IN >>= 4) ? 0 : IN & 0xf * 100000000ULL +
   778 }
   753            !(IN >>= 4) ? 0 : IN & 0xf * 1000000000ULL +
   779 
   754            !(IN >>= 4) ? 0 : IN & 0xf * 10000000000ULL +
       
   755            !(IN >>= 4) ? 0 : IN & 0xf * 100000000000ULL +
       
   756            !(IN >>= 4) ? 0 : IN & 0xf * 1000000000000ULL +
       
   757            !(IN >>= 4) ? 0 : IN & 0xf * 10000000000000ULL +
       
   758            !(IN >>= 4) ? 0 : IN & 0xf * 100000000000000ULL +
       
   759            !(IN >>= 4) ? 0 : IN & 0xf * 1000000000000000ULL;
       
   760 
       
   761 }
       
   762 static inline LWORD __uint_to_bcd(EN_ENO_PARAMS, ULINT IN){
   780 static inline LWORD __uint_to_bcd(EN_ENO_PARAMS, ULINT IN){
       
   781     LWORD res;
       
   782     USINT i;
   763     TEST_EN(LWORD)
   783     TEST_EN(LWORD)
   764     return (IN - (IN /= 10))|
   784 
   765            (IN - (IN /= 10)) << 4 |
   785     res = IN % 10;
   766            (IN - (IN /= 10)) << 8 |
   786     for(i = 4; i<=60; i += 4){
   767            (IN - (IN /= 10)) << 12 |
   787         if(!(IN /= 10))
   768            (IN - (IN /= 10)) << 16 |
   788             break;
   769            (IN - (IN /= 10)) << 20 |
   789         res |= (IN % 10) << i;
   770            (IN - (IN /= 10)) << 24 |
   790     }
   771            (IN - (IN /= 10)) << 28 |
   791     return res;
   772            (IN - (IN /= 10)) << 32 |
       
   773            (IN - (IN /= 10)) << 36 |
       
   774            (IN - (IN /= 10)) << 40 |
       
   775            (IN - (IN /= 10)) << 44 |
       
   776            (IN - (IN /= 10)) << 48 |
       
   777            (IN - (IN /= 10)) << 52 |
       
   778            (IN - (IN /= 10)) << 56 |
       
   779            (IN - (IN /= 10)) << 60;
       
   780 }
   792 }
   781 
   793 
   782 /* workaround for va-atgs limitation on shorter that int params */
   794 /* workaround for va-atgs limitation on shorter that int params */
   783 #define VA_ARGS_REAL LREAL
   795 #define VA_ARGS_REAL LREAL
   784 #define VA_ARGS_LREAL LREAL
   796 #define VA_ARGS_LREAL LREAL
   805 /*******************************************/
   817 /*******************************************/
   806 /*     Arithmetic and bitwise functions    */
   818 /*     Arithmetic and bitwise functions    */
   807 /*******************************************/
   819 /*******************************************/
   808 #define __arith_expand(fname,TYPENAME, OP) \
   820 #define __arith_expand(fname,TYPENAME, OP) \
   809 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
   821 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
   810   TEST_EN(TYPENAME)\
       
   811   va_list ap;\
   822   va_list ap;\
   812   UINT i;\
   823   UINT i;\
       
   824   TEST_EN(TYPENAME)\
   813   \
   825   \
   814   va_start (ap, op1);         /* Initialize the argument list.  */\
   826   va_start (ap, op1);         /* Initialize the argument list.  */\
   815   \
   827   \
   816   for (i = 0; i < param_count - 1; i++){\
   828   for (i = 0; i < param_count - 1; i++){\
   817     op1 = op1 OP va_arg (ap, VA_ARGS_##TYPENAME);\
   829     op1 = op1 OP va_arg (ap, VA_ARGS_##TYPENAME);\
   877 
   889 
   878 /**************/
   890 /**************/
   879 /*     XOR    */
   891 /*     XOR    */
   880 /**************/
   892 /**************/
   881 static inline BOOL __xor_BOOL(EN_ENO_PARAMS, UINT param_count, BOOL op1, ...){
   893 static inline BOOL __xor_BOOL(EN_ENO_PARAMS, UINT param_count, BOOL op1, ...){
   882   TEST_EN(BOOL)
       
   883   va_list ap;
   894   va_list ap;
   884   UINT i;
   895   UINT i;
       
   896   TEST_EN(BOOL)
   885 
   897 
   886   va_start (ap, op1);         /* Initialize the argument list.  */
   898   va_start (ap, op1);         /* Initialize the argument list.  */
   887 
   899 
   888   for (i = 0; i < param_count - 1; i++){
   900   for (i = 0; i < param_count - 1; i++){
   889     BOOL tmp = va_arg (ap, VA_ARGS_BOOL);
   901     BOOL tmp = va_arg (ap, VA_ARGS_BOOL);
   940 
   952 
   941 #define __ror_(TYPENAME)\
   953 #define __ror_(TYPENAME)\
   942 static inline TYPENAME __ror_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
   954 static inline TYPENAME __ror_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
   943   TEST_EN(TYPENAME)\
   955   TEST_EN(TYPENAME)\
   944   N %= 8*sizeof(TYPENAME);\
   956   N %= 8*sizeof(TYPENAME);\
   945   return (IN >> N) | (IN << 8*sizeof(TYPENAME)-N);\
   957   return (IN >> N) | (IN << (8*sizeof(TYPENAME)-N));\
   946 }
   958 }
   947 /* Call previously defined macro for each ANY_NBIT */
   959 /* Call previously defined macro for each ANY_NBIT */
   948 ANY_NBIT(__ror_)
   960 ANY_NBIT(__ror_)
   949 
   961 
   950 #define __rol_(TYPENAME)\
   962 #define __rol_(TYPENAME)\
   951 static inline TYPENAME __rol_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
   963 static inline TYPENAME __rol_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
   952   TEST_EN(TYPENAME)\
   964   TEST_EN(TYPENAME)\
   953   N %= 8*sizeof(TYPENAME);\
   965   N %= 8*sizeof(TYPENAME);\
   954   return (IN << N) | (IN >> 8*sizeof(TYPENAME)-N);\
   966   return (IN << N) | (IN >> (8*sizeof(TYPENAME)-N));\
   955 }
   967 }
   956 /* Call previously defined macro for each ANY_NBIT */
   968 /* Call previously defined macro for each ANY_NBIT */
   957 ANY_NBIT(__rol_)
   969 ANY_NBIT(__rol_)
   958 
   970 
   959 /*******************************************/
   971 /*******************************************/
   993 ANY_REAL(__sqrt_)
  1005 ANY_REAL(__sqrt_)
   994 
  1006 
   995   /**************/
  1007   /**************/
   996   /*     LN     */
  1008   /*     LN     */
   997   /**************/
  1009   /**************/
   998 #define __ln_(TYPENAME) __numeric(__ln_, TYPENAME, ln)
  1010 #define __ln_(TYPENAME) __numeric(__ln_, TYPENAME, log)
   999 ANY_REAL(__ln_)
  1011 ANY_REAL(__ln_)
  1000 
  1012 
  1001   /**************/
  1013   /**************/
  1002   /*     LOG    */
  1014   /*     LOG    */
  1003   /**************/
  1015   /**************/
  1004 #define __log_(TYPENAME) __numeric(__log_, TYPENAME, log)
  1016 #define __log_(TYPENAME) __numeric(__log_, TYPENAME, log10)
  1005 ANY_REAL(__log_)
  1017 ANY_REAL(__log_)
  1006 
  1018 
  1007   /**************/
  1019   /**************/
  1008   /*     EXP    */
  1020   /*     EXP    */
  1009   /**************/
  1021   /**************/
  1105     /*     MAX    */
  1117     /*     MAX    */
  1106     /**************/
  1118     /**************/
  1107 
  1119 
  1108 #define __extrem_(fname,TYPENAME, COND) \
  1120 #define __extrem_(fname,TYPENAME, COND) \
  1109 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
  1121 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
  1110   TEST_EN(TYPENAME)\
       
  1111   va_list ap;\
  1122   va_list ap;\
  1112   UINT i;\
  1123   UINT i;\
       
  1124   TEST_EN(TYPENAME)\
  1113   \
  1125   \
  1114   va_start (ap, op1);         /* Initialize the argument list.  */\
  1126   va_start (ap, op1);         /* Initialize the argument list.  */\
  1115   \
  1127   \
  1116   for (i = 0; i < param_count - 1; i++){\
  1128   for (i = 0; i < param_count - 1; i++){\
  1117     TYPENAME tmp = va_arg (ap, VA_ARGS_##TYPENAME);\
  1129     TYPENAME tmp = va_arg (ap, VA_ARGS_##TYPENAME);\
  1151     /**************/
  1163     /**************/
  1152     /*     MUX    */
  1164     /*     MUX    */
  1153     /**************/
  1165     /**************/
  1154 #define __mux_(TYPENAME) \
  1166 #define __mux_(TYPENAME) \
  1155 static inline TYPENAME __mux_##TYPENAME(EN_ENO_PARAMS, UINT param_count, UINT K, ...){\
  1167 static inline TYPENAME __mux_##TYPENAME(EN_ENO_PARAMS, UINT param_count, UINT K, ...){\
  1156   TEST_EN_COND(TYPENAME, K >= param_count)\
       
  1157   va_list ap;\
  1168   va_list ap;\
  1158   UINT i;\
  1169   UINT i;\
  1159   TYPENAME tmp = __INIT_##TYPENAME;\
  1170   TYPENAME tmp;\
       
  1171   TEST_EN_COND(TYPENAME, K >= param_count)\
       
  1172   tmp = __INIT_##TYPENAME;\
  1160   \
  1173   \
  1161   va_start (ap, K);         /* Initialize the argument list.  */\
  1174   va_start (ap, K);         /* Initialize the argument list.  */\
  1162   \
  1175   \
  1163   for (i = 0; i < param_count; i++){\
  1176   for (i = 0; i < param_count; i++){\
  1164     if(K == i){\
  1177     if(K == i){\
  1180 /* Comparison */
  1193 /* Comparison */
  1181 /**************/
  1194 /**************/
  1182 
  1195 
  1183 #define __compare_(fname,TYPENAME, COND) \
  1196 #define __compare_(fname,TYPENAME, COND) \
  1184 static inline BOOL fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
  1197 static inline BOOL fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
  1185   TEST_EN(BOOL)\
       
  1186   va_list ap;\
  1198   va_list ap;\
  1187   UINT i;\
  1199   UINT i;\
       
  1200   TEST_EN(BOOL)\
  1188   \
  1201   \
  1189   va_start (ap, op1);         /* Initialize the argument list.  */\
  1202   va_start (ap, op1);         /* Initialize the argument list.  */\
  1190   DBG(#fname #TYPENAME "\n")\
  1203   DBG(#fname #TYPENAME "\n")\
  1191   DBG_TYPE(TYPENAME, op1)\
  1204   DBG_TYPE(TYPENAME, op1)\
  1192   \
  1205   \
  1293 __ne_time(TIME)
  1306 __ne_time(TIME)
  1294 
  1307 
  1295 __compare_string(__ne_, != )
  1308 __compare_string(__ne_, != )
  1296 
  1309 
  1297 
  1310 
  1298 ///* Get string representation of variable referenced by a void pointer
  1311 /* Get string representation of variable referenced by a void pointer
  1299 // * where type is given as its number */
  1312  * where type is given as its number */
  1300 //#define __decl_str_case(cat,TYPENAME) \
  1313 /*#define __decl_str_case(cat,TYPENAME) \
  1301 //    case TYPENAME##_ENUM:\
  1314     case TYPENAME##_ENUM:\
  1302 //        return __##cat##_to_string(*(TYPENAME*)p);
  1315         return __##cat##_to_string(*(TYPENAME*)p);
  1303 //#define __decl_str_case_bit(TYPENAME) __decl_str_case(bit,TYPENAME)
  1316 #define __decl_str_case_bit(TYPENAME) __decl_str_case(bit,TYPENAME)
  1304 //#define __decl_str_case_real(TYPENAME) __decl_str_case(real,TYPENAME)
  1317 #define __decl_str_case_real(TYPENAME) __decl_str_case(real,TYPENAME)
  1305 //#define __decl_str_case_sint(TYPENAME) __decl_str_case(sint,TYPENAME)
  1318 #define __decl_str_case_sint(TYPENAME) __decl_str_case(sint,TYPENAME)
  1306 //#define __decl_str_case_uint(TYPENAME) __decl_str_case(uint,TYPENAME)
  1319 #define __decl_str_case_uint(TYPENAME) __decl_str_case(uint,TYPENAME)
  1307 //static inline STRING __get_type_enum_str(__IEC_types_enum t, void* p){
  1320 static inline STRING __get_type_enum_str(__IEC_types_enum t, void* p){
  1308 // switch(t){
  1321  switch(t){
  1309 //  __decl_str_case(bool,BOOL)
  1322   __decl_str_case(bool,BOOL)
  1310 //  ANY_NBIT(__decl_str_case_bit)
  1323   ANY_NBIT(__decl_str_case_bit)
  1311 //  ANY_REAL(__decl_str_case_real)
  1324   ANY_REAL(__decl_str_case_real)
  1312 //  ANY_SINT(__decl_str_case_sint)
  1325   ANY_SINT(__decl_str_case_sint)
  1313 //  ANY_UINT(__decl_str_case_uint)
  1326   ANY_UINT(__decl_str_case_uint)
  1314 //  __decl_str_case(time,TIME)
  1327   __decl_str_case(time,TIME)
  1315 //  __decl_str_case(date,DATE)
  1328   __decl_str_case(date,DATE)
  1316 //  __decl_str_case(tod,TOD)
  1329   __decl_str_case(tod,TOD)
  1317 //  __decl_str_case(dt, DT)
  1330   __decl_str_case(dt, DT)
  1318 // }
  1331  }
  1319 //}
  1332 }
  1320 //
  1333 */
  1321 
  1334 
  1322 
  1335 
  1323 
  1336 
  1324 
  1337 
  1325 
  1338 
  1326 
  1339