~sysman-one/starlet/main

« back to all changes in this revision

Viewing changes to utility_routines.h

  • Committer: SysManOne
  • Date: 2021-02-27 15:51:54 UTC
  • Revision ID: git-v1:5b01b936f0df1cf02a7b704221ceb8b21f60f99a
Added files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifdef _WIN32
 
2
        #pragma once
 
3
        #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
 
4
#endif
 
5
 
 
6
/*
 
7
**  Abstract: An API declaration for the general purpose and utility routines and  stuff ...
 
8
**
 
9
**  Author: Ruslan R. Laishev
 
10
**
 
11
**  Creation date: 4-SEP-2017
 
12
**
 
13
**  Modification history:
 
14
**
 
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;
 
20
**
 
21
**      20-OCT-2017     RRL     Added __util$uuid2str() - convert UUID into from binary form to ASCII text string.
 
22
**
 
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.
 
25
**
 
26
**      14-NOV-2017     RRL     Added __util$str2asc() - copy ASCIZ string to the ASCIC container.
 
27
**
 
28
**      11-MAY-2018     RRL     Added __util$fill() - fill buffer with the given pattern data
 
29
**
 
30
**      30-MAY-2018     RRL     Correct pointer type to exclude compilation error under VC 2017 in the __util$fill().
 
31
**
 
32
**       7-JUN-2018     RRL     Correct pointer type to compile under GCC.
 
33
**
 
34
**      15-OCT-2018     RRL     Added __ASC_TYPE__ macro to flag that ASC type is defined here.
 
35
**
 
36
**      25-JUN-2019     RRL     Redefined macro $TRACE() to eliminate "if (cond) ..."
 
37
**
 
38
**      10-JUL-2019     RRL     Warning fix.
 
39
*/
 
40
 
 
41
#if _WIN32
 
42
#define _CRT_SECURE_NO_WARNINGS 1
 
43
 
 
44
#include        <Windows.h>
 
45
#include        <sys/timeb.h>
 
46
 
 
47
#endif
 
48
 
 
49
#ifndef __STARLET$UTILS__
 
50
#define __STARLET$UTILS__       1
 
51
 
 
52
#ifdef __cplusplus
 
53
extern "C" {
 
54
#endif
 
55
 
 
56
#ifndef __MODULE__
 
57
#define __MODULE__      NULL
 
58
#endif
 
59
 
 
60
#include        <stdio.h>
 
61
#include        <stddef.h>
 
62
#include        <assert.h>
 
63
#include        <time.h>
 
64
#include        <ctype.h>
 
65
#include        <limits.h>
 
66
#include        <stdarg.h>
 
67
#include        <string.h>
 
68
 
 
69
#ifndef WIN32
 
70
#pragma GCC diagnostic push
 
71
#pragma GCC diagnostic ignored  "-Wparentheses"
 
72
#endif
 
73
 
 
74
#define CRLFCRLF_LW     0x0a0d0a0d
 
75
#define CRLFCRLF        "\r\n\r\n"
 
76
#define CRLF            "\r\n"
 
77
 
 
78
/*
 
79
 * A Macro to compute an arrays size in elements at compilation time
 
80
 */
 
81
#define $ARRSZ(a)       (sizeof(a)/sizeof(a[0]))
 
82
 
 
83
 
 
84
/*
 
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.
 
90
 
 
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.
 
95
 
 
96
  The function returns 0 if the store does not complete, and 1 if the
 
97
  store does complete.
 
98
 
 
99
  Syntax:
 
100
 
 
101
       int __CMP_STORE_LONG (volatile void *source, int old_value,
 
102
       int new_value,
 
103
       volatile void *dest);
 
104
 
 
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.
 
107
 
 
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.
 
110
*/
 
111
#define $CMP_STORE_LONG(src, old_val, new_val)  __sync_bool_compare_and_swap((int *) src, (int) old_val, (int) new_val )
 
112
 
 
113
 
 
114
#pragma pack    (push)
 
115
#pragma pack    (1)
 
116
 
 
117
 
 
118
#if _WIN32
 
119
#define inline  __inline
 
120
#endif
 
121
 
 
122
#ifdef _WIN32
 
123
/*
 
124
struct  timespec {
 
125
        time_t  tv_sec;
 
126
        long    tv_nsec;
 
127
};
 
128
*/
 
129
inline static   int     ____time(struct timespec *tv)
 
130
{
 
131
 
 
132
#if    1
 
133
 
 
134
        timespec_get(tv, TIME_UTC);
 
135
        tv->tv_nsec /=1024;
 
136
        //tv->tv_nsec *=1024;
 
137
#else
 
138
struct _timeb timebuffer;
 
139
 
 
140
        _ftime_s ( &timebuffer );
 
141
 
 
142
        tv->tv_sec = timebuffer.time;
 
143
        tv->tv_nsec = timebuffer.millitm;
 
144
        tv->tv_nsec *= 1024;
 
145
 
 
146
 
 
147
#endif // 1
 
148
 
 
149
        return  0;
 
150
}
 
151
 
 
152
#else
 
153
 
 
154
inline static int       ____time(struct timespec *tv)
 
155
{
 
156
        clock_gettime(CLOCK_REALTIME, tv);
 
157
 
 
158
        return  0;
 
159
}
 
160
 
 
161
#endif
 
162
 
 
163
 
 
164
 
 
165
 
 
166
inline  static void     __util$timbuf(time_t *__src, struct tm * __dst)
 
167
{
 
168
time_t  now;
 
169
 
 
170
        if ( !__src )
 
171
                time(&now);
 
172
 
 
173
#ifdef  WIN32
 
174
        localtime_s(__dst, __src ? __src : &now);
 
175
#else
 
176
        localtime_r(__src ? __src : &now, __dst);
 
177
#endif
 
178
 
 
179
        __dst->tm_mon   += 1;
 
180
        __dst->tm_year  += 1900;
 
181
}
 
182
 
 
183
 
 
184
#ifndef __PATH_SEPARATOR
 
185
        #ifndef WIN32
 
186
                #define __PATH_SEPARATOR        '/'
 
187
        #else
 
188
                #define __PATH_SEPARATOR        '\\'
 
189
        #endif
 
190
#endif
 
191
 
 
192
 
 
193
#ifndef __PATH_SEPARATOR_S
 
194
        #ifndef WIN32
 
195
                #define __PATH_SEPARATOR_S      "/"
 
196
        #else
 
197
                #define __PATH_SEPARATOR_S      "\\"
 
198
        #endif
 
199
#endif
 
200
 
 
201
/*
 
202
 *
 
203
 * Item List Element
 
204
 *
 
205
 */
 
206
typedef struct  __ile2  {
 
207
        unsigned short  code,   /* Item List Element code       */
 
208
                        len;    /* Length of data               */
 
209
                char *  ptr;    /* Pointer to data              */
 
210
} ILE2;
 
211
 
 
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 */
 
217
} ILE3;
 
218
 
 
219
 
 
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}
 
223
#define $ILENULL        {0}
 
224
 
 
225
/*
 
226
 *
 
227
 * Queue & Entry types & macros definitions
 
228
 *
 
229
 */
 
230
#pragma pack (push)
 
231
#pragma pack    (8)
 
232
 
 
233
/*
 
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
 
237
**
 
238
**      unsigned short  buflen,
 
239
**                      bufsz;
 
240
**      char    *pbuf;
 
241
**}
 
242
*/
 
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                                  */
 
247
} ENTRY;
 
248
 
 
249
 
 
250
/*
 
251
** Special data type to help organize of duble-linked lists (queues).
 
252
*/
 
253
typedef struct  __queue {
 
254
        ENTRY           *head, *tail;   /* An addresses of first and last element of the queue */
 
255
 
 
256
#if _WIN32
 
257
        SRWLOCK         lock;           /* A spinlock to coordinate an access to the head and tail*/
 
258
#else
 
259
        int             lock;
 
260
#endif
 
261
 
 
262
        unsigned        count;          /* An actual elements/entries count in the queue        */
 
263
} __QUEUE;
 
