lib/iec_std_lib.h
changeset 41 8998c8b24b60
parent 40 873a5b60a7ea
child 42 b45c7f34dec1
equal deleted inserted replaced
40:873a5b60a7ea 41:8998c8b24b60
     6 #include <float.h>
     6 #include <float.h>
     7 #include <math.h>
     7 #include <math.h>
     8 #include <time.h>
     8 #include <time.h>
     9 #include <sys/types.h>
     9 #include <sys/types.h>
    10 
    10 
       
    11 #include <stdio.h>
    11 #include <stdlib.h>
    12 #include <stdlib.h>
    12 #include <string.h>
    13 #include <string.h>
    13 #include <stdarg.h>
    14 #include <stdarg.h>
    14 
    15 
    15 #include "iec_std_lib_generated.h"
    16 #include "iec_std_lib_generated.h"
    45 typedef struct timespec DATE;
    46 typedef struct timespec DATE;
    46 typedef struct timespec DT;
    47 typedef struct timespec DT;
    47 typedef struct timespec TOD;
    48 typedef struct timespec TOD;
    48 
    49 
    49 #define __TIME_CMP(t1, t2) (t2.tv_sec == t1.tv_sec ? t2.tv_nsec - t1.tv_nsec : t1.tv_sec - t2.tv_sec) 
    50 #define __TIME_CMP(t1, t2) (t2.tv_sec == t1.tv_sec ? t2.tv_nsec - t1.tv_nsec : t1.tv_sec - t2.tv_sec) 
       
    51 extern TIME __CURRENT_TIME;
    50 
    52 
    51 #define STR_MAX_LEN 40
    53 #define STR_MAX_LEN 40
    52 typedef int8_t __strlen_t;
    54 typedef int8_t __strlen_t;
    53 typedef struct {
    55 typedef struct {
    54     __strlen_t len;
    56     __strlen_t len;
    55     u_int8_t body[STR_MAX_LEN];
    57     u_int8_t body[STR_MAX_LEN];
    56 } STRING;
    58 } STRING;
    57 
    59 
    58 #define __STR_CMP(str1, str2) memcmp((char*)&str1.body,(char*)&str2.body, str1.len < str2.len ? str1.len : str2.len)
    60 #define __STR_CMP(str1, str2) memcmp((char*)&str1.body,(char*)&str2.body, str1.len < str2.len ? str1.len : str2.len)
    59 
    61 
    60 
       
    61 /* TODO
    62 /* TODO
    62 typedef struct {
    63 typedef struct {
    63     __strlen_t len;
    64     __strlen_t len;
    64     u_int16_t body[STR_MAX_LEN];
    65     u_int16_t body[STR_MAX_LEN];
    65 } WSTRING;
    66 } WSTRING;
    66 */
    67 */
    67 
    68 
       
    69 #define __INIT_REAL 0
       
    70 #define __INIT_LREAL 0
       
    71 #define __INIT_SINT 0
       
    72 #define __INIT_INT 0
       
    73 #define __INIT_DINT 0
       
    74 #define __INIT_LINT 0
       
    75 #define __INIT_USINT 0
       
    76 #define __INIT_UINT 0
       
    77 #define __INIT_UDINT 0
       
    78 #define __INIT_ULINT 0
       
    79 #define __INIT_TIME (TIME){0,0}
       
    80 #define __INIT_BOOL 0
       
    81 #define __INIT_BYTE 0
       
    82 #define __INIT_WORD 0
       
    83 #define __INIT_DWORD 0
       
    84 #define __INIT_LWORD 0
       
    85 #define __INIT_STRING (STRING){0,""}
       
    86 //#define __INIT_WSTRING
       
    87 #define __INIT_DATE (DATE){0,0}
       
    88 #define __INIT_TOD (TOD){0,0}
       
    89 #define __INIT_DT (DT){0,0}
       
    90 
    68 typedef union __IL_DEFVAR_T {
    91 typedef union __IL_DEFVAR_T {
    69     BOOL    BOOLvar;
    92     BOOL    BOOLvar;
    70 
    93 
    71     SINT    SINTvar;
    94     SINT    SINTvar;
    72     INT     INTvar;
    95     INT     INTvar;
    98 /*****************/
   121 /*****************/
    99 /* Misc internal */
   122 /* Misc internal */
   100 /*****************/
   123 /*****************/
   101 
   124 
   102 /* function that generates an IEC runtime error */
   125 /* function that generates an IEC runtime error */
   103 void IEC_error(void) {
   126 static inline void IEC_error(void) {
   104   /* TODO... */
   127   /* TODO... */
   105   fprintf(stderr, "IEC 61131-3 runtime error.\n");
   128   fprintf(stderr, "IEC 61131-3 runtime error.\n");
   106   /*exit(1);*/
   129   /*exit(1);*/
   107 }
   130 }
   108 
   131 
   191 }
   214 }
   192 
   215 
   193 /***************/
   216 /***************/
   194 /*   Time ops  */
   217 /*   Time ops  */
   195 /***************/
   218 /***************/
   196 inline TIME __date_and_time_to_time_of_day(TIME IN){
   219 static inline TIME __date_and_time_to_time_of_day(TIME IN){
   197   return (TIME){IN.tv_sec % 86400, IN.tv_nsec};
   220   return (TIME){IN.tv_sec % 86400, IN.tv_nsec};
   198 }
   221 }
   199 inline TIME __date_and_time_to_date(TIME IN){
   222 static inline TIME __date_and_time_to_date(TIME IN){
   200   return (TIME){IN.tv_sec - (IN.tv_sec % (24*60*60)), 0};
   223   return (TIME){IN.tv_sec - (IN.tv_sec % (24*60*60)), 0};
   201 }
   224 }
   202 inline TIME __time_add(TIME IN1, TIME IN2){
   225 static inline TIME __time_add(TIME IN1, TIME IN2){
   203   TIME res ={IN1.tv_sec + IN2.tv_sec,
   226   TIME res ={IN1.tv_sec + IN2.tv_sec,
   204              IN1.tv_nsec + IN2.tv_nsec };
   227              IN1.tv_nsec + IN2.tv_nsec };
   205   __normalize_timespec(&res);
   228   __normalize_timespec(&res);
   206   return res;
   229   return res;
   207 }
   230 }
   208 inline TIME __time_sub(TIME IN1, TIME IN2){
   231 static inline TIME __time_sub(TIME IN1, TIME IN2){
   209   TIME res ={IN1.tv_sec - IN2.tv_sec,
   232   TIME res ={IN1.tv_sec - IN2.tv_sec,
   210              IN1.tv_nsec - IN2.tv_nsec };
   233              IN1.tv_nsec - IN2.tv_nsec };
   211   __normalize_timespec(&res);
   234   __normalize_timespec(&res);
   212   return res;
   235   return res;
   213 }
   236 }
   214 inline TIME __time_mul(TIME IN1, LREAL IN2){
   237 static inline TIME __time_mul(TIME IN1, LREAL IN2){
   215   LREAL s_f = IN1.tv_sec * IN2;
   238   LREAL s_f = IN1.tv_sec * IN2;
   216   time_t s = s_f;
   239   time_t s = s_f;
   217   div_t ns = div((LREAL)IN1.tv_nsec * IN2, 1000000000);
   240   div_t ns = div((LREAL)IN1.tv_nsec * IN2, 1000000000);
   218   TIME res = {s + ns.quot,
   241   TIME res = {s + ns.quot,
   219               ns.rem + (s_f - s) * 1000000000 };
   242               ns.rem + (s_f - s) * 1000000000 };
   220   __normalize_timespec(&res);
   243   __normalize_timespec(&res);
   221   return res;
   244   return res;
   222 }
   245 }
   223 inline TIME __time_div(TIME IN1, LREAL IN2){
   246 static inline TIME __time_div(TIME IN1, LREAL IN2){
   224   LREAL s_f = IN1.tv_sec / IN2;
   247   LREAL s_f = IN1.tv_sec / IN2;
   225   time_t s = s_f;
   248   time_t s = s_f;
   226   TIME res = {s,
   249   TIME res = {s,
   227               IN1.tv_nsec / IN2 + (s_f - s) * 1000000000 };
   250               IN1.tv_nsec / IN2 + (s_f - s) * 1000000000 };
   228   __normalize_timespec(&res);
   251   __normalize_timespec(&res);
   230 }
   253 }
   231 
   254 
   232 /***************/
   255 /***************/
   233 /* String ops  */
   256 /* String ops  */
   234 /***************/
   257 /***************/
   235 inline UINT __len(STRING IN){
   258 static inline UINT __len(STRING IN){
   236     return IN.len;
   259     return IN.len;
   237 }
   260 }
   238 inline STRING __left(STRING IN, SINT L){
   261 static inline STRING __left(STRING IN, SINT L){
   239     STRING res = {0,};
   262     STRING res = __INIT_STRING;
   240     memcpy(&res.body, &IN.body, L < res.len ? L : res.len);
       
   241     return res;
       
   242 }
       
   243 inline STRING __right(STRING IN, SINT L){
       
   244     STRING res = {0,};
       
   245     L = L < IN.len ? L : IN.len;
   263     L = L < IN.len ? L : IN.len;
   246     memcpy(&res, &IN.body[IN.len - L], L);
   264     memcpy(&res.body, &IN.body, L);
   247     res.len = L;
   265     res.len = L;
   248     return res;
   266     return res;
   249 }
   267 }
   250 inline STRING __mid(STRING IN, SINT L, SINT P){
   268 static inline STRING __right(STRING IN, SINT L){
   251     STRING res = {0,};
   269     STRING res = __INIT_STRING;
       
   270     L = L < IN.len ? L : IN.len;
       
   271     memcpy(&res.body, &IN.body[IN.len - L], L);
       
   272     res.len = L;
       
   273     return res;
       
   274 }
       
   275 static inline STRING __mid(STRING IN, SINT L, SINT P){
       
   276     STRING res = __INIT_STRING;
   252     if(P <= IN.len){
   277     if(P <= IN.len){
   253 	    P -= 1; /* now can be used as [index]*/
   278 	    P -= 1; /* now can be used as [index]*/
   254 	    L = L + P <= IN.len ? L : IN.len - P;
   279 	    L = L + P <= IN.len ? L : IN.len - P;
   255 	    memcpy(&res, &IN.body[P] , L);
   280 	    memcpy(&res.body, &IN.body[P] , L);
   256         res.len = L;
   281         res.len = L;
   257     }
   282     }
   258     return res;
   283     return res;
   259 }
   284 }
   260 inline STRING __concat(SINT param_count, ...){
   285 static inline STRING __concat(SINT param_count, ...){
   261   va_list ap;
   286   va_list ap;
   262   UINT i;
   287   UINT i;
   263   __strlen_t charcount = 0;
   288   __strlen_t charcount = 0;
   264   STRING res = {0,};
   289   STRING res = __INIT_STRING;
   265 
   290 
   266   va_start (ap, param_count);         /* Initialize the argument list.  */
   291   va_start (ap, param_count);         /* Initialize the argument list.  */
   267 
   292 
   268   for (i = 0; i < param_count && charcount < STR_MAX_LEN; i++)
   293   for (i = 0; i < param_count && charcount < STR_MAX_LEN; i++)
   269   {
   294   {
   277   res.len = charcount;
   302   res.len = charcount;
   278 
   303 
   279   va_end (ap);                  /* Clean up.  */
   304   va_end (ap);                  /* Clean up.  */
   280   return res;
   305   return res;
   281 }
   306 }
   282 inline STRING __insert(STRING IN1, STRING IN2, SINT P){
   307 static inline STRING __insert(STRING IN1, STRING IN2, SINT P){
   283     STRING res = {0,};
   308     STRING res = __INIT_STRING;
   284     __strlen_t to_copy;
   309     __strlen_t to_copy;
   285     
   310     
   286     to_copy = P > IN1.len ? IN1.len : P;
   311     to_copy = P > IN1.len ? IN1.len : P - 1;
   287     memcpy(&res.body, &IN1.body , to_copy);
   312     memcpy(&res.body, &IN1.body , to_copy);
   288     P = res.len = to_copy;
   313     P = res.len = to_copy;
   289     
   314     
   290     to_copy = IN2.len + res.len > STR_MAX_LEN ? STR_MAX_LEN - res.len : IN2.len;
   315     to_copy = IN2.len + res.len > STR_MAX_LEN ? STR_MAX_LEN - res.len : IN2.len;
   291     memcpy(&res.body[res.len], &IN2.body , to_copy);
   316     memcpy(&res.body[res.len], &IN2.body , to_copy);
   295     memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
   320     memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
   296     res.len += to_copy;
   321     res.len += to_copy;
   297 
   322 
   298     return res;
   323     return res;
   299 }
   324 }
   300 inline STRING __delete(STRING IN, SINT L_value, SINT P){
   325 static inline STRING __delete(STRING IN, SINT L, SINT P){
   301     STRING res = {0,};
   326     STRING res = __INIT_STRING;
   302     __strlen_t to_copy;
   327     __strlen_t to_copy;
   303     
   328     
   304     to_copy = P > IN.len ? IN.len : P;
   329     to_copy = P > IN.len ? IN.len : P-1;
   305     memcpy(&res.body, &IN.body , to_copy);
   330     memcpy(&res.body, &IN.body , to_copy);
   306     P = res.len = to_copy;
   331     P = res.len = to_copy;
   307 
   332 
   308     to_copy = IN.len - P;
   333     if( IN.len > P + L ){
   309     memcpy(&res.body[res.len], &IN.body[P] , to_copy);
   334         to_copy = IN.len - P - L;
   310     res.len += to_copy;
   335         memcpy(&res.body[res.len], &IN.body[P + L], to_copy);
   311 
   336         res.len += to_copy;
   312     return res;
   337     }
   313 }
   338 
   314 inline STRING __replace(STRING IN1, STRING IN2, SINT L, SINT P){
   339     return res;
   315     STRING res = {0,};
   340 }
       
   341 static inline STRING __replace(STRING IN1, STRING IN2, SINT L, SINT P){
       
   342     STRING res = __INIT_STRING;
   316     __strlen_t to_copy;
   343     __strlen_t to_copy;
   317     
   344     
   318     to_copy = P > IN1.len ? IN1.len : P;
   345     to_copy = P > IN1.len ? IN1.len : P-1;
   319     memcpy(&res.body, &IN1.body , to_copy);
   346     memcpy(&res.body, &IN1.body , to_copy);
   320     P = res.len = to_copy;
   347     P = res.len = to_copy;
   321     
   348     
   322     to_copy = IN2.len + res.len > STR_MAX_LEN ? STR_MAX_LEN - res.len : IN2.len;
   349     to_copy = IN2.len < L ? IN2.len : L;
       
   350 
       
   351     if( to_copy + res.len > STR_MAX_LEN ) 
       
   352        to_copy = STR_MAX_LEN - res.len;   
       
   353 
   323     memcpy(&res.body[res.len], &IN2.body , to_copy);
   354     memcpy(&res.body[res.len], &IN2.body , to_copy);
   324     res.len += to_copy;
   355     res.len += to_copy;
   325 
   356 
   326     to_copy = res.len < IN1.len ? IN1.len - res.len : 0;
   357     P += L;
   327     memcpy(&res.body[res.len], &IN1.body[res.len] , to_copy);
   358     if( res.len <  STR_MAX_LEN && P < IN1.len)
   328     res.len += to_copy;
   359     {
   329 
   360         to_copy = IN1.len - P;
   330     return res;
   361         memcpy(&res.body[res.len], &IN1.body[P] , to_copy);
   331 }
   362         res.len += to_copy;
   332 
   363     }
   333 
   364 
   334 
   365     return res;
   335 inline UINT __pfind(STRING* IN1, STRING* IN2){
   366 }
   336     UINT count1 = 0;
   367 
   337     UINT count2 = 0;
   368 
       
   369 
       
   370 static inline UINT __pfind(STRING* IN1, STRING* IN2){
       
   371     UINT count1 = 0; /* offset of first matching char in IN1 */
       
   372     UINT count2 = 0; /* count of matching char */
   338     while(count1 + count2 < IN1->len && count2 < IN2->len)
   373     while(count1 + count2 < IN1->len && count2 < IN2->len)
   339     {
   374     {
   340         if(IN1->body[count1 + count2] != IN2->body[count2++]){
   375         if(IN1->body[count1 + count2] != IN2->body[count2++]){
   341             count1 += count2;
   376             count1 += count2;
   342             count2 = 0;
   377             count2 = 0;
   343         }        
   378         }        
   344     }
   379     }
   345     return count2 == IN2->len ? 0 : count1;
   380     return count2 == IN2->len -1 ? 0 : count1 + 1;
   346 }
   381 }
   347 inline UINT __find(STRING IN1, STRING IN2){
   382 static inline UINT __find(STRING IN1, STRING IN2){
   348     return __pfind(&IN1, &IN2);
   383     return __pfind(&IN1, &IN2);
   349 }
   384 }
   350 
   385 
   351 /***************/
   386 /***************/
   352 /* Convertions */
   387 /* Convertions */
   353 /***************/
   388 /***************/
   354     /***************/
   389     /***************/
   355     /*  TO_STRING  */
   390     /*  TO_STRING  */
   356     /***************/
   391     /***************/
   357 inline STRING __bool_to_string(BOOL IN)
   392 static inline STRING __bool_to_string(BOOL IN)
   358 {
   393 {
   359     if(IN)
   394     if(IN)
   360         return (STRING){4, "TRUE"};
   395         return (STRING){4, "TRUE"};
   361     return (STRING){5,"FALSE"};
   396     return (STRING){5,"FALSE"};
   362 }
   397 }
   363 inline STRING __bit_to_string(LWORD IN){
   398 static inline STRING __bit_to_string(LWORD IN){
   364     STRING res = {0,};
   399     STRING res = __INIT_STRING;
   365     res.len = snprintf(res.body, STR_MAX_LEN, "16#%llx", IN);
   400     res.len = snprintf(res.body, STR_MAX_LEN, "16#%llx", IN);
   366     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   401     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   367     return res;
   402     return res;
   368 }
   403 }
   369 inline STRING __real_to_string(LREAL IN){
   404 static inline STRING __real_to_string(LREAL IN){
   370     STRING res = {0,};
   405     STRING res = __INIT_STRING;
   371     res.len = snprintf(res.body, STR_MAX_LEN, "%g", IN);
   406     res.len = snprintf(res.body, STR_MAX_LEN, "%g", IN);
   372     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   407     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   373     return res;
   408     return res;
   374 }
   409 }
   375 inline STRING __sint_to_string(LINT IN){
   410 static inline STRING __sint_to_string(LINT IN){
   376     STRING res = {0,};
   411     STRING res = __INIT_STRING;
   377     res.len = snprintf(res.body, STR_MAX_LEN, "%lld", IN);
   412     res.len = snprintf(res.body, STR_MAX_LEN, "%lld", IN);
   378     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   413     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   379     return res;
   414     return res;
   380 }
   415 }
   381 inline STRING __uint_to_string(ULINT IN){
   416 static inline STRING __uint_to_string(ULINT IN){
   382     STRING res = {0,};
   417     STRING res = __INIT_STRING;
   383     res.len = snprintf(res.body, STR_MAX_LEN, "16#%llu", IN);
   418     res.len = snprintf(res.body, STR_MAX_LEN, "16#%llu", IN);
   384     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   419     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   385     return res;
   420     return res;
   386 }
   421 }
   387     /***************/
   422     /***************/
   388     /* FROM_STRING */
   423     /* FROM_STRING */
   389     /***************/
   424     /***************/
   390 inline BOOL __string_to_bool(STRING IN){
   425 static inline BOOL __string_to_bool(STRING IN){
   391     return IN.len == 5 ? !memcmp(&IN.body,"TRUE", IN.len) : 0;
   426     return IN.len == 5 ? !memcmp(&IN.body,"TRUE", IN.len) : 0;
   392 }
   427 }
   393 
   428 
   394 inline LINT __pstring_to_sint(STRING* IN){
   429 static inline LINT __pstring_to_sint(STRING* IN){
   395     LINT res = 0;
   430     LINT res = 0;
   396     char tmp[STR_MAX_LEN];
   431     char tmp[STR_MAX_LEN];
   397     char tmp2[STR_MAX_LEN];
   432     char tmp2[STR_MAX_LEN];
   398     __strlen_t l;
   433     __strlen_t l;
   399     unsigned int shift = 0;
   434     unsigned int shift = 0;
   442             char c = IN->body[l];
   477             char c = IN->body[l];
   443             if( c >= '0' && c <= '9'){
   478             if( c >= '0' && c <= '9'){
   444                 res += ( c - '0') * fac;
   479                 res += ( c - '0') * fac;
   445                 fac *= 10;
   480                 fac *= 10;
   446                 shift += 1;
   481                 shift += 1;
   447             }
   482             }else if( c >= '.' ){ /* reset value */
       
   483                 res = 0;
       
   484                 fac = 1;
       
   485                 shift = 0;
       
   486             }            
   448         }
   487         }
   449     }
   488     }
   450     return res;
   489     return res;
   451 }
   490 }
   452 
   491 
   453 inline LINT __string_to_sint(STRING IN){
   492 static inline LINT __string_to_sint(STRING IN){
   454     return (LWORD)__pstring_to_sint(&IN);
   493     return (LWORD)__pstring_to_sint(&IN);
   455 }
   494 }
   456 inline LWORD __string_to_bit(STRING IN){
   495 static inline LWORD __string_to_bit(STRING IN){
   457     return (LWORD)__pstring_to_sint(&IN);
   496     return (LWORD)__pstring_to_sint(&IN);
   458 }
   497 }
   459 inline ULINT __string_to_uint(STRING IN){
   498 static inline ULINT __string_to_uint(STRING IN){
   460     return (ULINT)__pstring_to_sint(&IN);
   499     return (ULINT)__pstring_to_sint(&IN);
   461 }
   500 }
   462 inline LREAL __string_to_real(STRING IN){
   501 static inline LREAL __string_to_real(STRING IN){
   463     /* search the dot */
   502     /* search the dot */
   464     __strlen_t l = IN.len;
   503     __strlen_t l = IN.len;
   465     while(--l > 0 && IN.body[l] != '.');
   504     while(--l > 0 && IN.body[l] != '.');
   466     if(l != 0){
   505     if(l != 0){
   467         return atof((const char *)&IN.body);
   506         return atof((const char *)&IN.body);
   471 }
   510 }
   472 
   511 
   473     /***************/
   512     /***************/
   474     /*   TO_TIME   */
   513     /*   TO_TIME   */
   475     /***************/
   514     /***************/
   476 inline TIME __int_to_time(LINT IN){
   515 static inline TIME __int_to_time(LINT IN){
   477     return (TIME){IN, 0};
   516     return (TIME){IN, 0};
   478 }
   517 }
   479 
   518 
   480 inline TIME __real_to_time(LREAL IN){
   519 static inline TIME __real_to_time(LREAL IN){
   481     return (TIME){IN, (IN - (LINT)IN) * 1000000000};
   520     return (TIME){IN, (IN - (LINT)IN) * 1000000000};
   482 }
   521 }
   483 inline TIME __string_to_time(STRING IN){
   522 static inline TIME __string_to_time(STRING IN){
   484     /* TODO :
   523     /* TODO :
   485      *
   524      *
   486      *  Duration literals without underlines: T#14ms    T#-14ms   T#14.7s   T#14.7m
   525      *  Duration literals without underlines: T#14ms    T#-14ms   T#14.7s   T#14.7m
   487      *                short prefix            T#14.7h    t#14.7d   t#25h15m
   526      *                short prefix            T#14.7h    t#14.7d   t#25h15m
   488      *                                        t#5d14h12m18s3.5ms
   527      *                                        t#5d14h12m18s3.5ms
   514 }
   553 }
   515 
   554 
   516     /***************/
   555     /***************/
   517     /*  FROM_TIME  */
   556     /*  FROM_TIME  */
   518     /***************/
   557     /***************/
   519 inline LREAL __time_to_real(TIME IN){
   558 static inline LREAL __time_to_real(TIME IN){
   520     return (LREAL)IN.tv_sec + ((LREAL)IN.tv_nsec/1000000000);
   559     return (LREAL)IN.tv_sec + ((LREAL)IN.tv_nsec/1000000000);
   521 }
   560 }
   522 inline LINT __time_to_int(TIME IN){
   561 static inline LINT __time_to_int(TIME IN){
   523     return IN.tv_sec;
   562     return IN.tv_sec;
   524 }
   563 }
   525 inline STRING __time_to_string(TIME IN){
   564 static inline STRING __time_to_string(TIME IN){
   526     /*t#5d14h12m18s3.5ms*/
   565     /*t#5d14h12m18s3.5ms*/
   527     STRING res = {0,};
   566     STRING res = __INIT_STRING;
   528     div_t days = div(IN.tv_sec ,86400);
   567     div_t days = div(IN.tv_sec ,86400);
   529     if(!days.rem && IN.tv_nsec == 0){
   568     if(!days.rem && IN.tv_nsec == 0){
   530         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "T#%dd", days.quot);
   569         res.len = snprintf((char*)&res.body, STR_MAX_LEN, "T#%dd", days.quot);
   531     }else{
   570     }else{
   532         div_t hours = div(days.rem, 3600);
   571         div_t hours = div(days.rem, 3600);
   546         }
   585         }
   547     }
   586     }
   548     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   587     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   549     return res;
   588     return res;
   550 }
   589 }
   551 inline STRING __date_to_string(DATE IN){
   590 static inline STRING __date_to_string(DATE IN){
   552     /* D#1984-06-25 */
   591     /* D#1984-06-25 */
   553     STRING res = {0,};
   592     STRING res = __INIT_STRING;
   554     struct tm broken_down_time;
   593     struct tm broken_down_time;
   555     time_t seconds = IN.tv_sec;
   594     time_t seconds = IN.tv_sec;
   556     if (NULL == gmtime_r(&seconds, &broken_down_time)){ /* get the UTC (GMT) broken down time */
   595     if (NULL == gmtime_r(&seconds, &broken_down_time)){ /* get the UTC (GMT) broken down time */
   557         IEC_error();
   596         IEC_error();
   558         return (STRING){7,"D#ERROR"};
   597         return (STRING){7,"D#ERROR"};
   559     }
   598     }
   560     res.len = snprintf((char*)&res.body, STR_MAX_LEN, "D#%d-%2.2d-%2.2d", broken_down_time.tm_year, broken_down_time.tm_mon, broken_down_time.tm_mday);
   599     res.len = snprintf((char*)&res.body, STR_MAX_LEN, "D#%d-%2.2d-%2.2d", broken_down_time.tm_year, broken_down_time.tm_mon, broken_down_time.tm_mday);
   561     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   600     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   562     return res;
   601     return res;
   563 }
   602 }
   564 inline STRING __tod_to_string(TOD IN){
   603 static inline STRING __tod_to_string(TOD IN){
   565     /* TOD#15:36:55.36 */
   604     /* TOD#15:36:55.36 */
   566     STRING res = {0,};
   605     STRING res = __INIT_STRING;
   567     struct tm broken_down_time;
   606     struct tm broken_down_time;
   568     time_t seconds = IN.tv_sec;
   607     time_t seconds = IN.tv_sec;
   569     if (NULL == gmtime_r(&seconds, &broken_down_time)){ /* get the UTC (GMT) broken down time */
   608     if (NULL == gmtime_r(&seconds, &broken_down_time)){ /* get the UTC (GMT) broken down time */
   570         IEC_error();
   609         IEC_error();
   571         return (STRING){9,"TOD#ERROR"};
   610         return (STRING){9,"TOD#ERROR"};
   576         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 / 1000000);
   615         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 / 1000000);
   577     }
   616     }
   578     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   617     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   579     return res;
   618     return res;
   580 }
   619 }
   581 inline STRING __dt_to_string(DT IN){
   620 static inline STRING __dt_to_string(DT IN){
   582     /* DT#1984-06-25-15:36:55.36 */
   621     /* DT#1984-06-25-15:36:55.36 */
   583     STRING res;
   622     STRING res;
   584     struct tm broken_down_time;
   623     struct tm broken_down_time;
   585     time_t seconds = IN.tv_sec;
   624     time_t seconds = IN.tv_sec;
   586     if (NULL == gmtime_r(&seconds, &broken_down_time)){ /* get the UTC (GMT) broken down time */
   625     if (NULL == gmtime_r(&seconds, &broken_down_time)){ /* get the UTC (GMT) broken down time */
   606     }
   645     }
   607     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   646     if(res.len > STR_MAX_LEN) res.len = STR_MAX_LEN;
   608     return res;
   647     return res;
   609 }
   648 }
   610     /* BCD */
   649     /* BCD */
   611 inline ULINT __bcd_to_uint(LWORD IN){
   650 static inline ULINT __bcd_to_uint(LWORD IN){
   612     return IN & 0xf +
   651     return IN & 0xf +
   613            ((IN >>= 4) & 0xf) * 10 + 
   652            ((IN >>= 4) & 0xf) * 10 + 
   614            ((IN >>= 4) & 0xf) * 100 + 
   653            ((IN >>= 4) & 0xf) * 100 + 
   615            ((IN >>= 4) & 0xf) * 1000 + 
   654            ((IN >>= 4) & 0xf) * 1000 + 
   616            ((IN >>= 4) & 0xf) * 10000 + 
   655            ((IN >>= 4) & 0xf) * 10000 + 
   624            ((IN >>= 4) & 0xf) * 1000000000000 + 
   663            ((IN >>= 4) & 0xf) * 1000000000000 + 
   625            ((IN >>= 4) & 0xf) * 10000000000000 + 
   664            ((IN >>= 4) & 0xf) * 10000000000000 + 
   626            ((IN >>= 4) & 0xf) * 100000000000000 + 
   665            ((IN >>= 4) & 0xf) * 100000000000000 + 
   627            ((IN >>= 4) & 0xf) * 1000000000000000;
   666            ((IN >>= 4) & 0xf) * 1000000000000000;
   628 }
   667 }
   629 inline LWORD __uint_to_bcd(ULINT IN){
   668 static inline LWORD __uint_to_bcd(ULINT IN){
   630     return (IN - (IN /= 10))|
   669     return (IN - (IN /= 10))|
   631            (IN - (IN /= 10)) << 4 |
   670            (IN - (IN /= 10)) << 4 |
   632            (IN - (IN /= 10)) << 8 |
   671            (IN - (IN /= 10)) << 8 |
   633            (IN - (IN /= 10)) << 12 |
   672            (IN - (IN /= 10)) << 12 |
   634            (IN - (IN /= 10)) << 16 |
   673            (IN - (IN /= 10)) << 16 |
   647 
   686 
   648 /**************/
   687 /**************/
   649 /* Binary ops */
   688 /* Binary ops */
   650 /**************/
   689 /**************/
   651 #define __ror_(TYPENAME)\
   690 #define __ror_(TYPENAME)\
   652 inline TYPENAME __ror_##TYPENAME( TYPENAME IN, USINT N){\
   691 static inline TYPENAME __ror_##TYPENAME( TYPENAME IN, USINT N){\
   653  N %= 8*sizeof(TYPENAME);\
   692  N %= 8*sizeof(TYPENAME);\
   654  return (IN >> N) | (IN << 8*sizeof(TYPENAME)-N);\
   693  return (IN >> N) | (IN << 8*sizeof(TYPENAME)-N);\
   655 }
   694 }
   656 /* Call previously defined macro for each ANY_NBIT */
   695 /* Call previously defined macro for each ANY_NBIT */
   657 ANY_NBIT(__ror_)
   696 ANY_NBIT(__ror_)
   658 
   697 
   659 #define __rol_(TYPENAME)\
   698 #define __rol_(TYPENAME)\
   660 inline TYPENAME __rol_##TYPENAME( TYPENAME IN, USINT N){\
   699 static inline TYPENAME __rol_##TYPENAME( TYPENAME IN, USINT N){\
   661  N %= 8*sizeof(TYPENAME);\
   700  N %= 8*sizeof(TYPENAME);\
   662  return (IN << N) | (IN >> 8*sizeof(TYPENAME)-N);\
   701  return (IN << N) | (IN >> 8*sizeof(TYPENAME)-N);\
   663 }
   702 }
   664 /* Call previously defined macro for each ANY_NBIT */
   703 /* Call previously defined macro for each ANY_NBIT */
   665 ANY_NBIT(__rol_)
   704 ANY_NBIT(__rol_)
   670 	/**************/
   709 	/**************/
   671 	/*   limit    */
   710 	/*   limit    */
   672 	/**************/
   711 	/**************/
   673 
   712 
   674 #define __limit_(TYPENAME)\
   713 #define __limit_(TYPENAME)\
   675 inline TYPENAME __limit_##TYPENAME( TYPENAME MN, TYPENAME IN, TYPENAME MX){\
   714 static inline TYPENAME __limit_##TYPENAME( TYPENAME MN, TYPENAME IN, TYPENAME MX){\
   676  return IN > MN ? IN < MX ? IN : MX : MN;\
   715  return IN > MN ? IN < MX ? IN : MX : MN;\
   677 }
   716 }
   678 
   717 
   679 /* Call previously defined macro for each concerned type */
   718 /* Call previously defined macro for each concerned type */
   680 ANY_NBIT(__limit_)
   719 ANY_NBIT(__limit_)
   681 ANY_NUM(__limit_)
   720 ANY_NUM(__limit_)
   682 
   721 
   683 #define __limit_time(TYPENAME)\
   722 #define __limit_time(TYPENAME)\
   684 inline TIME __limit_##TYPENAME( TYPENAME MN, TYPENAME IN, TYPENAME MX){\
   723 static inline TIME __limit_##TYPENAME( TYPENAME MN, TYPENAME IN, TYPENAME MX){\
   685     return __TIME_CMP(IN, MN) > 0 ? /* IN>MN ?*/\
   724     return __TIME_CMP(IN, MN) > 0 ? /* IN>MN ?*/\
   686            __TIME_CMP(IN, MX) < 0 ? /* IN<MX ?*/\
   725            __TIME_CMP(IN, MX) < 0 ? /* IN<MX ?*/\
   687            IN : MX : MN;\
   726            IN : MX : MN;\
   688 }
   727 }
   689 
   728 
   690 /* Call previously defined macro for each concerned type */
   729 /* Call previously defined macro for each concerned type */
   691 ANY_DATE(__limit_time)
   730 ANY_DATE(__limit_time)
   692 __limit_time(TIME)
   731 __limit_time(TIME)
   693 
   732 
   694 inline STRING __limit_STRING( STRING MN, STRING IN, STRING MX){
   733 static inline STRING __limit_STRING( STRING MN, STRING IN, STRING MX){
   695     return __STR_CMP(IN, MN) > 0 ? __STR_CMP(IN, MX) < 0 ? IN : MX : MN;
   734     return __STR_CMP(IN, MN) > 0 ? __STR_CMP(IN, MX) < 0 ? IN : MX : MN;
   696 }
   735 }
   697 
   736 
   698     /**************/
   737     /**************/
   699     /*     MAX    */
   738     /*     MAX    */
   721 #define VA_ARGS_DATE DATE
   760 #define VA_ARGS_DATE DATE
   722 #define VA_ARGS_TOD TOD
   761 #define VA_ARGS_TOD TOD
   723 #define VA_ARGS_DT DT
   762 #define VA_ARGS_DT DT
   724 
   763 
   725 #define __extrem_(fname,TYPENAME, COND) \
   764 #define __extrem_(fname,TYPENAME, COND) \
   726 inline TYPENAME fname##TYPENAME( UINT param_count, TYPENAME op1, ...){\
   765 static inline TYPENAME fname##TYPENAME( UINT param_count, TYPENAME op1, ...){\
   727   va_list ap;\
   766   va_list ap;\
   728   UINT i;\
   767   UINT i;\
   729   \
   768   \
   730   va_start (ap, op1);         /* Initialize the argument list.  */\
   769   va_start (ap, op1);         /* Initialize the argument list.  */\
   731   \
   770   \
   766 
   805 
   767     /**************/
   806     /**************/
   768     /*     MUX    */
   807     /*     MUX    */
   769     /**************/
   808     /**************/
   770 #define __mux_(TYPENAME) \
   809 #define __mux_(TYPENAME) \
   771 inline TYPENAME __mux_##TYPENAME( UINT param_count, UINT K, TYPENAME op1, ...){\
   810 static inline TYPENAME __mux_##TYPENAME( UINT param_count, UINT K, ...){\
   772   va_list ap;\
   811   va_list ap;\
   773   UINT i;\
   812   UINT i;\
       
   813   TYPENAME tmp = __INIT_##TYPENAME;\
   774   \
   814   \
   775   va_start (ap, op1);         /* Initialize the argument list.  */\
   815   va_start (ap, K);         /* Initialize the argument list.  */\
   776   \
   816   \
   777   for (i = 0; i < param_count; i++){\
   817   for (i = 0; i < param_count; i++){\
   778     if(K == i){\
   818     if(K == i){\
   779         TYPENAME tmp = va_arg (ap, VA_ARGS_##TYPENAME);\
   819         tmp = va_arg (ap, VA_ARGS_##TYPENAME);\
   780         va_end (ap);                  /* Clean up.  */\
   820         va_end (ap);                  /* Clean up.  */\
   781         return tmp;\
   821         return tmp;\
   782     }else{\
   822     }else{\
   783         va_arg (ap, VA_ARGS_##TYPENAME);\
   823         va_arg (ap, VA_ARGS_##TYPENAME);\
   784     }\
   824     }\
   785   }\
   825   }\
   786   \
   826   \
   787   va_end (ap);                  /* Clean up.  */\
   827   va_end (ap);                  /* Clean up.  */\
   788   return op1;\
   828   return tmp;\
   789 }
   829 }
   790 
   830 
   791 ANY(__mux_)
   831 ANY(__mux_)
   792 
   832 
   793 /**************/
   833 /**************/
   794 /* Comparison */
   834 /* Comparison */
   795 /**************/
   835 /**************/
   796 
   836 
   797 #define __compare_(fname,TYPENAME, COND) \
   837 #define __compare_(fname,TYPENAME, COND) \
   798 inline BOOL fname##TYPENAME( UINT param_count, TYPENAME op1, ...){\
   838 static inline BOOL fname##TYPENAME( UINT param_count, TYPENAME op1, ...){\
   799   va_list ap;\
   839   va_list ap;\
   800   UINT i;\
   840   UINT i;\
   801   \
   841   \
   802   va_start (ap, op1);         /* Initialize the argument list.  */\
   842   va_start (ap, op1);         /* Initialize the argument list.  */\
   803   \
   843   \