3
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
7
** Abstract: An API declaration for the general purpose and utility routines and stuff ...
9
** Author: Ruslan R. Laishev
11
** Creation date: 4-SEP-2017
13
** Modification history:
15
** 14-SEP-2017 RRL Added __util$iszero() inline routine.
16
** 22-SEP-2017 RRL Added __util$hex2bin() inline routine.
17
** 26-SEP-2017 RRL Added __util$strcat_rx - concatenates given list of strings into the single area.
18
** 5-OCT-2017 RRL Added __util$syslog() routine declaration;
19
** changed __util$deflog() routine declaration;
21
** 20-OCT-2017 RRL Added __util$uuid2str() - convert UUID into from binary form to ASCII text string.
23
** 27-OCT-2017 RRL Added __util$movc5 (stolen OpenVMS version of the lib$movc5) - copy source string to destionation
24
** place, fill rest of output buffer with a given character.
26
** 14-NOV-2017 RRL Added __util$str2asc() - copy ASCIZ string to the ASCIC container.
28
** 11-MAY-2018 RRL Added __util$fill() - fill buffer with the given pattern data
30
** 30-MAY-2018 RRL Correct pointer type to exclude compilation error under VC 2017 in the __util$fill().
32
** 7-JUN-2018 RRL Correct pointer type to compile under GCC.
34
** 15-OCT-2018 RRL Added __ASC_TYPE__ macro to flag that ASC type is defined here.
36
** 25-JUN-2019 RRL Redefined macro $TRACE() to eliminate "if (cond) ..."
38
** 10-JUL-2019 RRL Warning fix.
42
#define _CRT_SECURE_NO_WARNINGS 1
45
#include <sys/timeb.h>
49
#ifndef __STARLET$UTILS__
50
#define __STARLET$UTILS__ 1
57
#define __MODULE__ NULL
70
#pragma GCC diagnostic push
71
#pragma GCC diagnostic ignored "-Wparentheses"
74
#define CRLFCRLF_LW 0x0a0d0a0d
75
#define CRLFCRLF "\r\n\r\n"
79
* A Macro to compute an arrays size in elements at compilation time
81
#define $ARRSZ(a) (sizeof(a)/sizeof(a[0]))
85
Performs a conditional atomic compare and update operation
86
involving one or two longwords in the same lock region. The value
87
pointed to by source is compared with the longword old_value. If
88
they are equal, the longword new_value is conditionally stored into
89
the value pointed to by dest.
91
The store will not complete if the compare yields unequal values or
92
if there is an intervening store to the lock region involved. To
93
be in the same lock region, source and dest must point to aligned
94
longwords in the same naturally aligned 16-byte region.
96
The function returns 0 if the store does not complete, and 1 if the
101
int __CMP_STORE_LONG (volatile void *source, int old_value,
103
volatile void *dest);
105
These built-in functions perform an atomic compare and swap. That is,
106
if the current value of *ptr is oldval, then write newval into *ptr.
108
The “bool” version returns true if the comparison is successful and newval
109
is written. The “val” version returns the contents of *ptr before the operation.
111
#define $CMP_STORE_LONG(src, old_val, new_val) __sync_bool_compare_and_swap((int *) src, (int) old_val, (int) new_val )
119
#define inline __inline
129
inline static int ____time(struct timespec *tv)
134
timespec_get(tv, TIME_UTC);
136
//tv->tv_nsec *=1024;
138
struct _timeb timebuffer;
140
_ftime_s ( &timebuffer );
142
tv->tv_sec = timebuffer.time;
143
tv->tv_nsec = timebuffer.millitm;
154
inline static int ____time(struct timespec *tv)
156
clock_gettime(CLOCK_REALTIME, tv);
166
inline static void __util$timbuf(time_t *__src, struct tm * __dst)
174
localtime_s(__dst, __src ? __src : &now);
176
localtime_r(__src ? __src : &now, __dst);
180
__dst->tm_year += 1900;
184
#ifndef __PATH_SEPARATOR
186
#define __PATH_SEPARATOR '/'
188
#define __PATH_SEPARATOR '\\'
193
#ifndef __PATH_SEPARATOR_S
195
#define __PATH_SEPARATOR_S "/"
197
#define __PATH_SEPARATOR_S "\\"
206
typedef struct __ile2 {
207
unsigned short code, /* Item List Element code */
208
len; /* Length of data */
209
char * ptr; /* Pointer to data */
212
typedef struct __ile3 {
213
unsigned short code, /* Item List Element code */
214
len; /* A size of the buffer */
215
char * ptr; /* An address of buffer to accept data */
216
unsigned short * retlen;/* An actual length of the data returned in the buffer */
220
/* Macros to initialize Item List with a given values */
221
#define $ILE2INI(code, len, ptr) {code, len, (char *)ptr}
222
#define $ILE3INI(ile, code, len, ptr, retlen) {ile.code = code, ile.len = len, ile.ptr = (char *)ptr, ile.retlen = retlen}
227
* Queue & Entry types & macros definitions
234
** Special type is supposed to be used as a part of complex types. Typical usage is:
235
** struct my_buffer {
236
** ENTRY links; // A part to be used by $INSQ/$REMQ macroses
238
** unsigned short buflen,
243
typedef struct __entry {
244
struct __entry *left, /* References (address) to left and right elements in the queue */
245
*right; /* NULL if the element is first or last in the queue */
246
void * queue; /* A link to __QUEUE structure */
251
** Special data type to help organize of duble-linked lists (queues).
253
typedef struct __queue {
254
ENTRY *head, *tail; /* An addresses of first and last element of the queue */
257
SRWLOCK lock; /* A spinlock to coordinate an access to the head and tail*/
262
unsigned count; /* An actual elements/entries count in the queue */
265
/* Macro to initialize a __QUEUE object with defaults. Typical usage is:
268
* __QUEUE que = QUEUE_INITIALIZER;
272
#define QUEUE_INITIALIZER { (ENTRY *) 0, (ENTRY *) 0, 0, 0 }
277
/* Logging facility */
279
#define __FAC__ "UTILS"
280
#define __FAC$_UTILS__ 0x01
284
#define STS$K_SUCCESS 1
285
#define STS$K_ERROR 2
287
#define STS$K_UNDEF 8
288
#define STS$K_SYSLOG 16 /* This option force sending message to the syslog service */
290
#define $STS_ERROR(code) ( ((code) & STS$K_ERROR ) || ((code) & STS$K_ERROR) )
293
* +---------------------+--------------------------+-------------------+
294
* | Facility (16 bits) | Message Number (13 bits) | Severity (3) bits |
295
* +---------------------+--------------------------+-------------------+
297
#define $FAC(code) ((code) >> 16)
298
#define $MSG(code) ((code) >> 3)
299
#define $SEV(code) ((code) & 0x7)
302
unsigned __util$log (const char *fac, unsigned severity, const char *fmt, ...);
303
unsigned __util$logd (const char *fac, unsigned severity, const char *fmt, const char *mod, const char *func, unsigned line, ...);
304
unsigned __util$log2buf (void *out, int outsz, int * outlen, const char *fac, unsigned severity, const char *fmt, ...);
305
unsigned __util$syslog (int fac, int sev, const char *tag, const char *msg, int msglen);
308
#define $LOG(severity, fmt, ...) __util$logd(__FAC__, severity, fmt, __MODULE__, __FUNCTION__ , __LINE__ , ## __VA_ARGS__)
309
#define $IFLOG(f, severity, fmt, ...) f ? __util$logd(__FAC__, severity, fmt, __MODULE__, __FUNCTION__ , __LINE__ , ## __VA_ARGS__) : severity
311
#define $LOG(severity, fmt, ...) __util$log(__FAC__, severity, fmt, ## __VA_ARGS__)
312
#define $IFLOG(f, severity, fmt, ...) f ? __util$logd(__FAC__, severity, fmt, __MODULE__, __FUNCTION__ , __LINE__ , ## __VA_ARGS__) : severity
319
* Description: Implement spinlock logic by using GCC builtin, set the lock value to 1.
322
* lock: a pointer to longword, to accept a lock flag
332
inline static int __util$lockspin (void volatile * lock)
334
unsigned i = 0xffffffffU;
340
for ( ; i && !(status = TryAcquireSRWLockExclusive((SRWLOCK *) lock)); i--);
342
return status ? STS$K_SUCCESS : STS$K_ERROR;
344
for ( ; i && __sync_lock_test_and_set(((int *) lock), 1); i--)
345
for (; i && (* ((int *)lock)); i--);
347
return i ? STS$K_SUCCESS : STS$K_ERROR;
352
#define $LOCK_LONG(lock) __util$lockspin(lock)
356
* Description: Release has been set lock flag, set the lock value to 0.
359
* lock: a pointer to longword, to accept a lock flag
364
inline static int __util$unlockspin (void * lock)
368
ReleaseSRWLockExclusive( (SRWLOCK *) lock);
370
__sync_lock_release((int *) lock);
373
return STS$K_SUCCESS;
378
#define $UNLOCK_LONG(lock) __util$unlockspin(lock)
384
* Description: Remove all entries from the given queue
387
* que: A pointer to __QUEUE structure
390
* count: A count of entries in the __QUEUE before cleanuping
395
inline static int __util$clrqueue (void * que, unsigned * count)
397
__QUEUE * _que = (__QUEUE *) que;
404
if ( !_que || !count )
408
return STS$K_SUCCESS;
413
if ( !(1 & __util$lockspin( &_que->lock)) )
416
/* Store entries counter */
417
*count = nums = _que->count;
419
/* Run over all entries, zeroing link to queue ... */
420
for ( _ent = _que->head; nums; nums--, _ent = _ent->right)
424
_que->head = _que->tail = NULL;
428
* Release the spinlock
430
return __util$unlockspin(&_que->lock);
435
* Description: Insert a new entry at tail of the queue
438
* que: A pointer to __QUEUE structure
439
* ent: New ENTRY pointer
442
* count: A count of entries in the __QUEUE before inserting
448
#define UTIL$S_INVARG 0x102
449
#define UTIL$S_INQUE 0x202
450
#define UTIL$S_NOLOCK 0x202
452
inline static int __util$insqtail (void * que, void * ent, unsigned * count)
454
__QUEUE * _que = (__QUEUE *) que;
455
ENTRY * _entold, *_entnew = (ENTRY *) ent;
460
if ( !_que || !ent || !count )
461
return UTIL$S_INVARG;
463
/* Check that ENTRY has not been in the a __QUEUE already */
464
if ( _entnew->queue == que )
465
return STS$K_SUCCESS; /* Already: in the __QUEUE*/
466
else if ( _entnew->queue ) /* in other __QUEUE */
473
if ( !(1 & __util$lockspin( &_que->lock)) )
474
return UTIL$S_NOLOCK;
476
*count = _que->count;
478
if ( _entold = _que->tail )
479
_entold->right = _entnew;
480
else _que->head = _entnew;
482
_entnew->left = _entold;
483
_entnew->right = NULL;
484
_entnew->queue = que;
485
_que->tail = _entnew;
490
* Release the spinlock
492
return __util$unlockspin(&_que->lock);
496
* Description: Insert a new entry at head of the queue
499
* que: A pointer to __QUEUE structure
500
* ent: New ENTRY pointer
503
* count: A count of entries in the __QUEUE before inserting
508
inline static int __util$insqhead (void * que, void * ent, unsigned * count)
510
__QUEUE * _que = (__QUEUE *) que;
511
ENTRY * _entold, *_entnew = (ENTRY *) ent;
516
if ( !_que || !ent || !count )
519
/* Check that ENTRY has not been in the a __QUEUE already */
520
if ( _entnew->queue == que )
521
return STS$K_SUCCESS; /* Already: in the __QUEUE*/
522
else if ( _entnew->queue ) /* in other __QUEUE */
528
if ( !(1 & __util$lockspin( &_que->lock)) )
531
*count = _que->count;
533
if ( _entold = _que->head )
534
_entold->left = _entnew;
535
else _que->tail = _entnew;
537
_entnew->right = _entold;
538
_entnew->left = NULL;
539
_entnew->queue = que;
540
_que->head = _entnew;
545
* Release the spinlock
547
return __util$unlockspin(&_que->lock);
552
* Description: Remove an entry from the the current place in the queue
555
* que: A pointer to __QUEUE structure
558
* ent: A removed entry
559
* count: A count of entries in the __QUEUE before inserting
564
inline static int __util$remqent (void * que, void *ent, unsigned * count)
566
__QUEUE * _que = (__QUEUE *) que;
567
ENTRY * _ent = (ENTRY *) ent, *_entleft;
572
if ( !_que || !ent || !count )
575
/* Check that ENTRY is belong to the __QUEUE */
576
if ( _ent->queue != que )
582
if ( !(1 & __util$lockspin( &_que->lock)) )
585
if ( !(*count = _que->count) )
587
__util$unlockspin(&_que->lock);
588
return STS$K_SUCCESS;
594
_entleft = _ent->left;
595
_entleft->right = _ent->right;
598
* Reset head & tail if queue is empty
600
if ( !(--_que->count) )
601
_que->head = _que->tail = NULL;
603
_ent->left = _ent->right = NULL;
607
* Release the spinlock
609
__util$unlockspin(&_que->lock);
611
return STS$K_SUCCESS;
621
* Description: Remove an entry from the tail of the queue
624
* que: A pointer to __QUEUE structure
627
* ent: A removed entry
628
* count: A count of entries in the __QUEUE before inserting
633
inline static int __util$remqtail (void * que, void **ent, unsigned * count)
635
__QUEUE * _que = (__QUEUE *) que;
636
ENTRY * _entleft, * _entright = NULL;
641
if ( !_que || !ent || !count )
647
if ( !(1 & __util$lockspin( &_que->lock)) )
650
if ( !(*count = _que->count) )
652
__util$unlockspin(&_que->lock);
653
return STS$K_SUCCESS;
659
if ( _entright = _que->tail )
661
if ( _entleft = _entright->left )
662
_entleft->right = NULL;
664
_que->tail = _entleft;
668
_entright->left = _entright->right = NULL;
669
_entright->queue = NULL;
672
* Reset head & tail if queue is empty
674
if ( !(--_que->count) )
675
_que->head = _que->tail = NULL;
678
* Release the spinlock
680
__util$unlockspin(&_que->lock);
686
return _entright ? STS$K_SUCCESS : STS$K_ERROR;
690
* Description: Remove an entry from the head of the queue
693
* que: A pointer to __QUEUE structure
696
* ent: A removed entry
697
* count: A count of entries in the __QUEUE before inserting
702
inline static int __util$remqhead (void * que, void **ent, unsigned * count)
704
__QUEUE * _que = (__QUEUE *) que;
705
ENTRY * _entleft = NULL, * _entright;
710
if ( !_que || !ent || !count )
716
if ( !(1 & __util$lockspin( &_que->lock)) )
719
if ( !(*count = _que->count) )
721
__util$unlockspin(&_que->lock);
722
return STS$K_SUCCESS;
728
if ( _entleft = _que->head )
730
if ( _entright = _entleft->right )
731
_entright->left = NULL;
733
_que->head = _entright;
740
_entleft->left = _entleft->right = NULL;
741
_entleft->queue = NULL;
744
* Reset head & tail if queue is empty
746
if ( !(--_que->count) )
747
_que->head = _que->tail = NULL;
750
* Release the spinlock
752
__util$unlockspin(&_que->lock);
759
return _entleft ? STS$K_SUCCESS : STS$K_ERROR;
763
* Description: Move an existen entry at head of queue.
766
* que: A pointer to __QUEUE structure
767
* ent: A pointer to ENTRY to be moved at head of queue
775
inline static int __util$movqhead (void * que, void **ent)
778
__QUEUE * _que = (__QUEUE *) que;
779
ENTRY * entp, * _entleft = NULL, * _entright = NULL;
790
if ( !(1 & __util$lockspin( &_que->lock)) )
793
if ( !(_que->count) )
795
__util$unlockspin(&_que->lock);
796
return STS$K_SUCCESS;
800
* Lookup in the queue an entry with a given address
802
for (i = 0, entp = _que->head; i < _que->count; i++, entp = entp->right)
804
if ( entp == (ENTRY *) ent )
809
* Is the entry already on head of the queue?
812
return __util$unlockspin(&_que->lock);
815
* Is the entry with a given address live in the queue?
819
__util$unlockspin(&_que->lock);
824
* Exclude has been found entry from the chain
826
if ( _entleft = entp->left )
827
_entleft->right = entp->right;
829
else assert ( entp->left ); /* left link can be only on first entry! */
833
if ( _entright= entp->right )
834
_entright->left = entp->left;
837
* Put has been found entry at head of tail
839
entp->right = _que->head;
844
* Release the spinlock
846
return __util$unlockspin(&_que->lock);
850
* Description: Move an existen entry to end of queue.
853
* que: A pointer to __QUEUE structure
854
* ent: A pointer to ENTRY to be moved at head of queue
862
inline static int __util$movqtail (void * que, void **ent)
865
__QUEUE * _que = (__QUEUE *) que;
866
ENTRY * entp, * _entleft = NULL, * _entright = NULL;
877
if ( !(1 & __util$lockspin( &_que->lock)) )
880
if ( !(_que->count) )
882
__util$unlockspin(&_que->lock);
883
return STS$K_SUCCESS;
887
* Lookup in the queue an entry with a given address
889
for (i = 0, entp = _que->head; i < _que->count; i++, entp = entp->right)
891
if ( entp == (ENTRY *) ent )
896
* Is the entry already at tail ?
898
if ( i == _que->count )
899
return __util$unlockspin(&_que->lock);
902
* Is the entry with a given address live in the queue?
906
__util$unlockspin(&_que->lock);
911
* Exclude has been found entry from the chain
913
if ( _entleft = entp->left )
914
_entleft->right = _entright;
916
if ( _entright= entp->right )
917
_entright->left = _entleft;
919
else assert( entp->right ); /* Right link can be on the last entry ! */
923
* Put has been found entry at tail of queue
925
entp->left = _que->tail;
930
* Release the spinlock
932
return __util$unlockspin(&_que->lock);
936
* A set of macros to implement good old hardcore school ... of VMS-ish double linked lists - queue,
937
* all queue modifications using interlocking by using GCC spinlocks.
939
* Typical scenario of using:
941
* __QUEUE myqueue = QUEUE_INITIALIZER;
943
* ENTRY entry; // A space reservation for stuff has been used my the queue's macros
944
* unsigned short len;
945
* unsigned char buf[128];
952
* // The queue preinitialization, by inserting element from statical allocated array
953
* for (int i ; i < sizeof(messages)/sizeof(messages[0)]); i++)
954
* $INSQTAIL(&myqueue, &messages[i], &count);
959
/* Insert a new entry into the queue at head, return condition status, count - a number of
960
* entries in the queue before addition of the new element
962
#define $INSQHEAD(que, ent, count) __util$insqhead ((__QUEUE *) que, (void *) ent, (unsigned *) count)
964
/* Insert a new entry into the queue at tail, return condition status, count - a number of
965
* entries in the queue before addition of the new element
967
#define $INSQTAIL(que, ent, count) __util$insqtail ((__QUEUE *) que, (void *) ent, (unsigned *) count)
969
/* Get/Remove an entry from head of the queue, return condition status, count - a number of
970
* entries in the queue before removing of the element
972
#define $REMQHEAD(que, ent, count) __util$remqhead ((__QUEUE *) que, (void **) ent, (unsigned *) count)
974
/* Get/Remove an entry from tail of the queue, return condition status, count - a number of
975
* entries in the queue before removing of the element
977
#define $REMQTAIL(que, ent, count) __util$remqtail ((__QUEUE *) que, (void **)ent, (unsigned *) count)
980
/* Move an entry with a given address from current position of the queue to head of the queue,
981
* return condition status;
983
#define $MOVQHEAD(que, ent) __util$movqhead ((__QUEUE *) que, (void *) ent)
985
/* Move an entry with a given address from current position of the queue to tail of the queue,
986
* return condition status;
988
#define $MOVQTAIL(que, ent) __util$movqtail ((__QUEUE *) que, (void *) ent)
990
/* Remove a givent entry from the queueue.
992
#define $REMQENT(que, ent, count) __util$remqent ((__QUEUE *) que, (void **)ent, (unsigned *) count)
995
/* Remove all entries form the queue.
997
#define $CLRQUE(que, count) __util$clrqueue ((__QUEUE *) que, (unsigned *) count)
1000
/* Macros to return minimal/maximum value from two given integers */
1001
inline static int __util$min (int x, int y)
1003
return (x < y) ? x : y;
1005
#define $MIN(x, y) __util$min((int) (x), (int) (y))
1007
inline static int __util$max (int x, int y)
1009
return (x > y) ? x : y;
1011
#define $MAX(x, y) __util$max((int) (x), (int) (y))
1013
/* Return a result of checking value in the given range, 0/false - out of range, 1/true - is in range */
1014
inline static int __util$isinrange (int x, int __min__, int __max__ )
1016
int left = $MIN(__min__, __max__) , right = $MAX(__min__, __max__);
1018
return ( (x < left) || ( x > right ) ) ? 0 : 1;
1021
/* Return result of checking value between two borders: min and max */
1022
#define $ISINRANGE(x, __min__, __max__) __util$isinrange(x, (__min__), (__max__))
1025
/* Return a result of checking value in the given range include border,
1026
* 0/false - out of range, 1/true - is in range
1028
inline static int __util$isinrange2 (int x, int __min__, int __max__ )
1030
int left = $MIN(__min__, __max__) , right = $MAX(__min__, __max__);
1032
return ( (x <= left) || ( x >= right ) ) ? 0 : 1;
1035
/* Return result of checking value between two borders: min and max */
1036
#define $ISINRANGE2(x, __min__, __max__) __util$isinrange2(x, (__min__), (__max__))
1039
/* Return value bound to left or right border eg. x = [min; max] */
1040
inline static int __util$range (int x, int __min__, int __max__ )
1042
int left = $MIN(__min__, __max__) , right = $MAX(__min__, __max__);
1050
/* Return value bound to left or right border eg. x = [min; max] */
1051
#define $RANGE(x, __min__, __max__) __util$range(x, __min__, __max__)
1057
* Description: check buffer for consecutive zero octets
1061
* bufp: buffer to check, address
1062
* bufsz: a length of data in the buffer
1066
* SS$_NORMAL - the buffer is zero filled
1067
* STS$K_WARN - the buffer is not zero filled
1070
* @brief __util$iszero - check buffer for consecutive zero octets
1071
* @param bufp : buffer to check, address
1072
* @param bufsz : a length of data in the buffer
1074
* * SS$_NORMAL - the buffer is zero filled
1075
* STS$K_WARN - the buffer is not zero filled
1077
inline static int __util$iszero (
1083
unsigned char *__bufp = (unsigned char *) bufp;
1085
#if ( (defined ULLONG_MAX && (ULLONG_MAX > UINT_MAX)) || (defined ULONG_LONG_MAX && (ULONG_LONG_MAX > UINT_MAX)) )
1087
//#pragma message ("%CC-I-ULLONG64, unsigned long long - 64 bits")
1089
/* Step by 8 octets ... */
1090
for (i = bufsz/sizeof(unsigned long long); i; i--, __bufp += sizeof(unsigned long long) )
1092
if ( *((unsigned long long *) __bufp ) )
1095
#endif // (sizeof(unsigned long long)) > sizeof(unsigned int long) )
1097
/* Compute remainder octets in the buffer */
1098
bufsz %= sizeof(unsigned int long);
1100
/* Step by 4 octets ... */
1101
for (i = bufsz/sizeof(unsigned int); i; i--, __bufp += sizeof(unsigned int) )
1103
if ( *((unsigned int *) __bufp ) )
1107
/* Compute remainder octets in the buffer */
1108
bufsz %= sizeof(unsigned int);
1110
/* Step by 2 octets ... */
1111
for (i = bufsz/sizeof(unsigned short); i; i--, __bufp += sizeof(unsigned short) )
1113
if ( *((unsigned short *) __bufp ) )
1117
/* Compute remainder octets in the buffer */
1118
bufsz %= sizeof(unsigned short);
1120
if ( bufsz && *__bufp )
1123
return STS$K_SUCCESS;
1128
* @brief __util$bzero - zeroing memory block
1129
* @param bufp : buffer to check, address
1130
* @param bufsz : a length of data in the buffer
1132
* SS$_NORMAL - the buffer is zero filled
1135
inline static int __util$bzero (
1141
unsigned char *__bufp = (unsigned char *) bufp;
1144
* There is a place for optimization : align a memory address at head
1145
* of the memory block
1148
#if ( (defined ULLONG_MAX && (ULLONG_MAX > UINT_MAX)) || (defined ULONG_LONG_MAX && (ULONG_LONG_MAX > UINT_MAX)) )
1150
//#pragma message ("%CC-I-ULLONG64, unsigned long long - 64 bits")
1152
/* Step by 8 octets ... */
1153
for (i = bufsz/sizeof(unsigned long long); i; i--, __bufp += sizeof(unsigned long long) )
1154
*((unsigned long long *) __bufp ) = 0;
1155
#endif // (sizeof(unsigned long long)) > sizeof(unsigned int) )
1157
/* Compute remainder octets in the buffer */
1158
bufsz %= sizeof(unsigned long long);
1160
/* Step by 4 octets ... */
1161
for (i = bufsz/sizeof(unsigned int); i; i--, __bufp += sizeof(unsigned int) )
1162
*((unsigned int *) __bufp ) = 0;
1164
/* Compute remainder octets in the buffer */
1165
bufsz %= sizeof(unsigned int);
1167
/* Step by 2 octets ... */
1168
for (i = bufsz/sizeof(unsigned short); i; i--, __bufp += sizeof(unsigned short) )
1169
if ( *((unsigned short *) __bufp ) )
1171
/* Compute remainder octets in the buffer */
1172
bufsz %= sizeof(unsigned short);
1177
return STS$K_SUCCESS;
1184
/* Tracing facility */
1185
void __util$trace (int cond, const char *fmt, const char *mod, const char *func, unsigned line, ...);
1189
#define $TRACE(fmt, ...) __util$trace(1, fmt, __MODULE__, __FUNCTION__, __LINE__ , ## __VA_ARGS__)
1193
#define $IFTRACE(cond, fmt, ...) __util$trace(cond, fmt, __MODULE__, __FUNCTION__, __LINE__ , ## __VA_ARGS__)
1196
#define $TRACE(fmt, ...) {}
1197
#define $IFTRACE(cond, fmt, ...) {}
1201
/* Counted (length-byte-prefixed) ASCII string, see VMS's ASCIC */
1204
#define ASC$K_SZ 255
1211
#define __ASC_TYPE__ 1
1215
/* Initialize an ASCIC structure by given string */
1216
#define $ASCDECL(a,sts) ASC a = {(unsigned char)sizeof(sts)-1,(sts)}
1217
#define $ASCINI(a) (unsigned char)sizeof(a)-1,(a)
1218
#define $ASCLEN(a) (((ASC *) a)->len)
1219
#define $ASCPTR(a) (((ASC *) a)->sts)
1220
#define $ASC(a) (((ASC *) a)->len),(((ASC *) a)->sts)
1224
/* Copying ASCIIZ string to ASCIC container */
1225
inline static int __util$str2asc
1231
$ASCLEN(dst) = (unsigned char) strnlen(src, ASC$K_SZ);
1232
memcpy($ASCPTR(dst), src, $ASCLEN(dst) );
1233
dst->sts[dst->len] = '\0';
1235
return $ASCLEN(dst);
1239
/* Comparing two ASCIC */
1240
inline static int __util$cmpasc
1248
if ( status = ($ASCLEN(s1) - $ASCLEN(s2)) )
1251
return memcmp($ASCPTR(s1), $ASCPTR(s2), $ASCLEN(s1) );
1254
#define $DUMPHEX(s,l) __util$dumphex(__FUNCTION__, __LINE__ , s, l)
1255
void __util$dumphex (char *__fi, unsigned __li, void * src, unsigned short srclen);
1258
** @RRL: Perform an addittion of two times with overflow control and handling.
1260
inline static void __util$add_time(struct timespec* time1, struct timespec* time2, struct timespec* result_time)
1262
time_t sec = time1->tv_sec + time2->tv_sec;
1263
long nsec = time1->tv_nsec + time2->tv_nsec;
1265
sec += nsec / 1000000000L;
1266
nsec = nsec % 1000000000L;
1268
result_time->tv_sec = sec;
1269
result_time->tv_nsec = nsec;
1274
** @RRL: Perform a subsctration of two times.
1278
struct timespec diff(struct timespec start, struct timespec end)
1280
struct timespec temp;
1281
if ((end.tv_nsec-start.tv_nsec)<0) {
1282
temp.tv_sec = end.tv_sec-start.tv_sec-1;
1283
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
1285
temp.tv_sec = end.tv_sec-start.tv_sec;
1286
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
1292
inline static void __util$sub_time(struct timespec * time1, struct timespec* time2, struct timespec* result_time)
1294
struct timespec temp;
1296
temp.tv_sec = time1->tv_sec - time2->tv_sec;
1297
temp.tv_nsec = time1->tv_nsec - time2->tv_nsec;
1299
*result_time = temp;
1306
* 0 - time1 == time2
1307
* 0 > - time1 < time2
1308
* 0 < - time1 > time2
1310
inline static int __util$cmp_time(struct timespec * time1, struct timespec* time2)
1312
if ( time1->tv_sec - time2->tv_sec )
1313
return (time1->tv_sec - time2->tv_sec);
1315
return (time1->tv_nsec - time2->tv_nsec);
1319
* INCrement , DECrement ...
1321
#define $ATOMIC_INC(val) __sync_fetch_and_add (&val, 1)
1322
#define $ATOMIC_DEC(val) __sync_fetch_and_sub (&val, 1)
1325
* Processing command line options stuff
1327
#define OPTS$K_INT 0 /* Integer parameter type */
1328
#define OPTS$K_STR 1 /* Parameter is string */
1329
#define OPTS$K_OPT 2 /* Presence - is ON, missing - - OFF */
1330
#define OPTS$K_PORT 3 /* A TCP/IP port number, NBO */
1331
#define OPTS$K_IP4 4 /* A TCP/IP IP adddres , NBO */
1332
#define OPTS$K_CONF 5 /* The options is a name of configuration
1333
file to be processed recursively */
1334
#define OPTS$K_PWD 6 /* Parameter is password - don't show it*/
1337
typedef struct _opts {
1338
ASC name; /* Options name */
1339
void * ptr; /* A pointer to buffer which will accept an option's value */
1340
size_t sz; /* A size of target buffer */
1341
int type; /* Value type, see OPTS$K_* constants */
1344
#define OPTS_NULL { {0, 0}, NULL, 0, 0}
1346
int __util$getparams (int, char *[], OPTS *);
1347
int __util$readparams (int, char *[], OPTS *);
1348
int __util$readconfig (char *, OPTS *);
1349
int __util$showparams (OPTS * opts);
1351
int __util$deflog (const char *, const char *);
1352
int __util$rewindlogfile (int);
1353
int __util$pattern_match (char * str$, char * pattern$);
1355
char * __util$strstr (char *s1, size_t s1len, char *s2, size_t s2len);
1357
unsigned __util$crc32c (unsigned int crc, const void *buf, size_t buflen);
1360
* @brief __util$hex2bin - convert a hexdecimal string in binary representative.
1361
* It's expected that output buffer have enough space to accept
1362
* <(source_length + 1) / 2> octets.
1364
* @param srchex - An address of source data buffer to convert from
1365
* @param dstbin - An address of the output buffer to accept converted octets
1366
* @param srchexlen - A length of the source data
1368
* @return - A length of the data in the output buffer
1371
inline static int __util$hex2bin
1375
unsigned short srchexlen
1378
unsigned char c, l = 0, h = 0, *__srchex = (unsigned char *) srchex, *__dstbin = (unsigned char *) dstbin;
1379
int retlen = (srchexlen + 1) / 2, i;
1381
/* We will converting from tail to head */
1382
__srchex += (srchexlen - 1);
1383
__dstbin += (retlen - 1);
1385
for( i = (srchexlen / 2); i; i--, __dstbin--, __srchex--)
1387
c = tolower(*__srchex);
1388
l = ((c) <= '9') ? (c) - '0' : (c) - 'a' + 10;
1392
c = tolower(*__srchex);
1393
h = ((c) <= '9') ? (c) - '0' : (c) - 'a' + 10;
1396
*__dstbin = c = l | (h << 4);
1401
c = tolower(*__srchex);
1402
l = ((c) <= '9') ? (c) - '0' : (c) - 'a' + 10;
1413
* @brief __util$bin2hex - convert a sequence of bytes from binary from
1414
* to a hexadecimal string. It's expected that output buffer have
1415
* enough space to accept <source_length * 2> characters.
1417
* @param srcbin - An address of source data buffer to convert from
1418
* @param dsthex - An address of the output buffer to accept hex-string
1419
* @param srcbinlen - A length of the source data
1421
* @return - A length of the data in the output buffer
1424
inline static int __util$bin2hex
1428
unsigned short srcbinlen
1431
unsigned char l = 0, h = 0, *__srcbin = (unsigned char *) srcbin, *__dsthex = (unsigned char *) dsthex; ;
1432
int retlen = srcbinlen * 2;
1434
__dsthex[retlen] = '\0';
1436
for( ; srcbinlen; srcbinlen--, __dsthex += 2, __srcbin++)
1438
h = (*__srcbin) >> 4;
1440
l = (*__srcbin) & 0x0F;
1442
*__dsthex = (h < 10) ? h + '0' : h + 'a' - 10;
1443
*(__dsthex+1)= (l < 10) ? l + '0' : l + 'a' - 10;
1450
#define $BIN2HEX(s,d,l) __util$bin2hex((char*) s, (char*) d, (unsigned short) l)
1454
* Description: removes leading and trailing spaces or tabs (HT and VT, CR, LF) from string
1456
* src: a pointer to the buffer wit string to process
1457
* srclen: a length of the source buffer
1460
* a length of the actual data in the source buffer
1463
inline static int __util$uncomment (
1470
char * cp, *cmnt = NULL;
1472
if ( !srclen || !src )
1476
* Remove comments from end of string
1478
for (count = srclen, cp = src + (srclen - 1); count; count--, cp--)
1479
cmnt = *cp == marker ? cp : cmnt;
1484
srclen = (int) (cmnt - src);
1492
* Description: removes leading and trailing spaces or tabs (HT and VT, CR, LF) from string
1494
* src: a pointer to the buffer wit string to process
1495
* srclen: a length of the source buffer
1498
* a length of the actual data in the source buffer
1501
inline static int __util$trim (
1509
if ( !srclen || !src )
1513
* Trim all space and tabs at begin of the string ...
1515
for (count = 0, cp = src; isspace (*cp) && (count < srclen); count++, cp++);
1519
memmove(src, cp, srclen -= count);
1520
*(src + srclen) = '\0';
1527
* Trim spaces at end of string ...
1529
for (count = 0, cp = src + srclen; isspace (*(--cp)) && (count < srclen); count++);
1542
* Description: removes all spaces or tabs (HT and VT, CR, LF) from string
1544
* src: a pointer to the buffer with string to process
1545
* srclen: a length of the source buffer
1548
* a length of the actual data in the source buffer
1551
inline static int __util$collapse (
1559
if ( !srclen || !src )
1563
* Remove all spaces or tabs
1565
for (count = 0, cp = src; srclen; src++, srclen--)
1566
if ( !isspace (*src) )
1578
* @brief __UTIL$STRCAT_RX - concatenates given list of strings into the single area.
1580
* @param dst : a pointer to area to accept concatenation of the strings
1581
* @param dstsz : destination area size
1582
* @param dstlen : a returned actual data length
1584
* @return - STS$K_SUCCESS
1585
* STS$K_ERROR - output buffer is overflow
1587
inline static int __util$strcat_rx (
1595
char * srcp, *dstp = (char *) dst;
1596
int srclen, status = STS$K_ERROR;
1598
/* Initialize the argument list. */
1599
va_start (ap, dstlen);
1601
/* Looping until destination buffer have a free space */
1602
for ( *dstlen = srclen = 0; (dstsz - *dstlen); )
1604
/* NULL is a "end-of-list" marker */
1605
if ( !(srcp = va_arg(ap, char *)) )
1607
status = STS$K_SUCCESS;
1611
/* Get source length, zero - skip to next */
1612
if ( !(srclen = va_arg(ap, int)) )
1615
if ( srclen > (dstsz - *dstlen) )
1618
memmove(dstp + *dstlen, srcp, srclen);
1622
*(dstp + *dstlen) = '\0';
1631
#define util$K_LOOKUP_NCASE (1 << 0)
1632
#define util$K_LOOKUP_ABBREV (1 << 1)
1634
typedef struct _kwdent
1643
inline static int __util$lookup_key (
1655
int status = STS$K_ERROR, len;
1658
for ( k = ktbl, len = 0; ktblsz; ktblsz--, k++)
1660
/* Exact comparing or abbreviated ? */
1661
if ( !(flags & util$K_LOOKUP_ABBREV) )
1662
if ( srclen != k->kwd->len )
1666
* We performs a comparing only in case when a compare length is
1667
* more then at previous step.
1669
if ( len < $MIN(srclen, k->kwd->len) )
1670
len = $MIN(srclen, k->kwd->len);
1675
status = (flags & util$K_LOOKUP_NCASE) ?
1682
(src, k->kwd->sts, len) : memcmp(src, k->kwd->sts, len);
1688
/* No matching ... */
1698
* @brief __UTIL$UUID2STR - convert UUID from binary form to the human readable text string.
1699
* implied zero byte (NIL, '\0') at end of the string.
1701
* @param uuid: UUID to be converted
1702
* @param buf: a buffer to accept text string
1703
* @param bufsz:a size of the output buffer
1705
* @return - length of the data in the output buffer.
1707
inline static int __util$uuid2str (
1713
unsigned char tmp [256], *puuid = (unsigned char *) uuid;
1716
len = snprintf( (char *) tmp, sizeof(tmp) - 1, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1717
puuid[0], puuid[1], puuid[2], puuid[3], puuid[4], puuid[5], puuid[6], puuid[7],
1718
puuid[8], puuid[9], puuid[10], puuid[11], puuid[12], puuid[13], puuid[14], puuid[15]);
1720
memcpy(buf, tmp, len = $MIN(bufsz, len));
1730
* @brief __UTIL$FILL - Fill destination buffer with a pattern data.
1732
* @param dst - destination buffer to be filled
1733
* @param dstsz - a size of the destination buffer
1734
* @param src - a buffer with the pattern data
1735
* @param srcsz - a size of the pattern data
1738
static inline int __util$fill (
1746
char * _dst = (char *) dst;
1750
fillen = $MIN(srcsz, dstsz);
1751
memcpy(_dst, src, fillen);
1759
return STS$K_SUCCESS;
1765
* @brief __UTIL$STRXOR - XORing octet source string with a given key to produde result to the destination buffer
1767
* @param key - a buffer with the key
1768
* @param keysz - a length of the key
1769
* @param src - a buffer with the data to be XOR-ed
1770
* @param srcsz - a lenth of the source data
1771
* @param src - a buffer to accept XOR-ed data
1772
* @param srcsz - a size of the output buffer
1775
static inline int __util$strxor (
1784
unsigned char *kp, *sp, *dp;
1785
int sz = (srcsz > dstsz) ? dstsz : srcsz;
1787
for ( kp = key, sp = src, dp = dst; sz; sz--, dp++, sp++, kp++ )
1789
if ( kp >= ( (char *) key + keysz) ) /* Check and reset a pointer to byte in the key buffer */
1792
(*dp) = (*sp) ^ (*kp); /* XOR */
1796
return STS$K_SUCCESS;
1802
/* LIB$MOVC5 - Execute MOVC5 instruction
1804
** FUNCTIONAL DESCRIPTION:
1806
** LIB$MOVC5 makes the VAX MOVC5 instruction available as
1807
** a callable procedure.
1809
** The source is moved to the destination. If the destination is
1810
** longer than the source, the highest address bytes of the
1811
** destination are replaced by the fill argument. If the
1812
** destination is shorter than the source, the highest
1813
** addressed bytes of the source are not moved. The operation is
1814
** such that overlap of the source and destination does not
1815
** affect the result.
1817
** For more information, see the VAX-11 Architecture Handbook.
1819
** CALLING SEQUENCE:
1821
** status.wlc.v = LIB$MOVC5 (src_len.rwu.r, source.rz.r, fill.rb.r,
1822
** dst_len.rwu.r, dest.wz.r)
1824
** FORMAL PARAMETERS:
1826
** src_len ; The length of source in bytes. Passed
1827
** ; by reference. The maximum length is 65535.
1829
** source ; The source to move from. Passed by reference.
1831
** fill ; The fill character. Passed by reference.
1833
** dst_len ; The length of dest in bytes. Passed by
1834
** ; reference. The maximum length is 65535.
1836
** dest ; The destination to move to. Passed by
1844
** IMPLICIT OUTPUTS:
1848
** COMPLETION STATUS:
1850
** SS$_NORMAL Procedure successfully completed.
1858
LIB$MOVC5 19-NOV-2004 08:39:23 Compaq C V6.5-001-48BCD Page 4
1859
15-DEC-1994 11:02:13 $1$DGA1016:[LIBRTL_2.SRC]LIBMOVC5.C;1
1862
static inline int __util$movc5 (
1863
unsigned short *srclen, /* pointer to source length */
1864
char *source, /* pointer to source */
1865
unsigned char *fill, /* pointer to fill byte */
1866
unsigned short *dstlen, /* pointer to destination length */
1867
char *dest /* pointer to destination */
1871
* if the destination is the same size as the source, or shorter
1872
* then this is a simple move.
1875
if (*srclen >= *dstlen)
1876
memmove (dest, source, *dstlen);
1879
* destination is larger, do move and fill
1881
memmove (dest, source, *srclen);
1882
memset (&dest[*srclen], *fill, *dstlen - *srclen);
1885
return STS$K_SUCCESS;
1890
// #define $TRACEBACK(expr) {if ( (expr) ) __util$traceback ( #expr, (expr) ); }
1894
#pragma GCC diagnostic pop
1903
#endif /* __util$UTILS__ */