264
 
 
265
/* Macro to initialize a __QUEUE object with defaults. Typical usage is:
 
266
 * void ZZtop (void)
 
267
 * {
 
268
 * __QUEUE que = QUEUE_INITIALIZER;
 
269
 *  ...
 
270
 * }
 
271
 */
 
272
#define QUEUE_INITIALIZER { (ENTRY *) 0, (ENTRY *) 0, 0, 0 }
 
273
 
 
274
#pragma pack    (pop)
 
275
 
 
276
 
 
277
/* Logging facility     */
 
278
#ifndef __FAC__
 
279
        #define __FAC__ "UTILS"
 
280
        #define __FAC$_UTILS__  0x01
 
281
#endif
 
282
 
 
283
#define STS$K_WARN      0
 
284
#define STS$K_SUCCESS   1
 
285
#define STS$K_ERROR     2
 
286
#define STS$K_INFO      3
 
287
#define STS$K_UNDEF     8
 
288
#define STS$K_SYSLOG    16      /* This option force sending message to the syslog service      */
 
289
 
 
290
#define $STS_ERROR(code)        ( ((code) & STS$K_ERROR ) || ((code) & STS$K_ERROR) )
 
291
 
 
292
/*
 
293
 * +---------------------+--------------------------+-------------------+
 
294
 * |  Facility (16 bits) | Message Number (13 bits) | Severity (3) bits |
 
295
 * +---------------------+--------------------------+-------------------+
 
296
 */
 
297
#define $FAC(code)              ((code) >> 16)
 
298
#define $MSG(code)              ((code) >> 3)
 
299
#define $SEV(code)              ((code) & 0x7)
 
300
 
 
301
 
 
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);
 
306
 
 
307
#ifdef  _DEBUG
 
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
 
310
#else
 
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
 
313
 
 
314
#endif
 
315
 
 
316
 
 
317
 
 
318
/*
 
319
 * Description: Implement spinlock logic by using GCC builtin, set the lock value to 1.
 
320
 *
 
321
 * Input:
 
322
 *      lock:   a pointer to longword, to accept a lock flag
 
323
 *
 
324
 * Return:
 
325
 *      STS$K_SUCCESS
 
326
 *      STS$K_ERROR
 
327
 */
 
328
 
 
329
 
 
330
 
 
331
 
 
332
inline  static int __util$lockspin (void volatile * lock)
 
333
{
 
334
unsigned i = 0xffffffffU;
 
335
 
 
336
 
 
337
#ifdef  WIN32
 
338
int     status = 0;
 
339
 
 
340
        for ( ; i && !(status = TryAcquireSRWLockExclusive((SRWLOCK *) lock)); i--);
 
341
 
 
342
        return  status ? STS$K_SUCCESS : STS$K_ERROR;
 
343
#else
 
344
        for ( ; i && __sync_lock_test_and_set(((int *) lock), 1); i--)
 
345
                for (; i && (* ((int *)lock)); i--);
 
346
 
 
347
        return  i ? STS$K_SUCCESS : STS$K_ERROR;
 
348
#endif
 
349
}
 
350
 
 
351
 
 
352
#define $LOCK_LONG(lock)        __util$lockspin(lock)
 
353
 
 
354
 
 
355
/*
 
356
 * Description: Release has been set lock flag, set the lock value to 0.
 
357
 *
 
358
 * Input:
 
359
 *      lock:   a pointer to longword, to accept a lock flag
 
360
 *
 
361
 * Return:
 
362
 *      STS$K_SUCCESS
 
363
 */
 
364
inline  static  int __util$unlockspin (void * lock)
 
365
{
 
366
 
 
367
#if _WIN32
 
368
        ReleaseSRWLockExclusive( (SRWLOCK *) lock);
 
369
#else
 
370
        __sync_lock_release((int *)  lock);
 
371
#endif
 
372
 
 
373
        return  STS$K_SUCCESS;
 
374
}
 
375
 
 
376
 
 
377
 
 
378
#define $UNLOCK_LONG(lock)      __util$unlockspin(lock)
 
379
 
 
380
 
 
381
 
 
382
 
 
383
/*
 
384
 * Description: Remove all entries from the given queue
 
385
 *
 
386
 * Input:
 
387
 *      que:    A pointer to __QUEUE structure
 
388
 *
 
389
 * Output:
 
390
 *      count:  A count of entries in the __QUEUE before cleanuping
 
391
 *
 
392
 * Return:
 
393
 *      condition code
 
394
 */
 
395
inline static int __util$clrqueue (void * que,  unsigned * count)
 
396
{
 
397
__QUEUE * _que = (__QUEUE *) que;
 
398
ENTRY * _ent;
 
399
int     nums;
 
400
 
 
401
        /*
 
402
         * Sanity check
 
403
         */
 
404
        if ( !_que || !count )
 
405
                return  STS$K_ERROR;
 
406
 
 
407
        if ( !_que->count )
 
408
                return  STS$K_SUCCESS;
 
409
 
 
410
        /*
 
411
         * Acquire lock
 
412
         */
 
413
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
414
                return  STS$K_ERROR;
 
415
 
 
416
        /* Store entries counter */
 
417
        *count = nums = _que->count;
 
418
 
 
419
        /* Run over all entries, zeroing link to queue ... */
 
420
        for ( _ent = _que->head; nums; nums--, _ent = _ent->right)
 
421
                _ent->queue = NULL;
 
422
 
 
423
        _que->count = 0;
 
424
        _que->head = _que->tail = NULL;
 
425
 
 
426
 
 
427
        /*
 
428
         * Release the spinlock
 
429
         */
 
430
        return  __util$unlockspin(&_que->lock);
 
431
}
 
432
 
 
433
 
 
434
/*
 
435
 * Description: Insert a new entry at tail of the queue
 
436
 *
 
437
 * Input:
 
438
 *      que:    A pointer to __QUEUE structure
 
439
 *      ent:    New ENTRY pointer
 
440
 *
 
441
 * Output:
 
442
 *      count:  A count of entries in the __QUEUE before inserting
 
443
 *
 
444
 * Return:
 
445
 *      condition code
 
446
 */
 
447
 
 
448
#define UTIL$S_INVARG   0x102
 
449
#define UTIL$S_INQUE    0x202
 
450
#define UTIL$S_NOLOCK   0x202
 
451
 
 
452
inline static int __util$insqtail (void * que, void * ent, unsigned * count)
 
453
{
 
454
__QUEUE * _que = (__QUEUE *) que;
 
455
ENTRY * _entold, *_entnew = (ENTRY *) ent;
 
456
 
 
457
        /*
 
458
         * Sanity check
 
459
         */
 
460
        if ( !_que || !ent || !count )
 
461
                return  UTIL$S_INVARG;
 
462
 
 
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  */
 
467
                return  UTIL$S_INQUE;
 
468
 
 
469
 
 
470
        /*
 
471
         * Acquire lock
 
472
         */
 
473
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
474
                return  UTIL$S_NOLOCK;
 
475
 
 
476
        *count = _que->count;
 
477
 
 
478
        if ( _entold = _que->tail )
 
479
                _entold->right  = _entnew;
 
480
        else    _que->head      = _entnew;
 
481
 
 
482
        _entnew->left   = _entold;
 
483
        _entnew->right  = NULL;
 
484
        _entnew->queue  = que;
 
485
        _que->tail      = _entnew;
 
486
 
 
487
        _que->count++;
 
488
 
 
489
        /*
 
490
         * Release the spinlock
 
491
         */
 
492
        return  __util$unlockspin(&_que->lock);
 
493
}
 
494
 
 
495
/*
 
496
 * Description: Insert a new entry at head of the queue
 
497
 *
 
498
 * Input:
 
499
 *      que:    A pointer to __QUEUE structure
 
500
 *      ent:    New ENTRY pointer
 
501
 *
 
502
 * Output:
 
503
 *      count:  A count of entries in the __QUEUE before inserting
 
504
 *
 
505
 * Return:
 
506
 *      condition code
 
507
 */
 
