lib/iec_std_lib.h
changeset 149 05ca171a3d57
parent 140 8c0366d41e84
child 156 6b16b7f8b527
equal deleted inserted replaced
148:912bdab1eca8 149:05ca171a3d57
    40 /*
    40 /*
    41  * Include type defs.
    41  * Include type defs.
    42  */
    42  */
    43 #include "iec_types_all.h"
    43 #include "iec_types_all.h"
    44 
    44 
    45 #define __TIME_CMP(t1, t2) (t2.tv_sec == t1.tv_sec ? t1.tv_nsec - t2.tv_nsec : t1.tv_sec - t2.tv_sec) 
       
    46 extern TIME __CURRENT_TIME;
    45 extern TIME __CURRENT_TIME;
    47 extern BOOL __DEBUG;
    46 extern BOOL __DEBUG;
    48 
       
    49 #define __STR_CMP(str1, str2) memcmp((char*)&str1.body,(char*)&str2.body, str1.len < str2.len ? str1.len : str2.len)
       
    50 
    47 
    51 /* TODO
    48 /* TODO
    52 typedef struct {
    49 typedef struct {
    53     __strlen_t len;
    50     __strlen_t len;
    54     u_int16_t body[STR_MAX_LEN];
    51     u_int16_t body[STR_MAX_LEN];
   232     IEC_error();
   229     IEC_error();
   233 
   230 
   234   return ts;
   231   return ts;
   235 }
   232 }
   236 
   233 
       
   234 /********************/
       
   235 /*   EN/ENO PARAMS  */
       
   236 /********************/
       
   237 
       
   238 #define EN_ENO_PARAMS BOOL EN, BOOL *ENO
       
   239 #define TEST_EN(TYPENAME)\
       
   240   if (!EN) {\
       
   241     if (ENO != NULL)\
       
   242       *ENO = __BOOL_LITERAL(FALSE);\
       
   243     return __INIT_##TYPENAME;\
       
   244   }\
       
   245   else if (ENO != NULL)\
       
   246     *ENO = __BOOL_LITERAL(TRUE);
       
   247 #define TEST_EN_COND(TYPENAME, COND)\
       
   248   if (!EN || (COND)) {\
       
   249     if (ENO != NULL)\
       
   250       *ENO = __BOOL_LITERAL(FALSE);\
       
   251     return __INIT_##TYPENAME;\
       
   252   }\
       
   253   else if (ENO != NULL)\
       
   254     *ENO = __BOOL_LITERAL(TRUE);
       
   255 
   237 /***************/
   256 /***************/
   238 /*   Time ops  */
   257 /*   Time ops  */
   239 /***************/
   258 /***************/
   240 static inline TIME __date_and_time_to_time_of_day(TIME IN){
   259 #define __TIME_CMP(t1, t2) (t2.tv_sec == t1.tv_sec ? t1.tv_nsec - t2.tv_nsec : t1.tv_sec - t2.tv_sec) 
   241   return (TIME){IN.tv_sec % 86400, IN.tv_nsec};
   260 
   242 }
   261 static inline TIME __TIME_ADD(TIME IN1, TIME IN2){
   243 static inline TIME __date_and_time_to_date(TIME IN){
       
   244   return (TIME){IN.tv_sec - (IN.tv_sec % (24*60*60)), 0};
       
   245 }
       
   246 static inline TIME __time_add(TIME IN1, TIME IN2){
       
   247   TIME res ={IN1.tv_sec + IN2.tv_sec,
   262   TIME res ={IN1.tv_sec + IN2.tv_sec,
   248              IN1.tv_nsec + IN2.tv_nsec };
   263              IN1.tv_nsec + IN2.tv_nsec };
   249   __normalize_timespec(&res);
   264   __normalize_timespec(&res);
   250   return res;
   265   return res;
   251 }
   266 }
   252 static inline TIME __time_sub(TIME IN1, TIME IN2){
   267 static inline TIME __TIME_SUB(TIME IN1, TIME IN2){
   253   TIME res ={IN1.tv_sec - IN2.tv_sec,
   268   TIME res ={IN1.tv_sec - IN2.tv_sec,
   254              IN1.tv_nsec - IN2.tv_nsec };
   269              IN1.tv_nsec - IN2.tv_nsec };
   255   __normalize_timespec(&res);
   270   __normalize_timespec(&res);
   256   return res;
   271   return res;
   257 }
   272 }
   258 static inline TIME __time_mul(TIME IN1, LREAL IN2){
   273 static inline TIME __TIME_MUL(TIME IN1, LREAL IN2){
   259   LREAL s_f = IN1.tv_sec * IN2;
   274   LREAL s_f = IN1.tv_sec * IN2;
   260   time_t s = s_f;
   275   time_t s = s_f;
   261   div_t ns = div((LREAL)IN1.tv_nsec * IN2, 1000000000);
   276   div_t ns = div((LREAL)IN1.tv_nsec * IN2, 1000000000);
   262   TIME res = {s + ns.quot,
   277   TIME res = {s + ns.quot,
   263               ns.rem + (s_f - s) * 1000000000 };
   278               ns.rem + (s_f - s) * 1000000000 };
   264   __normalize_timespec(&res);
   279   __normalize_timespec(&res);
   265   return res;
   280   return res;
   266 }
   281 }
   267 static inline TIME __time_div(TIME IN1, LREAL IN2){
   282 static inline TIME __TIME_DIV(TIME IN1, LREAL IN2){
   268   LREAL s_f = IN1.tv_sec / IN2;
   283   LREAL s_f = IN1.tv_sec / IN2;
   269   time_t s = s_f;
   284   time_t s = s_f;
   270   TIME res = {s,
   285   TIME res = {s,
   271               IN1.tv_nsec / IN2 + (s_f - s) * 1000000000 };
   286               IN1.tv_nsec / IN2 + (s_f - s) * 1000000000 };
   272   __normalize_timespec(&res);
   287   __normalize_timespec(&res);
   273   return res;
   288   return res;
   274 }
   289 }
   275 
   290 
       
   291 static inline TIME __date_and_time_to_time_of_day(EN_ENO_PARAMS, TIME IN){
       
   292   TEST_EN(TIME)
       
   293   return (TIME){IN.tv_sec % 86400, IN.tv_nsec};
       
   294 }
       
   295 static inline TIME __date_and_time_to_date(EN_ENO_PARAMS, TIME IN){
       
   296   TEST_EN(TIME)
       
   297   return (TIME){IN.tv_sec - (IN.tv_sec % (24*60*60)), 0};
       
   298 }
       
   299 static inline TIME __time_add(EN_ENO_PARAMS, TIME IN1, TIME IN2){
       
   300   TEST_EN(TIME)
       
   301   return __TIME_ADD(IN1, IN2);
       
   302 }
       
   303 static inline TIME __time_sub(EN_ENO_PARAMS, TIME IN1, TIME IN2){
       
   304   TEST_EN(TIME)
       
   305   return __TIME_SUB(IN1, IN2);
       
   306 }
       
   307 static inline TIME __time_mul(EN_ENO_PARAMS, TIME IN1, LREAL IN2){
       
   308   TEST_EN(TIME)
       
   309   return __TIME_MUL(IN1, IN2);
       
   310 }
       
   311 static inline TIME __time_div(EN_ENO_PARAMS, TIME IN1, LREAL IN2){
       
   312   TEST_EN(TIME)
       
   313   return __TIME_DIV(IN1, IN2);
       
   314 }
       
   315 
   276 /***************/
   316 /***************/
   277 /* String ops  */
   317 /* String ops  */
   278 /***************/
   318 /***************/
   279 static inline UINT __len(STRING IN){
   319 #define __STR_CMP(str1, str2) memcmp((char*)&str1.body,(char*)&str2.body, str1.len < str2.len ? str1.len : str2.len)
       
   320 
       
   321 static inline UINT __len(EN_ENO_PARAMS, STRING IN){
       
   322     TEST_EN(UINT)
   280     return IN.len;
   323     return IN.len;
   281 }
   324 }
   282 static inline STRING __left(STRING IN, SINT L){
   325 static inline STRING __left(EN_ENO_PARAMS, STRING IN, SINT L){
       
   326     TEST_EN_COND(STRING, L < 0)
   283     STRING res = __INIT_STRING;
   327     STRING res = __INIT_STRING;
   284     L = L < IN.len ? L : IN.len;
   328     L = L < IN.len ? L : IN.len;
   285     memcpy(&res.body, &IN.body, L);
   329     memcpy(&res.body, &IN.body, L);
   286     res.len = L;
   330     res.len = L;
   287     return res;
   331     return res;
   288 }
   332 }
   289 static inline STRING __right(STRING IN, SINT L){
   333 static inline STRING __right(EN_ENO_PARAMS, STRING IN, SINT L){
       
   334     TEST_EN_COND(STRING, L < 0)
   290     STRING res = __INIT_STRING;
   335     STRING res = __INIT_STRING;
   291     L = L < IN.len ? L : IN.len;
   336     L = L < IN.len ? L : IN.len;
   292     memcpy(&res.body, &IN.body[IN.len - L], L);
   337     memcpy(&res.body, &IN.body[IN.len - L], L);
   293     res.len = L;
   338     res.len = L;
   294     return res;
   339     return res;
   295 }
   340 }
   296 static inline STRING __mid(STRING IN, SINT L, SINT P){
   341 static inline STRING __mid(EN_ENO_PARAMS, STRING IN, SINT L, SINT P){
       
   342     TEST_EN_COND(STRING, L < 0 || P < 0)
   297     STRING res = __INIT_STRING;
   343     STRING res = __INIT_STRING;
   298     if(P <= IN.len){
   344     if(P <= IN.len){
   299 	    P -= 1; /* now can be used as [index]*/
   345 	    P -= 1; /* now can be used as [index]*/
   300 	    L = L + P <= IN.len ? L : IN.len - P;
   346 	    L = L + P <= IN.len ? L : IN.len - P;
   301 	    memcpy(&res.body, &IN.body[P] , L);
   347 	    memcpy(&res.body, &IN.body[P] , L);
   302         res.len = L;
   348         res.len = L;
   303     }
   349     }
   304     return res;
   350     return res;
   305 }
   351 }
   306 static inline STRING __concat(SINT param_count, ...){
   352 static inline STRING __concat(EN_ENO_PARAMS, SINT param_count, ...){
       
   353   TEST_EN(STRING)
   307   va_list ap;
   354   va_list ap;
   308   UINT i;
   355   UINT i;
   309   __strlen_t charcount = 0;
   356   __strlen_t charcount = 0;
   310   STRING res = __INIT_STRING;
   357   STRING res = __INIT_STRING;
   311 
   358 
   323   res.len = charcount;
   370   res.len = charcount;
   324 
   371 
   325   va_end (ap);                  /* Clean up.  */
   372   va_end (ap);                  /* Clean up.  */
   326   return res;
   373   return res;
   327 }
   374 }
   328 static inline STRING __insert(STRING IN1, STRING IN2, SINT P){
   375 static inline STRING __insert(EN_ENO_PARAMS, STRING IN1, STRING IN2, SINT P){
       
   376     TEST_EN_COND(STRING, P < 0)
   329     STRING res = __INIT_STRING;
   377     STRING res = __INIT_STRING;
   330     __strlen_t to_copy;
   378     __strlen_t to_copy;
   331     
   379     
   332     to_copy = P > IN1.len ? IN1.len : P - 1;
   380     to_copy = P > IN1.len ? IN1.len : P - 1;
   333     memcpy(&res.body, &IN1.body , to_copy);
   381     memcpy(&res.body, &IN1.body , to_copy);
   341     memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
   389     memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
   342     res.len += to_copy;
   390     res.len += to_copy;
   343 
   391 
   344     return res;
   392     return res;
   345 }
   393 }
   346 static inline STRING __delete(STRING IN, SINT L, SINT P){
   394 static inline STRING __delete(EN_ENO_PARAMS, STRING IN, SINT L, SINT P){
       
   395     TEST_EN_COND(STRING, L < 0 || P < 0)
   347     STRING res = __INIT_STRING;
   396     STRING res = __INIT_STRING;
   348     __strlen_t to_copy;
   397     __strlen_t to_copy;
   349     
   398     
   350     to_copy = P > IN.len ? IN.len : P-1;
   399     to_copy = P > IN.len ? IN.len : P-1;
   351     memcpy(&res.body, &IN.body , to_copy);
   400     memcpy(&res.body, &IN.body , to_copy);
   357         res.len += to_copy;
   406         res.len += to_copy;
   358     }
   407     }
   359 
   408 
   360     return res;
   409     return res;
   361 }
   410 }
   362 static inline STRING __replace(STRING IN1, STRING IN2, SINT L, SINT P){
   411 static inline STRING __replace(EN_ENO_PARAMS, STRING IN1, STRING IN2, SINT L, SINT P){
       
   412     TEST_EN_COND(STRING, L < 0 || P < 0)
   363     STRING res = __INIT_STRING;
   413     STRING res = __INIT_STRING;
   364     __strlen_t to_copy;
   414     __strlen_t to_copy;
   365     
   415     
   366     to_copy = P > IN1.len ? IN1.len : P-1;
   416     to_copy = P > IN1.len ? IN1.len : P-1;
   367     memcpy(&res.body, &IN1.body , to_copy);
   417     memcpy(&res.body, &IN1.body , to_copy);
   398             count2 = 0;
   448             count2 = 0;
   399         }        
   449         }        
   400     }
   450     }
   401     return count2 == IN2->len -1 ? 0 : count1 + 1;
   451     return count2 == IN2->len -1 ? 0 : count1 + 1;
   402 }
   452 }
   403 static inline UINT __find(STRING IN1, STRING IN2){
   453 static inline UINT __find(EN_ENO_PARAMS, STRING IN1, STRING IN2){
       
   454     TEST_EN(UINT)
   404     return __pfind(&IN1, &IN2);
   455     return __pfind(&IN1, &IN2);
   405 }
   456 }
   406 
   457 
   407 /***************/
   458 /***************/
   408 /* Convertions */
   459 /* Convertions */
   409 /***************/
   460 /***************/
   410     /***************/
   461     /***************/
   411     /*  TO_STRING  */
   462     /*  TO_STRING  */
   412     /***************/
   463     /***************/
   413 static inline STRING __bool_to_string(BOOL IN)
   464 static inline STRING __bool_to_string(EN_ENO_PARAMS, BOOL IN)
   414 {
   465 {
       
   466     TEST_EN(STRING)
   415     if(IN)
   467     if(IN)
   416         return (STRING){4, "TRUE"};
   468         return (STRING){4, "TRUE"};
   417     return (STRING){5,"FALSE"};
   469     return (STRING){5,"FALSE"};
   418 }
   470 }
   419 static inline STRING __bit_to_string(LWORD IN){
   471 static inline STRING __bit_to_string(EN_ENO_PARAMS, LWORD IN){
       
   472     TEST_EN(STRING)
   420     STRING res = __INIT_STRING;
   473     STRING res = __INIT_STRING;
   421     res.len = snprintf((char*)res.body, STR_MAX_LEN, "16#%llx", IN);
   474     res.len = snprintf((char*)res.body, STR_MAX_LEN, "16#%llx", IN);
   422     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   475     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   423     return res;
   476     return res;
   424 }
   477 }
   425 static inline STRING __real_to_string(LREAL IN){
   478 static inline STRING __real_to_string(EN_ENO_PARAMS, LREAL IN){
       
   479     TEST_EN(STRING)
   426     STRING res = __INIT_STRING;
   480     STRING res = __INIT_STRING;
   427     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%.10g", IN);
   481     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%.10g", IN);
   428     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   482     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   429     return res;
   483     return res;
   430 }
   484 }
   431 static inline STRING __sint_to_string(LINT IN){
   485 static inline STRING __sint_to_string(EN_ENO_PARAMS, LINT IN){
       
   486     TEST_EN(STRING)
   432     STRING res = __INIT_STRING;
   487     STRING res = __INIT_STRING;
   433     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%lld", IN);
   488     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%lld", IN);
   434     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   489     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   435     return res;
   490     return res;
   436 }
   491 }
   437 static inline STRING __uint_to_string(ULINT IN){
   492 static inline STRING __uint_to_string(EN_ENO_PARAMS, ULINT IN){
       
   493     TEST_EN(STRING)
   438     STRING res = __INIT_STRING;
   494     STRING res = __INIT_STRING;
   439     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%llu", IN);
   495     res.len = snprintf((char*)res.body, STR_MAX_LEN, "%llu", IN);
   440     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   496     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   441     return res;
   497     return res;
   442 }
   498 }
   443     /***************/
   499     /***************/
   444     /* FROM_STRING */
   500     /* FROM_STRING */
   445     /***************/
   501     /***************/
   446 static inline BOOL __string_to_bool(STRING IN){
   502 static inline BOOL __string_to_bool(EN_ENO_PARAMS, STRING IN){
       
   503     TEST_EN(BOOL)
   447     return IN.len == 5 ? !memcmp(&IN.body,"TRUE", IN.len) : 0;
   504     return IN.len == 5 ? !memcmp(&IN.body,"TRUE", IN.len) : 0;
   448 }
   505 }
   449 
   506 
   450 static inline LINT __pstring_to_sint(STRING* IN){
   507 static inline LINT __pstring_to_sint(STRING* IN){
   451     LINT res = 0;
   508     LINT res = 0;
   508         }
   565         }
   509     }
   566     }
   510     return res;
   567     return res;
   511 }
   568 }
   512 
   569 
   513 static inline LINT __string_to_sint(STRING IN){
   570 static inline LINT __string_to_sint(EN_ENO_PARAMS, STRING IN){
       
   571     TEST_EN(LINT)
   514     return (LWORD)__pstring_to_sint(&IN);
   572     return (LWORD)__pstring_to_sint(&IN);
   515 }
   573 }
   516 static inline LWORD __string_to_bit(STRING IN){
   574 static inline LWORD __string_to_bit(EN_ENO_PARAMS, STRING IN){
       
   575     TEST_EN(LWORD)
   517     return (LWORD)__pstring_to_sint(&IN);
   576     return (LWORD)__pstring_to_sint(&IN);
   518 }
   577 }
   519 static inline ULINT __string_to_uint(STRING IN){
   578 static inline ULINT __string_to_uint(EN_ENO_PARAMS, STRING IN){
       
   579     TEST_EN(ULINT)
   520     return (ULINT)__pstring_to_sint(&IN);
   580     return (ULINT)__pstring_to_sint(&IN);
   521 }
   581 }
   522 static inline LREAL __string_to_real(STRING IN){
   582 static inline LREAL __string_to_real(EN_ENO_PARAMS, STRING IN){
       
   583     TEST_EN(LREAL)
   523     /* search the dot */
   584     /* search the dot */
   524     __strlen_t l = IN.len;
   585     __strlen_t l = IN.len;
   525     while(--l > 0 && IN.body[l] != '.');
   586     while(--l > 0 && IN.body[l] != '.');
   526     if(l != 0){
   587     if(l != 0){
   527         return atof((const char *)&IN.body);
   588         return atof((const char *)&IN.body);
   531 }
   592 }
   532 
   593 
   533     /***************/
   594     /***************/
   534     /*   TO_TIME   */
   595     /*   TO_TIME   */
   535     /***************/
   596     /***************/
   536 static inline TIME __int_to_time(LINT IN){
   597 static inline TIME __int_to_time(EN_ENO_PARAMS, LINT IN){
       
   598     TEST_EN(TIME)
   537     return (TIME){IN, 0};
   599     return (TIME){IN, 0};
   538 }
   600 }
   539 
   601 
   540 static inline TIME __real_to_time(LREAL IN){
   602 static inline TIME __real_to_time(EN_ENO_PARAMS, LREAL IN){
       
   603     TEST_EN(TIME)
   541     return (TIME){IN, (IN - (LINT)IN) * 1000000000};
   604     return (TIME){IN, (IN - (LINT)IN) * 1000000000};
   542 }
   605 }
   543 static inline TIME __string_to_time(STRING IN){
   606 static inline TIME __string_to_time(EN_ENO_PARAMS, STRING IN){
       
   607     TEST_EN(TIME)
   544     /* TODO :
   608     /* TODO :
   545      *
   609      *
   546      *  Duration literals without underlines: T#14ms    T#-14ms   T#14.7s   T#14.7m
   610      *  Duration literals without underlines: T#14ms    T#-14ms   T#14.7s   T#14.7m
   547      *                short prefix            T#14.7h    t#14.7d   t#25h15m
   611      *                short prefix            T#14.7h    t#14.7d   t#25h15m
   548      *                                        t#5d14h12m18s3.5ms
   612      *                                        t#5d14h12m18s3.5ms
   574 }
   638 }
   575 
   639 
   576     /***************/
   640     /***************/
   577     /*  FROM_TIME  */
   641     /*  FROM_TIME  */
   578     /***************/
   642     /***************/
   579 static inline LREAL __time_to_real(TIME IN){
   643 static inline LREAL __time_to_real(EN_ENO_PARAMS, TIME IN){
       
   644     TEST_EN(LREAL)
   580     return (LREAL)IN.tv_sec + ((LREAL)IN.tv_nsec/1000000000);
   645     return (LREAL)IN.tv_sec + ((LREAL)IN.tv_nsec/1000000000);
   581 }
   646 }
   582 static inline LINT __time_to_int(TIME IN){
   647 static inline LINT __time_to_int(EN_ENO_PARAMS, TIME IN){
       
   648     TEST_EN(LINT)
   583     return IN.tv_sec;
   649     return IN.tv_sec;
   584 }
   650 }
   585 static inline STRING __time_to_string(TIME IN){
   651 static inline STRING __time_to_string(EN_ENO_PARAMS, TIME IN){
       
   652     TEST_EN(STRING)
   586     /*t#5d14h12m18s3.5ms*/
   653     /*t#5d14h12m18s3.5ms*/
   587     STRING res = __INIT_STRING;
   654     STRING res = __INIT_STRING;
   588     div_t days = div(IN.tv_sec ,86400);
   655     div_t days = div(IN.tv_sec ,86400);
   589     if(!days.rem && IN.tv_nsec == 0){
   656     if(!days.rem && IN.tv_nsec == 0){
   590         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "T#%dd", days.quot);
   657         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "T#%dd", days.quot);
   606         }
   673         }
   607     }
   674     }
   608     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   675     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   609     return res;
   676     return res;
   610 }
   677 }
   611 static inline STRING __date_to_string(DATE IN){
   678 static inline STRING __date_to_string(EN_ENO_PARAMS, DATE IN){
       
   679     TEST_EN(STRING)
   612     /* D#1984-06-25 */
   680     /* D#1984-06-25 */
   613     STRING res = __INIT_STRING;
   681     STRING res = __INIT_STRING;
   614     struct tm* broken_down_time;
   682     struct tm* broken_down_time;
   615     time_t seconds = IN.tv_sec;
   683     time_t seconds = IN.tv_sec;
   616     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   684     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   619     }
   687     }
   620     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);
   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);
   621     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   689     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   622     return res;
   690     return res;
   623 }
   691 }
   624 static inline STRING __tod_to_string(TOD IN){
   692 static inline STRING __tod_to_string(EN_ENO_PARAMS, TOD IN){
       
   693     TEST_EN(STRING)
   625     /* TOD#15:36:55.36 */
   694     /* TOD#15:36:55.36 */
   626     STRING res = __INIT_STRING;
   695     STRING res = __INIT_STRING;
   627     struct tm* broken_down_time;
   696     struct tm* broken_down_time;
   628     time_t seconds = IN.tv_sec;
   697     time_t seconds = IN.tv_sec;
   629     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   698     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   636         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "TOD#%2.2d:%2.2d:%g", broken_down_time->tm_hour, broken_down_time->tm_min, (LREAL)broken_down_time->tm_sec + (LREAL)IN.tv_nsec / 1e9);
   705         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "TOD#%2.2d:%2.2d:%g", broken_down_time->tm_hour, broken_down_time->tm_min, (LREAL)broken_down_time->tm_sec + (LREAL)IN.tv_nsec / 1e9);
   637     }
   706     }
   638     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   707     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   639     return res;
   708     return res;
   640 }
   709 }
   641 static inline STRING __dt_to_string(DT IN){
   710 static inline STRING __dt_to_string(EN_ENO_PARAMS, DT IN){
       
   711     TEST_EN(STRING)
   642     /* DT#1984-06-25-15:36:55.36 */
   712     /* DT#1984-06-25-15:36:55.36 */
   643     STRING res;
   713     STRING res;
   644     struct tm* broken_down_time;
   714     struct tm* broken_down_time;
   645     time_t seconds = IN.tv_sec;
   715     time_t seconds = IN.tv_sec;
   646     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   716     if (NULL == (broken_down_time = localtime(&seconds))){ /* get the UTC (GMT) broken down time */
   667     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   737     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   668     return res;
   738     return res;
   669 }
   739 }
   670     /* BCD */
   740     /* BCD */
   671 #define __bcd_digit(fac) 
   741 #define __bcd_digit(fac) 
   672 static inline ULINT __bcd_to_uint(LWORD IN){
   742 static inline ULINT __bcd_to_uint(EN_ENO_PARAMS, LWORD IN){
       
   743     TEST_EN(ULINT)
   673     return IN & 0xf +
   744     return IN & 0xf +
   674            !(IN >>= 4) ? 0 : IN & 0xf * 10ULL + 
   745            !(IN >>= 4) ? 0 : IN & 0xf * 10ULL + 
   675            !(IN >>= 4) ? 0 : IN & 0xf * 100ULL + 
   746            !(IN >>= 4) ? 0 : IN & 0xf * 100ULL + 
   676            !(IN >>= 4) ? 0 : IN & 0xf * 1000ULL + 
   747            !(IN >>= 4) ? 0 : IN & 0xf * 1000ULL + 
   677            !(IN >>= 4) ? 0 : IN & 0xf * 10000ULL + 
   748            !(IN >>= 4) ? 0 : IN & 0xf * 10000ULL + 
   686            !(IN >>= 4) ? 0 : IN & 0xf * 10000000000000ULL + 
   757            !(IN >>= 4) ? 0 : IN & 0xf * 10000000000000ULL + 
   687            !(IN >>= 4) ? 0 : IN & 0xf * 100000000000000ULL + 
   758            !(IN >>= 4) ? 0 : IN & 0xf * 100000000000000ULL + 
   688            !(IN >>= 4) ? 0 : IN & 0xf * 1000000000000000ULL;
   759            !(IN >>= 4) ? 0 : IN & 0xf * 1000000000000000ULL;
   689            
   760            
   690 }
   761 }
   691 static inline LWORD __uint_to_bcd(ULINT IN){
   762 static inline LWORD __uint_to_bcd(EN_ENO_PARAMS, ULINT IN){
       
   763     TEST_EN(LWORD)
   692     return (IN - (IN /= 10))|
   764     return (IN - (IN /= 10))|
   693            (IN - (IN /= 10)) << 4 |
   765            (IN - (IN /= 10)) << 4 |
   694            (IN - (IN /= 10)) << 8 |
   766            (IN - (IN /= 10)) << 8 |
   695            (IN - (IN /= 10)) << 12 |
   767            (IN - (IN /= 10)) << 12 |
   696            (IN - (IN /= 10)) << 16 |
   768            (IN - (IN /= 10)) << 16 |
   705            (IN - (IN /= 10)) << 52 |
   777            (IN - (IN /= 10)) << 52 |
   706            (IN - (IN /= 10)) << 56 |
   778            (IN - (IN /= 10)) << 56 |
   707            (IN - (IN /= 10)) << 60;
   779            (IN - (IN /= 10)) << 60;
   708 }
   780 }
   709 
   781 
   710 /**************/
       
   711 /* Binary ops */
       
   712 /**************/
       
   713 #define __ror_(TYPENAME)\
       
   714 static inline TYPENAME __ror_##TYPENAME( TYPENAME IN, USINT N){\
       
   715  N %= 8*sizeof(TYPENAME);\
       
   716  return (IN >> N) | (IN << 8*sizeof(TYPENAME)-N);\
       
   717 }
       
   718 /* Call previously defined macro for each ANY_NBIT */
       
   719 ANY_NBIT(__ror_)
       
   720 
       
   721 #define __rol_(TYPENAME)\
       
   722 static inline TYPENAME __rol_##TYPENAME( TYPENAME IN, USINT N){\
       
   723  N %= 8*sizeof(TYPENAME);\
       
   724  return (IN << N) | (IN >> 8*sizeof(TYPENAME)-N);\
       
   725 }
       
   726 /* Call previously defined macro for each ANY_NBIT */
       
   727 ANY_NBIT(__rol_)
       
   728 
       
   729 /**************/
       
   730 /* Selection  */
       
   731 /**************/
       
   732 	/**************/
       
   733 	/*   limit    */
       
   734 	/**************/
       
   735 
       
   736 #define __limit_(TYPENAME)\
       
   737 static inline TYPENAME __limit_##TYPENAME( TYPENAME MN, TYPENAME IN, TYPENAME MX){\
       
   738  return IN > MN ? IN < MX ? IN : MX : MN;\
       
   739 }
       
   740 
       
   741 /* Call previously defined macro for each concerned type */
       
   742 ANY_NBIT(__limit_)
       
   743 ANY_NUM(__limit_)
       
   744 
       
   745 #define __limit_time(TYPENAME)\
       
   746 static inline TIME __limit_##TYPENAME( TYPENAME MN, TYPENAME IN, TYPENAME MX){\
       
   747     return __TIME_CMP(IN, MN) > 0 ? /* IN>MN ?*/\
       
   748            __TIME_CMP(IN, MX) < 0 ? /* IN<MX ?*/\
       
   749            IN : MX : MN;\
       
   750 }
       
   751 
       
   752 /* Call previously defined macro for each concerned type */
       
   753 ANY_DATE(__limit_time)
       
   754 __limit_time(TIME)
       
   755 
       
   756 static inline STRING __limit_STRING( STRING MN, STRING IN, STRING MX){
       
   757     return __STR_CMP(IN, MN) > 0 ? __STR_CMP(IN, MX) < 0 ? IN : MX : MN;
       
   758 }
       
   759 
       
   760     /**************/
       
   761     /*     MAX    */
       
   762     /**************/
       
   763     
       
   764 /* workaround for va-atgs limitation on shorter that int params */    
   782 /* workaround for va-atgs limitation on shorter that int params */    
   765 #define VA_ARGS_REAL LREAL
   783 #define VA_ARGS_REAL LREAL
   766 #define VA_ARGS_LREAL LREAL
   784 #define VA_ARGS_LREAL LREAL
   767 #define VA_ARGS_SINT DINT
   785 #define VA_ARGS_SINT DINT
   768 #define VA_ARGS_INT DINT
   786 #define VA_ARGS_INT DINT
   782 #define VA_ARGS_WSTRING WSTRING
   800 #define VA_ARGS_WSTRING WSTRING
   783 #define VA_ARGS_DATE DATE
   801 #define VA_ARGS_DATE DATE
   784 #define VA_ARGS_TOD TOD
   802 #define VA_ARGS_TOD TOD
   785 #define VA_ARGS_DT DT
   803 #define VA_ARGS_DT DT
   786 
   804 
       
   805 /*******************************************/
       
   806 /*     Arithmetic and bitwise functions    */
       
   807 /*******************************************/
       
   808 #define __arith_expand(fname,TYPENAME, OP) \
       
   809 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
       
   810   TEST_EN(TYPENAME)\
       
   811   va_list ap;\
       
   812   UINT i;\
       
   813   \
       
   814   va_start (ap, op1);         /* Initialize the argument list.  */\
       
   815   \
       
   816   for (i = 0; i < param_count - 1; i++){\
       
   817     op1 = op1 OP va_arg (ap, VA_ARGS_##TYPENAME);\
       
   818   }\
       
   819   \
       
   820   va_end (ap);                  /* Clean up.  */\
       
   821   return op1;\
       
   822 }
       
   823 
       
   824 #define __arith_static(fname,TYPENAME, OP) \
       
   825 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\
       
   826   TEST_EN(TYPENAME)\
       
   827   return op1 OP op2;\
       
   828 }
       
   829 
       
   830 /**************/
       
   831 /*     ADD    */
       
   832 /**************/
       
   833 #define __add_(TYPENAME) __arith_expand(__add_, TYPENAME, + )
       
   834 ANY_NUM(__add_)
       
   835 
       
   836 /**************/
       
   837 /*     MUL    */
       
   838 /**************/
       
   839 #define __mul_(TYPENAME) __arith_expand(__mul_, TYPENAME, * )
       
   840 ANY_NUM(__mul_)
       
   841 
       
   842 /**************/
       
   843 /*     SUB    */
       
   844 /**************/
       
   845 #define __sub_(TYPENAME) __arith_static(__sub_, TYPENAME, - )
       
   846 ANY_NUM(__sub_)
       
   847 
       
   848 /**************/
       
   849 /*     DIV    */
       
   850 /**************/
       
   851 #define __div_(TYPENAME)\
       
   852 static inline TYPENAME __div_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1, TYPENAME op2){\
       
   853   TEST_EN_COND(TYPENAME, op2 == 0)\
       
   854   return op1 / op2;\
       
   855 }
       
   856 ANY_NUM(__div_)
       
   857 
       
   858 /**************/
       
   859 /*     MOD    */
       
   860 /**************/
       
   861 #define __mod_(TYPENAME) __arith_static(__mod_, TYPENAME, % )
       
   862 ANY_INT(__mod_)
       
   863 
       
   864 /**************/
       
   865 /*     AND    */
       
   866 /**************/
       
   867 __arith_expand(__and_, BOOL, && )
       
   868 #define __and_(TYPENAME) __arith_expand(__and_, TYPENAME, & )
       
   869 ANY_NBIT(__and_)
       
   870 
       
   871 /*************/
       
   872 /*     OR    */
       
   873 /*************/
       
   874 __arith_expand(__or_, BOOL, || )
       
   875 #define __or_(TYPENAME) __arith_expand(__or_, TYPENAME, |)
       
   876 ANY_NBIT(__or_)
       
   877 
       
   878 /**************/
       
   879 /*     XOR    */
       
   880 /**************/
       
   881 static inline BOOL __xor_BOOL(EN_ENO_PARAMS, UINT param_count, BOOL op1, ...){
       
   882   TEST_EN(BOOL)
       
   883   va_list ap;
       
   884   UINT i;
       
   885   
       
   886   va_start (ap, op1);         /* Initialize the argument list.  */
       
   887   
       
   888   for (i = 0; i < param_count - 1; i++){
       
   889     BOOL tmp = va_arg (ap, VA_ARGS_BOOL);
       
   890     op1 = (op1 && !tmp) || (!op1 && tmp);
       
   891   }
       
   892   
       
   893   va_end (ap);                  /* Clean up.  */
       
   894   return op1;
       
   895 }
       
   896 #define __xor_(TYPENAME) __arith_expand(__xor_, TYPENAME, ^)
       
   897 ANY_NBIT(__xor_)
       
   898 
       
   899 /**************/
       
   900 /*     NOT    */
       
   901 /**************/
       
   902 static inline BOOL __not_BOOL(EN_ENO_PARAMS, BOOL op1){
       
   903   TEST_EN(BOOL)
       
   904   return !op1;
       
   905 }
       
   906 
       
   907 #define __not_(TYPENAME)\
       
   908 static inline TYPENAME __not_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\
       
   909   TEST_EN(TYPENAME)\
       
   910   return ~op1;\
       
   911 }
       
   912 ANY_NBIT(__not_)
       
   913 
       
   914 /***************/
       
   915 /*     MOVE    */
       
   916 /***************/
       
   917 #define __move_(TYPENAME)\
       
   918 static inline TYPENAME __move_##TYPENAME(EN_ENO_PARAMS, TYPENAME op1){\
       
   919   TEST_EN(TYPENAME)\
       
   920   return op1;\
       
   921 }
       
   922 ANY(__move_)
       
   923 
       
   924 /**************/
       
   925 /* Binary ops */
       
   926 /**************/
       
   927 #define __shift_(fname, TYPENAME, OP)\
       
   928 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N) {\
       
   929   TEST_EN_COND(TYPENAME, N < 0)\
       
   930   return IN OP N;\
       
   931 }
       
   932 
       
   933 #define __shl_(TYPENAME) __shift_(__shl_, TYPENAME, << )
       
   934 /* Call previously defined macro for each ANY_NBIT */
       
   935 ANY_NBIT(__shl_)
       
   936 
       
   937 #define __shr_(TYPENAME) __shift_(__shr_, TYPENAME, >> )
       
   938 /* Call previously defined macro for each ANY_NBIT */
       
   939 ANY_NBIT(__shr_)
       
   940 
       
   941 #define __ror_(TYPENAME)\
       
   942 static inline TYPENAME __ror_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
       
   943   TEST_EN_COND(TYPENAME, N < 0)\
       
   944   N %= 8*sizeof(TYPENAME);\
       
   945   return (IN >> N) | (IN << 8*sizeof(TYPENAME)-N);\
       
   946 }
       
   947 /* Call previously defined macro for each ANY_NBIT */
       
   948 ANY_NBIT(__ror_)
       
   949 
       
   950 #define __rol_(TYPENAME)\
       
   951 static inline TYPENAME __rol_##TYPENAME(EN_ENO_PARAMS, TYPENAME IN, USINT N){\
       
   952   TEST_EN_COND(TYPENAME, N < 0)\
       
   953   N %= 8*sizeof(TYPENAME);\
       
   954   return (IN << N) | (IN >> 8*sizeof(TYPENAME)-N);\
       
   955 }
       
   956 /* Call previously defined macro for each ANY_NBIT */
       
   957 ANY_NBIT(__rol_)
       
   958 
       
   959 /**************/
       
   960 /* Selection  */
       
   961 /**************/
       
   962 
       
   963   /**************/
       
   964   /*    SEL     */
       
   965   /**************/
       
   966 
       
   967 #define __sel_(TYPENAME)\
       
   968 static inline TYPENAME __sel_##TYPENAME(EN_ENO_PARAMS, BOOL G, TYPENAME op0, TYPENAME op1){\
       
   969   TEST_EN(TYPENAME)\
       
   970   return G ? op1 : op0;\
       
   971 }
       
   972 ANY(__sel_)
       
   973 
       
   974 	/**************/
       
   975 	/*   limit    */
       
   976 	/**************/
       
   977 
       
   978 #define __limit_(TYPENAME)\
       
   979 static inline TYPENAME __limit_##TYPENAME(EN_ENO_PARAMS, TYPENAME MN, TYPENAME IN, TYPENAME MX){\
       
   980   TEST_EN(TYPENAME)\
       
   981   return IN > MN ? IN < MX ? IN : MX : MN;\
       
   982 }
       
   983 
       
   984 /* Call previously defined macro for each concerned type */
       
   985 ANY_NBIT(__limit_)
       
   986 ANY_NUM(__limit_)
       
   987 
       
   988 #define __limit_time(TYPENAME)\
       
   989 static inline TYPENAME __limit_##TYPENAME(EN_ENO_PARAMS, TYPENAME MN, TYPENAME IN, TYPENAME MX){\
       
   990     TEST_EN(TYPENAME)\
       
   991     return __TIME_CMP(IN, MN) > 0 ? /* IN>MN ?*/\
       
   992            __TIME_CMP(IN, MX) < 0 ? /* IN<MX ?*/\
       
   993            IN : MX : MN;\
       
   994 }
       
   995 
       
   996 /* Call previously defined macro for each concerned type */
       
   997 ANY_DATE(__limit_time)
       
   998 __limit_time(TIME)
       
   999 
       
  1000 static inline STRING __limit_STRING(EN_ENO_PARAMS, STRING MN, STRING IN, STRING MX){
       
  1001     TEST_EN(STRING)
       
  1002     return __STR_CMP(IN, MN) > 0 ? __STR_CMP(IN, MX) < 0 ? IN : MX : MN;
       
  1003 }
       
  1004 
       
  1005     /**************/
       
  1006     /*     MAX    */
       
  1007     /**************/
       
  1008 
   787 #define __extrem_(fname,TYPENAME, COND) \
  1009 #define __extrem_(fname,TYPENAME, COND) \
   788 static inline TYPENAME fname##TYPENAME( UINT param_count, TYPENAME op1, ...){\
  1010 static inline TYPENAME fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
       
  1011   TEST_EN(TYPENAME)\
   789   va_list ap;\
  1012   va_list ap;\
   790   UINT i;\
  1013   UINT i;\
   791   \
  1014   \
   792   va_start (ap, op1);         /* Initialize the argument list.  */\
  1015   va_start (ap, op1);         /* Initialize the argument list.  */\
   793   \
  1016   \
   828 
  1051 
   829     /**************/
  1052     /**************/
   830     /*     MUX    */
  1053     /*     MUX    */
   831     /**************/
  1054     /**************/
   832 #define __mux_(TYPENAME) \
  1055 #define __mux_(TYPENAME) \
   833 static inline TYPENAME __mux_##TYPENAME( UINT param_count, UINT K, ...){\
  1056 static inline TYPENAME __mux_##TYPENAME(EN_ENO_PARAMS, UINT param_count, UINT K, ...){\
       
  1057   TEST_EN_COND(TYPENAME, K < 0 || K >= param_count)\
   834   va_list ap;\
  1058   va_list ap;\
   835   UINT i;\
  1059   UINT i;\
   836   TYPENAME tmp = __INIT_##TYPENAME;\
  1060   TYPENAME tmp = __INIT_##TYPENAME;\
   837   \
  1061   \
   838   va_start (ap, K);         /* Initialize the argument list.  */\
  1062   va_start (ap, K);         /* Initialize the argument list.  */\
   856 /**************/
  1080 /**************/
   857 /* Comparison */
  1081 /* Comparison */
   858 /**************/
  1082 /**************/
   859 
  1083 
   860 #define __compare_(fname,TYPENAME, COND) \
  1084 #define __compare_(fname,TYPENAME, COND) \
   861 static inline BOOL fname##TYPENAME( UINT param_count, TYPENAME op1, ...){\
  1085 static inline BOOL fname##TYPENAME(EN_ENO_PARAMS, UINT param_count, TYPENAME op1, ...){\
       
  1086   TEST_EN(BOOL)\
   862   va_list ap;\
  1087   va_list ap;\
   863   UINT i;\
  1088   UINT i;\
   864   \
  1089   \
   865   va_start (ap, op1);         /* Initialize the argument list.  */\
  1090   va_start (ap, op1);         /* Initialize the argument list.  */\
   866   DBG(#fname #TYPENAME "\n")\
  1091   DBG(#fname #TYPENAME "\n")\
   882 }
  1107 }
   883 
  1108 
   884 #define __compare_num(fname, TYPENAME, TEST) __compare_(fname, TYPENAME, op1 TEST tmp )
  1109 #define __compare_num(fname, TYPENAME, TEST) __compare_(fname, TYPENAME, op1 TEST tmp )
   885 #define __compare_time(fname, TYPENAME, TEST) __compare_(fname, TYPENAME, __TIME_CMP(op1, tmp) TEST 0)
  1110 #define __compare_time(fname, TYPENAME, TEST) __compare_(fname, TYPENAME, __TIME_CMP(op1, tmp) TEST 0)
   886 #define __compare_string(fname, TEST) __compare_(fname, STRING, __STR_CMP(op1, tmp) TEST 0 )
  1111 #define __compare_string(fname, TEST) __compare_(fname, STRING, __STR_CMP(op1, tmp) TEST 0 )
       
  1112 
   887 
  1113 
   888     /**************/
  1114     /**************/
   889     /*     GT     */
  1115     /*     GT     */
   890     /**************/
  1116     /**************/
   891 
  1117