508
inline static int __util$insqhead (void * que, void * ent, unsigned * count)
 
509
{
 
510
__QUEUE * _que = (__QUEUE *) que;
 
511
ENTRY * _entold, *_entnew = (ENTRY *) ent;
 
512
 
 
513
        /*
 
514
         * Sanity check
 
515
         */
 
516
        if ( !_que || !ent || !count )
 
517
                return  STS$K_ERROR;
 
518
 
 
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  */
 
523
                return  STS$K_ERROR;
 
524
 
 
525
        /*
 
526
         * Acquire lock
 
527
         */
 
528
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
529
                return  STS$K_ERROR;
 
530
 
 
531
        *count = _que->count;
 
532
 
 
533
        if ( _entold = _que->head )
 
534
                _entold->left   = _entnew;
 
535
        else    _que->tail = _entnew;
 
536
 
 
537
        _entnew->right  = _entold;
 
538
        _entnew->left   = NULL;
 
539
        _entnew->queue  = que;
 
540
        _que->head = _entnew;
 
541
 
 
542
        _que->count++;
 
543
 
 
544
        /*
 
545
         * Release the spinlock
 
546
         */
 
547
        return  __util$unlockspin(&_que->lock);
 
548
}
 
549
 
 
550
 
 
551
/*
 
552
 * Description: Remove an entry from the the current place in the queue
 
553
 *
 
554
 * Input:
 
555
 *      que:    A pointer to __QUEUE structure
 
556
 *
 
557
 * Output:
 
558
 *      ent:    A removed entry
 
559
 *      count:  A count of entries in the __QUEUE before inserting
 
560
 *
 
561
 * Return:
 
562
 *      condition code
 
563
 */
 
564
inline static int __util$remqent (void * que, void *ent, unsigned * count)
 
565
{
 
566
__QUEUE * _que = (__QUEUE *) que;
 
567
ENTRY * _ent = (ENTRY *) ent, *_entleft;
 
568
 
 
569
        /*
 
570
         * Sanity check
 
571
         */
 
572
        if ( !_que || !ent || !count )
 
573
                return  STS$K_ERROR;
 
574
 
 
575
        /* Check that ENTRY is belong to the __QUEUE    */
 
576
        if ( _ent->queue != que )
 
577
                return  STS$K_ERROR;
 
578
 
 
579
        /*
 
580
         * Acquire lock
 
581
         */
 
582
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
583
                return  STS$K_ERROR;
 
584
 
 
585
        if ( !(*count = _que->count) )
 
586
                {
 
587
                __util$unlockspin(&_que->lock);
 
588
                return STS$K_SUCCESS;
 
589
                }
 
590
 
 
591
        /*
 
592
        ** Main work ...
 
593
        */
 
594
        _entleft = _ent->left;
 
595
        _entleft->right = _ent->right;
 
596
 
 
597
        /*
 
598
         * Reset head & tail if queue is empty
 
599
         */
 
600
        if ( !(--_que->count) )
 
601
                _que->head = _que->tail = NULL;
 
602
 
 
603
        _ent->left = _ent->right = NULL;
 
604
        _ent->queue = NULL;
 
605
 
 
606
        /*
 
607
         * Release the spinlock
 
608
         */
 
609
        __util$unlockspin(&_que->lock);
 
610
 
 
611
        return  STS$K_SUCCESS;
 
612
}
 
613
 
 
614
 
 
615
 
 
616
 
 
617
 
 
618
 
 
619
 
 
620
/*
 
621
 * Description: Remove an entry from the tail of the queue
 
622
 *
 
623
 * Input:
 
624
 *      que:    A pointer to __QUEUE structure
 
625
 *
 
626
 * Output:
 
627
 *      ent:    A removed entry
 
628
 *      count:  A count of entries in the __QUEUE before inserting
 
629
 *
 
630
 * Return:
 
631
 *      condition code
 
632
 */
 
633
inline static int __util$remqtail (void * que, void **ent, unsigned * count)
 
634
{
 
635
__QUEUE * _que = (__QUEUE *) que;
 
636
ENTRY * _entleft, * _entright = NULL;
 
637
 
 
638
        /*
 
639
         * Sanity check
 
640
         */
 
641
        if ( !_que || !ent || !count )
 
642
                return  STS$K_ERROR;
 
643
 
 
644
        /*
 
645
         * Acquire lock
 
646
         */
 
647
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
648
                return  STS$K_ERROR;
 
649
 
 
650
        if ( !(*count = _que->count) )
 
651
                {
 
652
                __util$unlockspin(&_que->lock);
 
653
                return STS$K_SUCCESS;
 
654
                }
 
655
 
 
656
        /*
 
657
        ** Main work ...
 
658
        */
 
659
        if ( _entright = _que->tail )
 
660
                {
 
661
                if ( _entleft = _entright->left )
 
662
                        _entleft->right = NULL;
 
663
 
 
664
                _que->tail = _entleft;
 
665
                }
 
666
 
 
667
        *ent    = _entright;
 
668
        _entright->left = _entright->right = NULL;
 
669
        _entright->queue = NULL;
 
670
 
 
671
        /*
 
672
         * Reset head & tail if queue is empty
 
673
         */
 
674
        if ( !(--_que->count) )
 
675
                _que->head = _que->tail = NULL;
 
676
 
 
677
        /*
 
678
         * Release the spinlock
 
679
         */
 
680
        __util$unlockspin(&_que->lock);
 
681
 
 
682
#ifndef WIN32
 
683
        assert(_entright);
 
684
#endif
 
685
 
 
686
        return  _entright ? STS$K_SUCCESS : STS$K_ERROR;
 
687
}
 
688
 
 
689
/*
 
690
 * Description: Remove an entry from the head of the queue
 
691
 *
 
692
 * Input:
 
693
 *      que:    A pointer to __QUEUE structure
 
694
 *
 
695
 * Output:
 
696
 *      ent:    A removed entry
 
697
 *      count:  A count of entries in the __QUEUE before inserting
 
698
 *
 
699
 * Return:
 
700
 *      condition code
 
701
 */
 
702
inline static int __util$remqhead (void * que, void **ent, unsigned * count)
 
703
{
 
704
__QUEUE * _que = (__QUEUE *) que;
 
705
ENTRY * _entleft = NULL, * _entright;
 
706
 
 
707
        /*
 
708
         * Sanity check
 
709
         */
 
710
        if ( !_que || !ent || !count )
 
711
                return  STS$K_ERROR;
 
712
 
 
713
        /*
 
714
         * Acquire lock
 
715
         */
 
716
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
717
                return  STS$K_ERROR;
 
718
 
 
719
        if ( !(*count = _que->count) )
 
720
                {
 
721
                __util$unlockspin(&_que->lock);
 
722
                return STS$K_SUCCESS;
 
723
                }
 
724
 
 
725
        /*
 
726
        ** Main work ...
 
727
        */
 
728
        if ( _entleft = _que->head )
 
729
                {
 
730
                if ( _entright = _entleft->right )
 
731
                        _entright->left = NULL;
 
732
 
 
733
                _que->head = _entright;
 
734
                }
 
735
#ifndef WIN32
 
736
        assert(_entleft);
 
737
#endif
 
738
 
 
739
        *ent    = _entleft;
 
740
        _entleft->left = _entleft->right = NULL;
 
741
        _entleft->queue = NULL;
 
742
 
 
743
        /*
 
744
         * Reset head & tail if queue is empty
 
745
         */
 
746
        if ( !(--_que->count) )
 
747
                _que->head = _que->tail = NULL;
 
748
 
 
749
        /*
 
750
         * Release the spinlock
 
751
         */
 
752
        __util$unlockspin(&_que->lock);
 
753
 
 
754
#ifndef WIN32
 
755
        assert(_entleft);
 
756
#endif
 
757
 
 
758
 
 
759
        return  _entleft ? STS$K_SUCCESS : STS$K_ERROR;
 
760
}
 
761
 
 
762
/*
 
763
 * Description: Move an existen entry at head of queue.
 
764
 *
 
765
 * Input:
 
766
 *      que:    A pointer to __QUEUE structure
 
767
 *      ent:    A pointer to ENTRY to be moved at head of queue
 
768
 *
 
769
 * Output:
 
770
 *      NONE
 
771
 *
 
772
 * Return:
 
773
 *      condition code
 
774
 */
 
775
inline static int __util$movqhead (void * que, void **ent)
 
776
{
 
777
unsigned        i;
 
778
__QUEUE * _que = (__QUEUE *) que;
 
779
ENTRY * entp, * _entleft = NULL, * _entright = NULL;
 
780
 
 
781
        /*
 
782
         * Sanity check
 
783
         */
 
784
        if ( !_que || !ent )
 
785
                return  STS$K_ERROR;
 
786
 
 
787
        /*
 
788
         * Acquire lock
 
789
         */
 
790
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
791
                return  STS$K_ERROR;
 
792
 
 
793
        if ( !(_que->count) )
 
794
                {
 
795
                __util$unlockspin(&_que->lock);
 
796
                return STS$K_SUCCESS;
 
797
                }
 
798
 
 
799
        /*
 
800
         * Lookup in the queue an entry with a given address
 
801
         */
 
802
        for (i = 0, entp = _que->head; i < _que->count; i++, entp = entp->right)
 
803
                {
 
804
                if ( entp == (ENTRY *) ent )
 
805
                        break;
 
806
                }
 
807
 
 
808
        /*
 
809
         * Is the entry already on head of the queue?
 
810
         */
 
811
        if ( !i )
 
812
                return  __util$unlockspin(&_que->lock);
 
813
 
 
814
        /*
 
815
         * Is the entry with a given address live in the queue?
 
816
         */
 
817
        if ( !entp )
 
818
                {
 
819
                __util$unlockspin(&_que->lock);
 
820
                return  STS$K_ERROR;
 
821
                }
 
822
 
 
823
        /*
 
824
         * Exclude has been found entry from the chain
 
825
         */
 
826
        if ( _entleft = entp->left )
 
827
                _entleft->right = entp->right;
 
828
#ifndef WIN32
 
829
        else    assert ( entp->left );  /* left link can be only on first entry! */
 
830
#endif
 
831
 
 
832
 
 
833
        if ( _entright= entp->right )
 
834
                _entright->left = entp->left;
 
835
 
 
836
        /*
 
837
         * Put has been found entry at head of tail
 
838
         */
 
839
        entp->right = _que->head;
 
840
        entp->left = NULL;
 
841
        _que->head = entp;
 
842
 
 
843
        /*
 
844
         * Release the spinlock
 
845
         */
 
846
        return  __util$unlockspin(&_que->lock);
 
847
}
 
848
 
 
849
/*
 
850
 * Description: Move an existen entry to end of queue.
 
851
 *
 
852
 * Input:
 
853
 *      que:    A pointer to __QUEUE structure
 
854
 *      ent:    A pointer to ENTRY to be moved at head of queue
 
855
 *
 
856
 * Output:
 
857
 *      NONE
 
858
 *
 
859
 * Return:
 
860
 *      condition code
 
861
 */
 
862
inline static int __util$movqtail (void * que, void **ent)
 
863
{
 
864
unsigned        i;
 
865
__QUEUE * _que = (__QUEUE *) que;
 
866
ENTRY * entp, * _entleft = NULL, * _entright = NULL;
 
867
 
 
868
        /*
 
869
         * Sanity check
 
870
         */
 
871
        if ( !_que || !ent )
 
872
                return  STS$K_ERROR;
 
873
 
 
874
        /*
 
875
         * Acquire lock
 
876
         */
 
877
        if ( !(1 & __util$lockspin( &_que->lock)) )
 
878
                return  STS$K_ERROR;
 
879
 
 
880
        if ( !(_que->count) )
 
881
                {
 
882
                __util$unlockspin(&_que->lock);
 
883
                return STS$K_SUCCESS;
 
884
                }
 
885
 
 
886
        /*
 
887
         * Lookup in the queue an entry with a given address
 
888
         */
 
889
        for (i = 0, entp = _que->head; i < _que->count; i++, entp = entp->right)
 
890
                {
 
891
                if ( entp == (ENTRY *) ent )
 
892
                        break;
 
893
                }
 
894
 
 
895
        /*
 
896
         * Is the entry already at tail ?
 
897
         */
 
898
        if ( i == _que->count )
 
899
                return  __util$unlockspin(&_que->lock);
 
900
 
 
901
        /*
 
902
         * Is the entry with a given address live in the queue?
 
903
         */
 
904
        if ( !entp )
 
905
                {
 
906
                __util$unlockspin(&_que->lock);
 
907
                return  STS$K_ERROR;
 
908
                }
 
909
 
 
910
        /*
 
911
         * Exclude has been found entry from the chain
 
912
         */
 
913
        if ( _entleft = entp->left )
 
914
                _entleft->right = _entright;
 
915
 
 
916
        if ( _entright= entp->right )
 
917
                _entright->left = _entleft;
 
918
#ifndef WIN32
 
919
        else assert( entp->right );     /* Right link can be on the last entry ! */
 
920
#endif
 
921
 
 
922
        /*
 
923
         * Put has been found entry at tail of queue
 
924
         */
 
925
        entp->left = _que->tail;
 
926
        entp->right = NULL;
 
927
        _que->tail = entp;
 
928
 
 
929
        /*
 
930
         * Release the spinlock
 
931
         */
 
932
        return  __util$unlockspin(&_que->lock);
 
933
}
 
934
 
 
935
/*
 
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.
 
938
 *
 
939
 * Typical scenario of using:
 
940
 *
 
941
 * __QUEUE      myqueue = QUEUE_INITIALIZER;
 
942
 * struct message {
 
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];
 
946
 * } messages [ 32 ];
 
947
 *
 
948
 * int  main    (void)
 
949
 * {
 
950
 * int status, count;
 
951
 *
 
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);
 
955
 * }
 
956
 *
 
957
 */
 
958
 
 
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
 
961
 */
 
962
#define $INSQHEAD(que, ent, count)      __util$insqhead ((__QUEUE *) que, (void *) ent, (unsigned *) count)
 
963
 
 
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
 
966
 */
 
967
#define $INSQTAIL(que, ent, count)      __util$insqtail ((__QUEUE *) que, (void *) ent, (unsigned *) count)
 
968
 
 
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
 
971
 */
 
972
#define $REMQHEAD(que, ent, count)      __util$remqhead ((__QUEUE *) que, (void **) ent, (unsigned *) count)
 
973
 
 
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
 
976
 */
 
977
#define $REMQTAIL(que, ent, count)      __util$remqtail ((__QUEUE *) que, (void **)ent, (unsigned *) count)
 
978
 
 
979
 
 
980
/*      Move an entry with a given address from current position of the queue to head of the queue,
 
981
 *      return condition status;
 
982
 */
 
983
#define $MOVQHEAD(que, ent)             __util$movqhead ((__QUEUE *) que, (void *) ent)
 
984
 
 
985
/*      Move an entry with a given address from current position of the queue to tail of the queue,
 
986
 *      return condition status;
 
987
 */
 
988
#define $MOVQTAIL(que, ent)             __util$movqtail ((__QUEUE *) que, (void *) ent)
 
989
 
 
990
/*      Remove a givent entry from the queueue.
 
991
 */
 
992
#define $REMQENT(que, ent, count)       __util$remqent ((__QUEUE *) que, (void **)ent, (unsigned *) count)
 
993
 
 
994
 
 
995
/*      Remove all entries form the queue.
 
996
 */
 
997
#define $CLRQUE(que, count)     __util$clrqueue ((__QUEUE *) que, (unsigned *) count)
 
998
 
 
999
 
 
1000
/* Macros to return minimal/maximum value from two given integers               */
 
1001
inline static int __util$min (int x, int y)
 
1002
{
 
1003
        return  (x < y) ? x : y;
 
1004
}
 
1005
#define $MIN(x, y)      __util$min((int) (x), (int) (y))
 
1006
 
 
1007
inline static int __util$max (int x, int y)
 
1008
{
 
1009
        return  (x > y) ? x : y;
 
1010
}
 
1011
#define $MAX(x, y)      __util$max((int) (x), (int) (y))
 
1012
 
 
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__ )
 
1015
{
 
1016
int     left = $MIN(__min__, __max__) , right = $MAX(__min__, __max__);
 
1017
 
 
1018
        return ( (x < left) || ( x > right ) ) ? 0 : 1;
 
1019
}
 
1020
 
 
1021
/* Return result of checking value between two borders: min and max     */
 
1022
#define $ISINRANGE(x, __min__, __max__) __util$isinrange(x, (__min__), (__max__))
 
1023
 
 
1024
 
 
1025
/* Return a result of checking value in the given range include border,
 
1026
 * 0/false - out of range, 1/true - is in range
 
1027
 */
 
1028
inline static int __util$isinrange2 (int x, int __min__, int __max__ )
 
1029
{
 
1030
int     left = $MIN(__min__, __max__) , right = $MAX(__min__, __max__);
 
1031
 
 
1032
        return ( (x <= left) || ( x >= right ) ) ? 0 : 1;
 
1033
}
 
1034
 
 
1035
/* Return result of checking value between two borders: min and max     */
 
1036
#define $ISINRANGE2(x, __min__, __max__)        __util$isinrange2(x, (__min__), (__max__))
 
1037
 
 
1038
 
 
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__ )
 
1041
{
 
1042
int     left = $MIN(__min__, __max__) , right = $MAX(__min__, __max__);
 
1043
 
 
1044
        x = $MAX(x, left);
 
1045
        x = $MIN(x, right);
 
1046
 
 
1047
        return  x;
 
1048
}
 
1049
 
 
1050
/* Return value bound to left or right border eg. x = [min; max]        */
 
1051
#define $RANGE(x, __min__, __max__)     __util$range(x, __min__, __max__)
 
1052
 
 
1053
 
 
1054
 
 
1055
/*
 
1056
 *
 
1057
 *  Description: check buffer for consecutive zero octets
 
1058
 *
 
1059
 *  Input:
 
1060
 *
 
1061
 *      bufp:   buffer to check, address
 
1062
 *      bufsz:  a length of data in the buffer
 
1063
 *
 
1064
 *
 
1065
 *  Return:
 
1066
 *      SS$_NORMAL      - the buffer is zero filled
 
1067
 *      STS$K_WARN      - the buffer is not zero filled
 
1068
 */
 
1069
/**
 
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
 
1073
 * @return -
 
1074
 * *    SS$_NORMAL      - the buffer is zero filled
 
1075
 *      STS$K_WARN      - the buffer is not zero filled
 
1076
 */
 
1077
inline static int __util$iszero (
 
1078
                void *  bufp,
 
1079
                int     bufsz
 
1080
                        )
 
1081
{
 
1082
int     i;
 
1083
unsigned char *__bufp = (unsigned char *) bufp;
 
1084
 
 
1085
#if ( (defined ULLONG_MAX && (ULLONG_MAX > UINT_MAX)) || (defined ULONG_LONG_MAX && (ULONG_LONG_MAX > UINT_MAX)) )
 
1086
 
 
1087
//#pragma message       ("%CC-I-ULLONG64, unsigned long long - 64 bits")
 
1088
 
 
1089
        /* Step by 8 octets ... */
 
1090
        for (i = bufsz/sizeof(unsigned long long); i; i--, __bufp += sizeof(unsigned long long) )
 
1091
                {
 
1092
                if ( *((unsigned long long *) __bufp ) )
 
1093
                        return  STS$K_WARN;
 
1094
                }
 
1095
#endif // (sizeof(unsigned long long)) > sizeof(unsigned int long) )
 
1096
 
 
1097
        /* Compute remainder octets in the buffer */
 
1098
        bufsz %= sizeof(unsigned int long);
 
1099
 
 
1100
        /* Step by 4 octets ... */
 
1101
        for (i = bufsz/sizeof(unsigned int); i; i--, __bufp += sizeof(unsigned int) )
 
1102
                {
 
1103
                if ( *((unsigned int *) __bufp ) )
 
1104
                        return  STS$K_WARN;
 
1105
                }
 
1106
 
 
1107
        /* Compute remainder octets in the buffer */
 
1108
        bufsz %= sizeof(unsigned int);
 
1109
 
 
1110
        /* Step by 2 octets ... */
 
1111
        for (i = bufsz/sizeof(unsigned short); i; i--, __bufp += sizeof(unsigned short) )
 
1112
                {
 
1113
                if ( *((unsigned short *) __bufp ) )
 
1114
                        return  STS$K_WARN;
 
1115
                }
 
1116
 
 
1117
        /* Compute remainder octets in the buffer */
 
1118
        bufsz %= sizeof(unsigned short);
 
1119
 
 
1120
        if ( bufsz && *__bufp )
 
1121
                return  STS$K_WARN;
 
1122
 
 
1123
        return  STS$K_SUCCESS;
 
1124
}
 
1125
 
 
1126
 
 
1127
/**
 
1128
 * @brief __util$bzero  - zeroing memory block
 
1129
 * @param bufp  :       buffer to check, address
 
1130
 * @param bufsz :       a length of data in the buffer
 
1131
 * @return -
 
1132
 *      SS$_NORMAL      - the buffer is zero filled
 
1133
 *
 
1134
 */
 
1135
inline static int __util$bzero  (
 
1136
                void *  bufp,
 
1137
                int     bufsz
 
1138
                        )
 
1139
{
 
1140
int     i;
 
1141
unsigned char *__bufp = (unsigned char *) bufp;
 
1142
 
 
1143
        /*
 
1144
         * There is a place for optimization : align a memory address at head
 
1145
         * of the memory block
 
1146
         */
 
1147
 
 
1148
#if ( (defined ULLONG_MAX && (ULLONG_MAX > UINT_MAX)) || (defined ULONG_LONG_MAX && (ULONG_LONG_MAX > UINT_MAX)) )
 
1149
 
 
1150
//#pragma message       ("%CC-I-ULLONG64, unsigned long long - 64 bits")
 
1151
 
 
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) )
 
1156
 
 
1157
        /* Compute remainder octets in the buffer */
 
1158
        bufsz %= sizeof(unsigned long long);
 
1159
 
 
1160
        /* Step by 4 octets ... */
 
1161
        for (i = bufsz/sizeof(unsigned int); i; i--, __bufp += sizeof(unsigned int) )
 
1162
                *((unsigned int *) __bufp ) = 0;
 
1163
 
 
1164
        /* Compute remainder octets in the buffer */
 
1165
        bufsz %= sizeof(unsigned int);
 
1166
 
 
1167
        /* Step by 2 octets ... */
 
1168
        for (i = bufsz/sizeof(unsigned short); i; i--, __bufp += sizeof(unsigned short) )
 
1169
                if ( *((unsigned short *) __bufp ) )
 
1170
 
 
1171
        /* Compute remainder octets in the buffer */
 
1172
        bufsz %= sizeof(unsigned short);
 
1173
 
 
1174
        if ( bufsz )
 
1175
                __bufp = '\0';
 
1176
 
 
1177
        return  STS$K_SUCCESS;
 
1178
}
 
1179
 
 
1180
 
 
1181
 
 
1182
 
 
1183
 
 
1184
/* Tracing facility     */
 
1185
void    __util$trace    (int cond, const char *fmt, const char *mod, const char *func, unsigned line, ...);
 
1186
 
 
1187
#ifdef  __TRACE__
 
1188
        #ifndef $TRACE
 
1189
                #define $TRACE(fmt, ...)        __util$trace(1, fmt, __MODULE__, __FUNCTION__, __LINE__ , ## __VA_ARGS__)
 
1190
        #endif
 
1191
 
 
1192
        #ifndef $IFTRACE
 
1193
                #define $IFTRACE(cond, fmt, ...) __util$trace(cond, fmt, __MODULE__, __FUNCTION__, __LINE__ , ## __VA_ARGS__)
 
1194
        #endif
 
1195
#else
 
1196
        #define $TRACE(fmt, ...)        {}
 
1197
        #define $IFTRACE(cond, fmt, ...)        {}
 
1198
 
 
1199
#endif
 
1200
 
 
1201
/* Counted (length-byte-prefixed) ASCII string, see VMS's ASCIC */
 
1202
 
 
1203
 
 
1204
#define ASC$K_SZ        255
 
1205
 
 
1206
typedef struct _asc
 
1207
{
 
1208
        unsigned char   len;
 
1209
        char    sts[ASC$K_SZ];
 
1210
 
 
1211
        #define __ASC_TYPE__    1
 
1212
} ASC;
 
1213
 
 
1214
 
 
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)
 
1221
#define $ASCNIL         0,0
 
1222
 
 
1223
 
 
1224
/* Copying ASCIIZ string to ASCIC container */
 
1225
inline static int       __util$str2asc
 
1226
                        (
 
1227
                char *  src,
 
1228
                ASC *   dst
 
1229
                        )
 
1230
{
 
1231
        $ASCLEN(dst) = (unsigned char) strnlen(src, ASC$K_SZ);
 
1232
        memcpy($ASCPTR(dst), src, $ASCLEN(dst) );
 
1233
        dst->sts[dst->len] = '\0';
 
1234
 
 
1235
        return  $ASCLEN(dst);
 
1236
}
 
1237
 
 
1238
 
 
1239
/* Comparing two ASCIC */
 
1240
inline static int       __util$cmpasc
 
1241
                        (
 
1242
                ASC *   s1,
 
1243
                ASC *   s2
 
1244
                        )
 
1245
{
 
1246
int     status;
 
1247
 
 
1248
        if ( status = ($ASCLEN(s1) - $ASCLEN(s2)) )
 
1249
                return  status;
 
1250
 
 
1251
        return  memcmp($ASCPTR(s1), $ASCPTR(s2), $ASCLEN(s1) );
 
1252
}
 
1253
 
 
1254
#define $DUMPHEX(s,l)   __util$dumphex(__FUNCTION__, __LINE__ , s, l)
 
1255
void    __util$dumphex  (char *__fi, unsigned __li, void  * src, unsigned short srclen);
 
1256
 
 
1257
/*
 
1258
** @RRL: Perform an addittion of two times with overflow control and handling.
 
1259
*/
 
1260
inline static void __util$add_time(struct timespec* time1, struct timespec* time2, struct timespec* result_time)
 
1261
{
 
1262
time_t sec = time1->tv_sec + time2->tv_sec;
 
1263
long nsec = time1->tv_nsec + time2->tv_nsec;
 
1264
 
 
1265
        sec += nsec / 1000000000L;
 
1266
        nsec = nsec % 1000000000L;
 
1267
 
 
1268
        result_time->tv_sec = sec;
 
1269
        result_time->tv_nsec = nsec;
 
1270
}
 
1271
 
 
1272
 
 
1273
/*
 
1274
** @RRL: Perform a subsctration of two times.
 
1275
*/
 
1276
 
 
1277
/*
 
1278
struct timespec diff(struct timespec start, struct timespec end)
 
1279
{
 
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;
 
1284
    } else {
 
1285
        temp.tv_sec = end.tv_sec-start.tv_sec;
 
1286
        temp.tv_nsec = end.tv_nsec-start.tv_nsec;
 
1287
    }
 
1288
    return temp;
 
1289
}
 
1290
*/
 
1291
 
 
1292
inline static void __util$sub_time(struct timespec * time1, struct timespec* time2, struct timespec* result_time)
 
1293
{
 
1294
struct timespec temp;
 
1295
 
 
1296
        temp.tv_sec = time1->tv_sec - time2->tv_sec;
 
1297
        temp.tv_nsec = time1->tv_nsec - time2->tv_nsec;
 
1298
 
 
1299
        *result_time = temp;
 
1300
}
 
1301
 
 
1302
 
 
1303
 
 
1304
/*
 
1305
 *   RETURN
 
1306
 *      0       - time1 == time2
 
1307
 *      0 >     - time1 < time2
 
1308
 *      0 <     - time1 > time2
 
1309
 */
 
1310
inline static int __util$cmp_time(struct timespec * time1, struct timespec* time2)
 
1311
{
 
1312
        if ( time1->tv_sec - time2->tv_sec )
 
1313
                return  (time1->tv_sec - time2->tv_sec);
 
1314
 
 
1315
        return  (time1->tv_nsec - time2->tv_nsec);
 
1316
}
 
1317
 
 
1318
/*
 
1319
 * INCrement , DECrement ...
 
1320
 */
 
1321
#define $ATOMIC_INC(val)        __sync_fetch_and_add (&val, 1)
 
1322
#define $ATOMIC_DEC(val)        __sync_fetch_and_sub (&val, 1)
 
1323
 
 
1324
/*
 
1325
 * Processing command line options stuff
 
1326
 */
 
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*/
 
1335
 
 
1336
 
 
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   */
 
1342
        } OPTS;
 
1343
 
 
1344
#define OPTS_NULL { {0, 0}, NULL, 0, 0}
 
1345
 
 
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);
 
1350
 
 
1351
int     __util$deflog           (const char *, const char *);
 
1352
int     __util$rewindlogfile    (int);
 
1353
int     __util$pattern_match    (char * str$, char * pattern$);
 
1354
 
 
1355
char *  __util$strstr           (char *s1, size_t s1len, char *s2, size_t s2len);
 
1356
 
 
1357
unsigned        __util$crc32c   (unsigned int crc, const void *buf, size_t buflen);
 
1358
 
 
1359
/**
 
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.
 
1363
 *
 
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
 
1367
 *
 
1368
 * @return      -       A length of the data in the output buffer
 
1369
 *
 
1370
 */
 
1371
inline  static int __util$hex2bin
 
1372
                (
 
1373
                void *  srchex,
 
1374
                void *  dstbin,
 
1375
        unsigned short  srchexlen
 
1376
                )
 
1377
{
 
1378
unsigned char   c, l = 0, h = 0, *__srchex = (unsigned char *) srchex, *__dstbin = (unsigned char *) dstbin;
 
1379
int     retlen = (srchexlen + 1) / 2, i;
 
1380
 
 
1381
        /* We will converting from tail to head */
 
1382
        __srchex += (srchexlen - 1);
 
1383
        __dstbin += (retlen - 1);
 
1384
 
 
1385
        for( i = (srchexlen / 2); i; i--, __dstbin--, __srchex--)
 
1386
                {
 
1387
                c = tolower(*__srchex);
 
1388
                l = ((c) <= '9') ? (c) - '0' : (c) - 'a' + 10;
 
1389
 
 
1390
                __srchex--;
 
1391
 
 
1392
                c = tolower(*__srchex);
 
1393
                h = ((c) <= '9') ? (c) - '0' : (c) - 'a' + 10;
 
1394
 
 
1395
 
 
1396
                *__dstbin    = c = l | (h << 4);
 
1397
                }
 
1398
 
 
1399
        if ( srchexlen % 2)
 
1400
                {
 
1401
                c = tolower(*__srchex);
 
1402
                l = ((c) <= '9') ? (c) - '0' : (c) - 'a' + 10;
 
1403
 
 
1404
                *__dstbin    = c = l;
 
1405
                }
 
1406
 
 
1407
 
 
1408
 
 
1409
        return  retlen;
 
1410
}
 
1411
 
 
1412
/**
 
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.
 
1416
 *
 
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
 
1420
 *
 
1421
 * @return      -       A length of the data in the output buffer
 
1422
 *
 
1423
 */
 
1424
inline  static int __util$bin2hex
 
1425
                (
 
1426
                void *  srcbin,
 
1427
                void *  dsthex,
 
1428
        unsigned short  srcbinlen
 
1429
                )
 
1430
{
 
1431
unsigned char    l = 0, h = 0, *__srcbin = (unsigned char *) srcbin, *__dsthex = (unsigned char *) dsthex; ;
 
1432
int     retlen = srcbinlen * 2;
 
1433
 
 
1434
        __dsthex[retlen] = '\0';
 
1435
 
 
1436
        for( ; srcbinlen; srcbinlen--, __dsthex += 2, __srcbin++)
 
1437
                {
 
1438
                h       = (*__srcbin) >> 4;
 
1439
                h       &= 0x0F;
 
1440
                l       = (*__srcbin) & 0x0F;
 
1441
 
 
1442
                *__dsthex    = (h < 10) ? h + '0' : h + 'a' - 10;
 
1443
                *(__dsthex+1)= (l < 10) ? l + '0' : l + 'a' - 10;
 
1444
                }
 
1445
 
 
1446
 
 
1447
        return  retlen;
 
1448
}
 
1449
 
 
1450
#define $BIN2HEX(s,d,l) __util$bin2hex((char*) s, (char*) d, (unsigned short) l)
 
1451
 
 
1452
/*
 
1453
 *
 
1454
 *  Description: removes leading and trailing spaces or tabs (HT and VT, CR, LF) from string
 
1455
 *  Input:
 
1456
 *      src:    a pointer to the buffer wit string to process
 
1457
 *      srclen: a length of the source buffer
 
1458
 *
 
1459
 *  Return:
 
1460
 *      a length of the actual data in the source buffer
 
1461
 *
 
1462
 */
 
1463
inline static int       __util$uncomment        (
 
1464
                char    *src,
 
1465
                int     srclen,
 
1466
                char    marker
 
1467
                        )
 
1468
{
 
1469
int     count;
 
1470
char *  cp, *cmnt = NULL;
 
1471
 
 
1472
        if ( !srclen || !src )
 
1473
                return 0;
 
1474
 
 
1475
        /*
 
1476
         * Remove comments from end of string
 
1477
         */
 
1478
        for (count = srclen, cp = src + (srclen - 1); count; count--, cp--)
 
1479
                cmnt = *cp == marker ? cp : cmnt;
 
1480
 
 
1481
        if ( cmnt )
 
1482
                {
 
1483
                *cmnt = '\0';
 
1484
                srclen = (int) (cmnt - src);
 
1485
                }
 
1486
 
 
1487
        return  srclen;
 
1488
}
 
1489
 
 
1490
/*
 
1491
 *
 
1492
 *  Description: removes leading and trailing spaces or tabs (HT and VT, CR, LF) from string
 
1493
 *  Input:
 
1494
 *      src:    a pointer to the buffer wit string to process
 
1495
 *      srclen: a length of the source buffer
 
1496
 *
 
1497
 *  Return:
 
1498
 *      a length of the actual data in the source buffer
 
1499
 *
 
1500
 */
 
1501
inline static int       __util$trim     (
 
1502
                char    *src,
 
1503
                int     srclen
 
1504
                        )
 
1505
{
 
1506
int     count;
 
1507
char *  cp;
 
1508
 
 
1509
        if ( !srclen || !src )
 
1510
                return 0;
 
1511
 
 
1512
        /*
 
1513
         * Trim all space and tabs at begin of the string ...
 
1514
         */
 
1515
        for (count = 0, cp = src; isspace (*cp) && (count < srclen); count++, cp++);
 
1516
 
 
1517
        if ( count )
 
1518
                {
 
1519
                memmove(src, cp, srclen -= count);
 
1520
                *(src + srclen) = '\0';
 
1521
                }
 
1522
 
 
1523
        if ( !srclen )
 
1524
                return 0;
 
1525
 
 
1526
        /*
 
1527
         * Trim spaces at end of string ...
 
1528
         */
 
1529
        for (count = 0, cp = src + srclen; isspace (*(--cp)) && (count < srclen); count++);
 
1530
 
 
1531
        if ( count )
 
1532
                {
 
1533
                * (cp + 1) = '\0';
 
1534
                srclen -= count;
 
1535
                }
 
1536
 
 
1537
        return  srclen;
 
1538
}
 
1539
 
 
1540
/*
 
1541
 *
 
1542
 *  Description: removes all spaces or tabs (HT and VT, CR, LF) from string
 
1543
 *  Input:
 
1544
 *      src:    a pointer to the buffer with string to process
 
1545
 *      srclen: a length of the source buffer
 
1546
 *
 
1547
 *  Return:
 
1548
 *      a length of the actual data in the source buffer
 
1549
 *
 
1550
 */
 
1551
inline static int       __util$collapse (
 
1552
                char    *src,
 
1553
                int     srclen
 
1554
                        )
 
1555
{
 
1556
int     count;
 
1557
char *  cp;
 
1558
 
 
1559
        if ( !srclen || !src )
 
1560
                return 0;
 
1561
 
 
1562
        /*
 
1563
         * Remove all spaces or tabs
 
1564
         */
 
1565
        for (count = 0, cp = src; srclen; src++, srclen--)
 
1566
                if ( !isspace (*src) )
 
1567
                        {
 
1568
                        *(cp++) = *src;
 
1569
                        count++;
 
1570
                        }
 
1571
 
 
1572
        *cp = '\0';
 
1573
 
 
1574
        return  count;
 
1575
}
 
1576
 
 
1577
/**
 
1578
 * @brief __UTIL$STRCAT_RX - concatenates given list of strings into the single area.
 
1579
 *
 
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
 
1583
 *
 
1584
 * @return -    STS$K_SUCCESS
 
1585
 *              STS$K_ERROR - output buffer is overflow
 
1586
 */
 
1587
inline static   int     __util$strcat_rx        (
 
1588
        void    *       dst,
 
1589
        int     dstsz,
 
1590
        int *   dstlen,
 
1591
        ...
 
1592
        )
 
1593
{
 
1594
va_list ap;
 
1595
char *  srcp, *dstp = (char *) dst;
 
1596
int     srclen, status = STS$K_ERROR;
 
1597
 
 
1598
        /* Initialize the argument list. */
 
1599
        va_start (ap, dstlen);
 
1600
 
 
1601
        /* Looping until destination buffer have a free space */
 
1602
        for ( *dstlen = srclen = 0; (dstsz - *dstlen); )
 
1603
                {
 
1604
                /* NULL is a "end-of-list" marker */
 
1605
                if ( !(srcp = va_arg(ap, char *)) )
 
1606
                        {
 
1607
                        status = STS$K_SUCCESS;
 
1608
                        break;
 
1609
                        }
 
1610
 
 
1611
                /* Get source length, zero - skip to next */
 
1612
                if ( !(srclen = va_arg(ap, int)) )
 
1613
                        continue;
 
1614
 
 
1615
                if ( srclen > (dstsz - *dstlen) )
 
1616
                        break;
 
1617
 
 
1618
                memmove(dstp + *dstlen, srcp, srclen);
 
1619
                *dstlen += srclen;
 
1620
                }
 
1621
 
 
1622
        *(dstp + *dstlen) = '\0';
 
1623
        va_end(ap);
 
1624
 
 
1625
        return  status;
 
1626
}
 
1627
 
 
1628
 
 
1629
/*
 
1630
*/
 
1631
#define util$K_LOOKUP_NCASE     (1 << 0)
 
1632
#define util$K_LOOKUP_ABBREV    (1 << 1)
 
1633
 
 
1634
typedef struct _kwdent
 
1635
{
 
1636
        ASC *   kwd;
 
1637
        union   {
 
1638
                int     val;
 
1639
                void *  ptr;
 
1640
                };
 
1641
} KWDENT;
 
1642
 
 
1643
inline  static  int     __util$lookup_key       (
 
1644
                        char    *src,
 
1645
                        int     srclen,
 
1646
 
 
1647
                KWDENT *        ktbl,
 
1648
                        int     ktblsz,
 
1649
 
 
1650
                KWDENT  **      kwd,
 
1651
 
 
1652
                        int     flags
 
1653
                        )
 
1654
{
 
1655
int     status = STS$K_ERROR, len;
 
1656
KWDENT *        k = ktbl;
 
1657
 
 
1658
        for ( k = ktbl, len = 0; ktblsz; ktblsz--, k++)
 
1659
                {
 
1660
                /* Exact comparing or abbreviated ? */
 
1661
                if ( !(flags & util$K_LOOKUP_ABBREV) )
 
1662
                        if ( srclen != k->kwd->len )
 
1663
                                continue;
 
1664
 
 
1665
                /*
 
1666
                * We performs a comparing only in case when a compare length is
 
1667
                * more then at previous step.
 
1668
                */
 
1669
                if ( len < $MIN(srclen, k->kwd->len) )
 
1670
                        len = $MIN(srclen, k->kwd->len);
 
1671
                else    continue;
 
1672
 
 
1673
 
 
1674
                /* Comparing ... */
 
1675
                status = (flags & util$K_LOOKUP_NCASE) ?
 
1676
#ifdef  WIN32
 
1677
 
 
1678
                        _strnicmp
 
1679
#else
 
1680
                        strncasecmp
 
1681
#endif
 
1682
                        (src, k->kwd->sts, len) : memcmp(src, k->kwd->sts, len);
 
1683
 
 
1684
                if ( status )
 
1685
                        continue;
 
1686
                }
 
1687
 
 
1688
        /* No matching ... */
 
1689
        if ( status )
 
1690
                return  STS$K_ERROR;
 
1691
 
 
1692
        *kwd = k;
 
1693
}
 
1694
 
 
1695
 
 
1696
 
 
1697
/**
 
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.
 
1700
 *
 
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
 
1704
 *
 
1705
 * @return -    length of the data in the output buffer.
 
1706
 */
 
1707
inline static int       __util$uuid2str (
 
1708
                void *  uuid,
 
1709
                char *  buf,
 
1710
                int     bufsz
 
1711
                        )
 
1712
{
 
1713
unsigned char   tmp [256], *puuid = (unsigned char *) uuid;
 
1714
int     len;
 
1715
 
 
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]);
 
1719
 
 
1720
        memcpy(buf, tmp, len = $MIN(bufsz, len));
 
1721
        buf[len] = '\0';
 
1722
 
 
1723
        return  len;
 
1724
}
 
1725
 
 
1726
 
 
1727
 
 
1728
 
 
1729
/**
 
1730
 * @brief __UTIL$FILL - Fill destination buffer with a pattern data.
 
1731
 *
 
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
 
1736
 * @return
 
1737
 */
 
1738
static inline   int     __util$fill     (
 
1739
                void    *       dst,
 
1740
                int             dstsz,
 
1741
                void    *       src,
 
1742
                int             srcsz
 
1743
                        )
 
1744
{
 
1745
int     fillen = 0;
 
1746
char *  _dst = (char *) dst;
 
1747
 
 
1748
        while ( dstsz )
 
1749
                {
 
1750
                fillen = $MIN(srcsz, dstsz);
 
1751
                memcpy(_dst, src, fillen);
 
1752
 
 
1753
                dstsz   -= fillen;
 
1754
                _dst    += fillen;
 
1755
 
 
1756
 
 
1757
                }
 
1758
 
 
1759
        return  STS$K_SUCCESS;
 
1760
}
 
1761
 
 
1762
 
 
1763
 
 
1764
/**
 
1765
 * @brief __UTIL$STRXOR - XORing octet source string with a given key to produde result to the destination buffer
 
1766
 *
 
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
 
1773
 * @return
 
1774
 */
 
1775
static inline   int     __util$strxor   (
 
1776
                void    *       key,
 
1777
                int             keysz,
 
1778
                void    *       src,
 
1779
                int             srcsz,
 
1780
                void    *       dst,
 
1781
                int             dstsz
 
1782
                        )
 
1783
{
 
1784
unsigned char   *kp, *sp, *dp;
 
1785
int     sz = (srcsz > dstsz) ? dstsz : srcsz;
 
1786
 
 
1787
        for ( kp = key, sp = src, dp = dst; sz; sz--, dp++, sp++, kp++ )
 
1788
                {
 
1789
                if ( kp >= ( (char *) key + keysz) )            /* Check and reset a pointer to byte in the key buffer */
 
1790
                        kp = key;
 
1791
 
 
1792
                (*dp) = (*sp) ^ (*kp);                          /* XOR */
 
1793
 
 
1794
                }
 
1795
 
 
1796
        return  STS$K_SUCCESS;
 
1797
}
 
1798
 
 
1799
 
 
1800
 
 
1801
 
 
1802
/*      LIB$MOVC5 - Execute MOVC5 instruction
 
1803
**++
 
1804
** FUNCTIONAL DESCRIPTION:
 
1805
**
 
1806
**      LIB$MOVC5 makes the VAX MOVC5 instruction available as
 
1807
**      a callable procedure.
 
1808
**
 
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.
 
1816
**
 
1817
**      For more information, see the VAX-11 Architecture Handbook.
 
1818
**
 
1819
** CALLING SEQUENCE:
 
1820
**
 
1821
**      status.wlc.v = LIB$MOVC5 (src_len.rwu.r, source.rz.r, fill.rb.r,
 
1822
**                                dst_len.rwu.r, dest.wz.r)
 
1823
**
 
1824
** FORMAL PARAMETERS:
 
1825
**
 
1826
**      src_len         ; The length of source in bytes.  Passed
 
1827
**                      ; by reference.  The maximum length is 65535.
 
1828
**
 
1829
**      source          ; The source to move from.  Passed by reference.
 
1830
**
 
1831
**      fill            ; The fill character.  Passed by reference.
 
1832
**
 
1833
**      dst_len         ; The length of dest in bytes.  Passed by
 
1834
**                      ; reference.  The maximum length is 65535.
 
1835
**
 
1836
**      dest            ; The destination to move to.  Passed by
 
1837
**                      ; reference.
 
1838
**
 
1839
**
 
1840
** IMPLICIT INPUTS:
 
1841
**
 
1842
**      NONE
 
1843
**
 
1844
** IMPLICIT OUTPUTS:
 
1845
**
 
1846
**      NONE
 
1847
**
 
1848
** COMPLETION STATUS:
 
1849
**
 
1850
**      SS$_NORMAL      Procedure successfully completed.
 
1851
**
 
1852
** SIDE EFFECTS:
 
1853
**
 
1854
**      NONE
 
1855
**
 
1856
**--
 
1857
 
 
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
 
1860
*/
 
1861
 
 
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       */
 
1868
                        )
 
1869
{
 
1870
        /*
 
1871
        *  if the destination is the same size as the source, or shorter
 
1872
        *  then this is a simple move.
 
1873
        */
 
1874
 
 
1875
        if (*srclen >= *dstlen)
 
1876
                memmove (dest, source, *dstlen);
 
1877
        else    {
 
1878
                /*
 
1879
                 * destination is larger, do move and fill
 
1880
                 */
 
1881
                memmove (dest, source, *srclen);
 
1882
                memset (&dest[*srclen], *fill, *dstlen - *srclen);
 
1883
                }
 
1884
 
 
1885
        return STS$K_SUCCESS;
 
1886
}
 
1887
 
 
1888
 
 
1889
#ifdef  __TRACE__
 
1890
//      #define $TRACEBACK(expr)        {if ( (expr) ) __util$traceback ( #expr, (expr) ); }
 
1891
#endif
 
1892
 
 
1893
#ifndef WIN32
 
1894
#pragma GCC diagnostic pop
 
1895
#endif
 
1896
 
 
1897
#pragma pack (pop)
 
1898
 
 
1899
#ifdef __cplusplus
 
1900
}
 
1901
#endif
 
1902
 
 
1903
#endif  /*      __util$UTILS__  */