minimap2 0.2.23.0 → 0.2.23.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +60 -76
  3. data/ext/Rakefile +41 -0
  4. data/ext/cmappy/cmappy.c +129 -0
  5. data/ext/cmappy/cmappy.h +44 -0
  6. data/ext/minimap2/FAQ.md +46 -0
  7. data/ext/minimap2/LICENSE.txt +24 -0
  8. data/ext/minimap2/MANIFEST.in +10 -0
  9. data/ext/minimap2/Makefile +132 -0
  10. data/ext/minimap2/Makefile.simde +97 -0
  11. data/ext/minimap2/NEWS.md +807 -0
  12. data/ext/minimap2/README.md +403 -0
  13. data/ext/minimap2/align.c +1020 -0
  14. data/ext/minimap2/bseq.c +169 -0
  15. data/ext/minimap2/bseq.h +64 -0
  16. data/ext/minimap2/code_of_conduct.md +30 -0
  17. data/ext/minimap2/cookbook.md +243 -0
  18. data/ext/minimap2/esterr.c +64 -0
  19. data/ext/minimap2/example.c +63 -0
  20. data/ext/minimap2/format.c +559 -0
  21. data/ext/minimap2/hit.c +466 -0
  22. data/ext/minimap2/index.c +775 -0
  23. data/ext/minimap2/kalloc.c +205 -0
  24. data/ext/minimap2/kalloc.h +76 -0
  25. data/ext/minimap2/kdq.h +132 -0
  26. data/ext/minimap2/ketopt.h +120 -0
  27. data/ext/minimap2/khash.h +615 -0
  28. data/ext/minimap2/krmq.h +474 -0
  29. data/ext/minimap2/kseq.h +256 -0
  30. data/ext/minimap2/ksort.h +153 -0
  31. data/ext/minimap2/ksw2.h +184 -0
  32. data/ext/minimap2/ksw2_dispatch.c +96 -0
  33. data/ext/minimap2/ksw2_extd2_sse.c +402 -0
  34. data/ext/minimap2/ksw2_exts2_sse.c +416 -0
  35. data/ext/minimap2/ksw2_extz2_sse.c +313 -0
  36. data/ext/minimap2/ksw2_ll_sse.c +152 -0
  37. data/ext/minimap2/kthread.c +159 -0
  38. data/ext/minimap2/kthread.h +15 -0
  39. data/ext/minimap2/kvec.h +105 -0
  40. data/ext/minimap2/lchain.c +344 -0
  41. data/ext/minimap2/main.c +455 -0
  42. data/ext/minimap2/map.c +714 -0
  43. data/ext/minimap2/minimap.h +409 -0
  44. data/ext/minimap2/minimap2.1 +722 -0
  45. data/ext/minimap2/misc/README.md +179 -0
  46. data/ext/minimap2/misc/mmphase.js +335 -0
  47. data/ext/minimap2/misc/paftools.js +3149 -0
  48. data/ext/minimap2/misc.c +162 -0
  49. data/ext/minimap2/mmpriv.h +131 -0
  50. data/ext/minimap2/options.c +233 -0
  51. data/ext/minimap2/pe.c +177 -0
  52. data/ext/minimap2/python/README.rst +196 -0
  53. data/ext/minimap2/python/cmappy.h +152 -0
  54. data/ext/minimap2/python/cmappy.pxd +153 -0
  55. data/ext/minimap2/python/mappy.pyx +273 -0
  56. data/ext/minimap2/python/minimap2.py +39 -0
  57. data/ext/minimap2/sdust.c +213 -0
  58. data/ext/minimap2/sdust.h +25 -0
  59. data/ext/minimap2/seed.c +131 -0
  60. data/ext/minimap2/setup.py +55 -0
  61. data/ext/minimap2/sketch.c +143 -0
  62. data/ext/minimap2/splitidx.c +84 -0
  63. data/ext/minimap2/sse2neon/emmintrin.h +1689 -0
  64. data/ext/minimap2/test/MT-human.fa +278 -0
  65. data/ext/minimap2/test/MT-orang.fa +276 -0
  66. data/ext/minimap2/test/q-inv.fa +4 -0
  67. data/ext/minimap2/test/q2.fa +2 -0
  68. data/ext/minimap2/test/t-inv.fa +127 -0
  69. data/ext/minimap2/test/t2.fa +2 -0
  70. data/ext/minimap2/tex/Makefile +21 -0
  71. data/ext/minimap2/tex/bioinfo.cls +930 -0
  72. data/ext/minimap2/tex/blasr-mc.eval +17 -0
  73. data/ext/minimap2/tex/bowtie2-s3.sam.eval +28 -0
  74. data/ext/minimap2/tex/bwa-s3.sam.eval +52 -0
  75. data/ext/minimap2/tex/bwa.eval +55 -0
  76. data/ext/minimap2/tex/eval2roc.pl +33 -0
  77. data/ext/minimap2/tex/graphmap.eval +4 -0
  78. data/ext/minimap2/tex/hs38-simu.sh +10 -0
  79. data/ext/minimap2/tex/minialign.eval +49 -0
  80. data/ext/minimap2/tex/minimap2.bib +460 -0
  81. data/ext/minimap2/tex/minimap2.tex +724 -0
  82. data/ext/minimap2/tex/mm2-s3.sam.eval +62 -0
  83. data/ext/minimap2/tex/mm2-update.tex +240 -0
  84. data/ext/minimap2/tex/mm2.approx.eval +12 -0
  85. data/ext/minimap2/tex/mm2.eval +13 -0
  86. data/ext/minimap2/tex/natbib.bst +1288 -0
  87. data/ext/minimap2/tex/natbib.sty +803 -0
  88. data/ext/minimap2/tex/ngmlr.eval +38 -0
  89. data/ext/minimap2/tex/roc.gp +60 -0
  90. data/ext/minimap2/tex/snap-s3.sam.eval +62 -0
  91. data/ext/minimap2.patch +19 -0
  92. data/{vendor → ext/vendor}/libminimap2.so +0 -0
  93. data/lib/minimap2/ffi/functions.rb +5 -0
  94. data/lib/minimap2/version.rb +1 -1
  95. data/lib/minimap2.rb +32 -0
  96. metadata +94 -4
@@ -0,0 +1,205 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+ #include "kalloc.h"
5
+
6
+ /* In kalloc, a *core* is a large chunk of contiguous memory. Each core is
7
+ * associated with a master header, which keeps the size of the current core
8
+ * and the pointer to next core. Kalloc allocates small *blocks* of memory from
9
+ * the cores and organizes free memory blocks in a circular single-linked list.
10
+ *
11
+ * In the following diagram, "@" stands for the header of a free block (of type
12
+ * header_t), "#" for the header of an allocated block (of type size_t), "-"
13
+ * for free memory, and "+" for allocated memory.
14
+ *
15
+ * master This region is core 1. master This region is core 2.
16
+ * | |
17
+ * *@-------#++++++#++++++++++++@-------- *@----------#++++++++++++#+++++++@------------
18
+ * | | | |
19
+ * p=p->ptr->ptr->ptr->ptr p->ptr p->ptr->ptr p->ptr->ptr->ptr
20
+ */
21
+ typedef struct header_t {
22
+ size_t size;
23
+ struct header_t *ptr;
24
+ } header_t;
25
+
26
+ typedef struct {
27
+ void *par;
28
+ size_t min_core_size;
29
+ header_t base, *loop_head, *core_head; /* base is a zero-sized block always kept in the loop */
30
+ } kmem_t;
31
+
32
+ static void panic(const char *s)
33
+ {
34
+ fprintf(stderr, "%s\n", s);
35
+ abort();
36
+ }
37
+
38
+ void *km_init2(void *km_par, size_t min_core_size)
39
+ {
40
+ kmem_t *km;
41
+ km = (kmem_t*)kcalloc(km_par, 1, sizeof(kmem_t));
42
+ km->par = km_par;
43
+ km->min_core_size = min_core_size > 0? min_core_size : 0x80000;
44
+ return (void*)km;
45
+ }
46
+
47
+ void *km_init(void) { return km_init2(0, 0); }
48
+
49
+ void km_destroy(void *_km)
50
+ {
51
+ kmem_t *km = (kmem_t*)_km;
52
+ void *km_par;
53
+ header_t *p, *q;
54
+ if (km == NULL) return;
55
+ km_par = km->par;
56
+ for (p = km->core_head; p != NULL;) {
57
+ q = p->ptr;
58
+ kfree(km_par, p);
59
+ p = q;
60
+ }
61
+ kfree(km_par, km);
62
+ }
63
+
64
+ static header_t *morecore(kmem_t *km, size_t nu)
65
+ {
66
+ header_t *q;
67
+ size_t bytes, *p;
68
+ nu = (nu + 1 + (km->min_core_size - 1)) / km->min_core_size * km->min_core_size; /* the first +1 for core header */
69
+ bytes = nu * sizeof(header_t);
70
+ q = (header_t*)kmalloc(km->par, bytes);
71
+ if (!q) panic("[morecore] insufficient memory");
72
+ q->ptr = km->core_head, q->size = nu, km->core_head = q;
73
+ p = (size_t*)(q + 1);
74
+ *p = nu - 1; /* the size of the free block; -1 because the first unit is used for the core header */
75
+ kfree(km, p + 1); /* initialize the new "core"; NB: the core header is not looped. */
76
+ return km->loop_head;
77
+ }
78
+
79
+ void kfree(void *_km, void *ap) /* kfree() also adds a new core to the circular list */
80
+ {
81
+ header_t *p, *q;
82
+ kmem_t *km = (kmem_t*)_km;
83
+
84
+ if (!ap) return;
85
+ if (km == NULL) {
86
+ free(ap);
87
+ return;
88
+ }
89
+ p = (header_t*)((size_t*)ap - 1);
90
+ p->size = *((size_t*)ap - 1);
91
+ /* Find the pointer that points to the block to be freed. The following loop can stop on two conditions:
92
+ *
93
+ * a) "p>q && p<q->ptr": @------#++++++++#+++++++@------- @---------------#+++++++@-------
94
+ * (can also be in | | | -> | |
95
+ * two cores) q p q->ptr q q->ptr
96
+ *
97
+ * @-------- #+++++++++@-------- @-------- @------------------
98
+ * | | | -> | |
99
+ * q p q->ptr q q->ptr
100
+ *
101
+ * b) "q>=q->ptr && (p>q || p<q->ptr)": @-------#+++++ @--------#+++++++ @-------#+++++ @----------------
102
+ * | | | -> | |
103
+ * q->ptr q p q->ptr q
104
+ *
105
+ * #+++++++@----- #++++++++@------- @------------- #++++++++@-------
106
+ * | | | -> | |
107
+ * p q->ptr q q->ptr q
108
+ */
109
+ for (q = km->loop_head; !(p > q && p < q->ptr); q = q->ptr)
110
+ if (q >= q->ptr && (p > q || p < q->ptr)) break;
111
+ if (p + p->size == q->ptr) { /* two adjacent blocks, merge p and q->ptr (the 2nd and 4th cases) */
112
+ p->size += q->ptr->size;
113
+ p->ptr = q->ptr->ptr;
114
+ } else if (p + p->size > q->ptr && q->ptr >= p) {
115
+ panic("[kfree] The end of the allocated block enters a free block.");
116
+ } else p->ptr = q->ptr; /* backup q->ptr */
117
+
118
+ if (q + q->size == p) { /* two adjacent blocks, merge q and p (the other two cases) */
119
+ q->size += p->size;
120
+ q->ptr = p->ptr;
121
+ km->loop_head = q;
122
+ } else if (q + q->size > p && p >= q) {
123
+ panic("[kfree] The end of a free block enters the allocated block.");
124
+ } else km->loop_head = p, q->ptr = p; /* in two cores, cannot be merged; create a new block in the list */
125
+ }
126
+
127
+ void *kmalloc(void *_km, size_t n_bytes)
128
+ {
129
+ kmem_t *km = (kmem_t*)_km;
130
+ size_t n_units;
131
+ header_t *p, *q;
132
+
133
+ if (n_bytes == 0) return 0;
134
+ if (km == NULL) return malloc(n_bytes);
135
+ n_units = (n_bytes + sizeof(size_t) + sizeof(header_t) - 1) / sizeof(header_t); /* header+n_bytes requires at least this number of units */
136
+
137
+ if (!(q = km->loop_head)) /* the first time when kmalloc() is called, intialize it */
138
+ q = km->loop_head = km->base.ptr = &km->base;
139
+ for (p = q->ptr;; q = p, p = p->ptr) { /* search for a suitable block */
140
+ if (p->size >= n_units) { /* p->size if the size of current block. This line means the current block is large enough. */
141
+ if (p->size == n_units) q->ptr = p->ptr; /* no need to split the block */
142
+ else { /* split the block. NB: memory is allocated at the end of the block! */
143
+ p->size -= n_units; /* reduce the size of the free block */
144
+ p += p->size; /* p points to the allocated block */
145
+ *(size_t*)p = n_units; /* set the size */
146
+ }
147
+ km->loop_head = q; /* set the end of chain */
148
+ return (size_t*)p + 1;
149
+ }
150
+ if (p == km->loop_head) { /* then ask for more "cores" */
151
+ if ((p = morecore(km, n_units)) == 0) return 0;
152
+ }
153
+ }
154
+ }
155
+
156
+ void *kcalloc(void *_km, size_t count, size_t size)
157
+ {
158
+ kmem_t *km = (kmem_t*)_km;
159
+ void *p;
160
+ if (size == 0 || count == 0) return 0;
161
+ if (km == NULL) return calloc(count, size);
162
+ p = kmalloc(km, count * size);
163
+ memset(p, 0, count * size);
164
+ return p;
165
+ }
166
+
167
+ void *krealloc(void *_km, void *ap, size_t n_bytes) // TODO: this can be made more efficient in principle
168
+ {
169
+ kmem_t *km = (kmem_t*)_km;
170
+ size_t cap, *p, *q;
171
+
172
+ if (n_bytes == 0) {
173
+ kfree(km, ap); return 0;
174
+ }
175
+ if (km == NULL) return realloc(ap, n_bytes);
176
+ if (ap == NULL) return kmalloc(km, n_bytes);
177
+ p = (size_t*)ap - 1;
178
+ cap = (*p) * sizeof(header_t) - sizeof(size_t);
179
+ if (cap >= n_bytes) return ap; /* TODO: this prevents shrinking */
180
+ q = (size_t*)kmalloc(km, n_bytes);
181
+ memcpy(q, ap, cap);
182
+ kfree(km, ap);
183
+ return q;
184
+ }
185
+
186
+ void km_stat(const void *_km, km_stat_t *s)
187
+ {
188
+ kmem_t *km = (kmem_t*)_km;
189
+ header_t *p;
190
+ memset(s, 0, sizeof(km_stat_t));
191
+ if (km == NULL || km->loop_head == NULL) return;
192
+ for (p = km->loop_head;; p = p->ptr) {
193
+ s->available += p->size * sizeof(header_t);
194
+ if (p->size != 0) ++s->n_blocks; /* &kmem_t::base is always one of the cores. It is zero-sized. */
195
+ if (p->ptr > p && p + p->size > p->ptr)
196
+ panic("[km_stat] The end of a free block enters another free block.");
197
+ if (p->ptr == km->loop_head) break;
198
+ }
199
+ for (p = km->core_head; p != NULL; p = p->ptr) {
200
+ size_t size = p->size * sizeof(header_t);
201
+ ++s->n_cores;
202
+ s->capacity += size;
203
+ s->largest = s->largest > size? s->largest : size;
204
+ }
205
+ }
@@ -0,0 +1,76 @@
1
+ #ifndef _KALLOC_H_
2
+ #define _KALLOC_H_
3
+
4
+ #include <stddef.h> /* for size_t */
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ typedef struct {
11
+ size_t capacity, available, n_blocks, n_cores, largest;
12
+ } km_stat_t;
13
+
14
+ void *kmalloc(void *km, size_t size);
15
+ void *krealloc(void *km, void *ptr, size_t size);
16
+ void *kcalloc(void *km, size_t count, size_t size);
17
+ void kfree(void *km, void *ptr);
18
+
19
+ void *km_init(void);
20
+ void *km_init2(void *km_par, size_t min_core_size);
21
+ void km_destroy(void *km);
22
+ void km_stat(const void *_km, km_stat_t *s);
23
+
24
+ #ifdef __cplusplus
25
+ }
26
+ #endif
27
+
28
+ #define KMALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kmalloc((km), (len) * sizeof(*(ptr))))
29
+ #define KCALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kcalloc((km), (len), sizeof(*(ptr))))
30
+ #define KREALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))krealloc((km), (ptr), (len) * sizeof(*(ptr))))
31
+
32
+ #define KEXPAND(km, a, m) do { \
33
+ (m) = (m) >= 4? (m) + ((m)>>1) : 16; \
34
+ KREALLOC((km), (a), (m)); \
35
+ } while (0)
36
+
37
+ #ifndef klib_unused
38
+ #if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
39
+ #define klib_unused __attribute__ ((__unused__))
40
+ #else
41
+ #define klib_unused
42
+ #endif
43
+ #endif /* klib_unused */
44
+
45
+ #define KALLOC_POOL_INIT2(SCOPE, name, kmptype_t) \
46
+ typedef struct { \
47
+ size_t cnt, n, max; \
48
+ kmptype_t **buf; \
49
+ void *km; \
50
+ } kmp_##name##_t; \
51
+ SCOPE kmp_##name##_t *kmp_init_##name(void *km) { \
52
+ kmp_##name##_t *mp; \
53
+ KCALLOC(km, mp, 1); \
54
+ mp->km = km; \
55
+ return mp; \
56
+ } \
57
+ SCOPE void kmp_destroy_##name(kmp_##name##_t *mp) { \
58
+ size_t k; \
59
+ for (k = 0; k < mp->n; ++k) kfree(mp->km, mp->buf[k]); \
60
+ kfree(mp->km, mp->buf); kfree(mp->km, mp); \
61
+ } \
62
+ SCOPE kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \
63
+ ++mp->cnt; \
64
+ if (mp->n == 0) return (kmptype_t*)kcalloc(mp->km, 1, sizeof(kmptype_t)); \
65
+ return mp->buf[--mp->n]; \
66
+ } \
67
+ SCOPE void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \
68
+ --mp->cnt; \
69
+ if (mp->n == mp->max) KEXPAND(mp->km, mp->buf, mp->max); \
70
+ mp->buf[mp->n++] = p; \
71
+ }
72
+
73
+ #define KALLOC_POOL_INIT(name, kmptype_t) \
74
+ KALLOC_POOL_INIT2(static inline klib_unused, name, kmptype_t)
75
+
76
+ #endif
@@ -0,0 +1,132 @@
1
+ #ifndef __AC_KDQ_H
2
+ #define __AC_KDQ_H
3
+
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+ #include <stdint.h>
7
+ #include "kalloc.h"
8
+
9
+ #define __KDQ_TYPE(type) \
10
+ typedef struct { \
11
+ uint64_t front:58, bits:6, count, mask; \
12
+ type *a; \
13
+ void *km; \
14
+ } kdq_##type##_t;
15
+
16
+ #define kdq_t(type) kdq_##type##_t
17
+ #define kdq_size(q) ((q)->count)
18
+ #define kdq_first(q) ((q)->a[(q)->front])
19
+ #define kdq_last(q) ((q)->a[((q)->front + (q)->count - 1) & (q)->mask])
20
+ #define kdq_at(q, i) ((q)->a[((q)->front + (i)) & (q)->mask])
21
+
22
+ #define __KDQ_IMPL(type, SCOPE) \
23
+ SCOPE kdq_##type##_t *kdq_init_##type(void *km) \
24
+ { \
25
+ kdq_##type##_t *q; \
26
+ q = (kdq_##type##_t*)kcalloc(km, 1, sizeof(kdq_##type##_t)); \
27
+ q->bits = 2, q->mask = (1ULL<<q->bits) - 1; \
28
+ q->a = (type*)kmalloc(km, (1<<q->bits) * sizeof(type)); \
29
+ q->km = km; \
30
+ return q; \
31
+ } \
32
+ SCOPE void kdq_destroy_##type(kdq_##type##_t *q) \
33
+ { \
34
+ if (q == 0) return; \
35
+ kfree(q->km, q->a); kfree(q->km, q); \
36
+ } \
37
+ SCOPE int kdq_resize_##type(kdq_##type##_t *q, int new_bits) \
38
+ { \
39
+ size_t new_size = 1ULL<<new_bits, old_size = 1ULL<<q->bits; \
40
+ if (new_size < q->count) { /* not big enough */ \
41
+ int i; \
42
+ for (i = 0; i < 64; ++i) \
43
+ if (1ULL<<i > q->count) break; \
44
+ new_bits = i, new_size = 1ULL<<new_bits; \
45
+ } \
46
+ if (new_bits == q->bits) return q->bits; /* unchanged */ \
47
+ if (new_bits > q->bits) q->a = (type*)krealloc(q->km, q->a, (1ULL<<new_bits) * sizeof(type)); \
48
+ if (q->front + q->count <= old_size) { /* unwrapped */ \
49
+ if (q->front + q->count > new_size) /* only happens for shrinking */ \
50
+ memmove(q->a, q->a + new_size, (q->front + q->count - new_size) * sizeof(type)); \
51
+ } else { /* wrapped */ \
52
+ memmove(q->a + (new_size - (old_size - q->front)), q->a + q->front, (old_size - q->front) * sizeof(type)); \
53
+ q->front = new_size - (old_size - q->front); \
54
+ } \
55
+ q->bits = new_bits, q->mask = (1ULL<<q->bits) - 1; \
56
+ if (new_bits < q->bits) q->a = (type*)krealloc(q->km, q->a, (1ULL<<new_bits) * sizeof(type)); \
57
+ return q->bits; \
58
+ } \
59
+ SCOPE type *kdq_pushp_##type(kdq_##type##_t *q) \
60
+ { \
61
+ if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
62
+ return &q->a[((q->count++) + q->front) & (q)->mask]; \
63
+ } \
64
+ SCOPE void kdq_push_##type(kdq_##type##_t *q, type v) \
65
+ { \
66
+ if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
67
+ q->a[((q->count++) + q->front) & (q)->mask] = v; \
68
+ } \
69
+ SCOPE type *kdq_unshiftp_##type(kdq_##type##_t *q) \
70
+ { \
71
+ if (q->count == 1ULL<<q->bits) kdq_resize_##type(q, q->bits + 1); \
72
+ ++q->count; \
73
+ q->front = q->front? q->front - 1 : (1ULL<<q->bits) - 1; \
74
+ return &q->a[q->front]; \
75
+ } \
76
+ SCOPE void kdq_unshift_##type(kdq_##type##_t *q, type v) \
77
+ { \
78
+ type *p; \
79
+ p = kdq_unshiftp_##type(q); \
80
+ *p = v; \
81
+ } \
82
+ SCOPE type *kdq_pop_##type(kdq_##type##_t *q) \
83
+ { \
84
+ return q->count? &q->a[((--q->count) + q->front) & q->mask] : 0; \
85
+ } \
86
+ SCOPE type *kdq_shift_##type(kdq_##type##_t *q) \
87
+ { \
88
+ type *d = 0; \
89
+ if (q->count == 0) return 0; \
90
+ d = &q->a[q->front++]; \
91
+ q->front &= q->mask; \
92
+ --q->count; \
93
+ return d; \
94
+ }
95
+
96
+ #define KDQ_INIT2(type, SCOPE) \
97
+ __KDQ_TYPE(type) \
98
+ __KDQ_IMPL(type, SCOPE)
99
+
100
+ #ifndef klib_unused
101
+ #if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3)
102
+ #define klib_unused __attribute__ ((__unused__))
103
+ #else
104
+ #define klib_unused
105
+ #endif
106
+ #endif /* klib_unused */
107
+
108
+ #define KDQ_INIT(type) KDQ_INIT2(type, static inline klib_unused)
109
+
110
+ #define KDQ_DECLARE(type) \
111
+ __KDQ_TYPE(type) \
112
+ kdq_##type##_t *kdq_init_##type(); \
113
+ void kdq_destroy_##type(kdq_##type##_t *q); \
114
+ int kdq_resize_##type(kdq_##type##_t *q, int new_bits); \
115
+ type *kdq_pushp_##type(kdq_##type##_t *q); \
116
+ void kdq_push_##type(kdq_##type##_t *q, type v); \
117
+ type *kdq_unshiftp_##type(kdq_##type##_t *q); \
118
+ void kdq_unshift_##type(kdq_##type##_t *q, type v); \
119
+ type *kdq_pop_##type(kdq_##type##_t *q); \
120
+ type *kdq_shift_##type(kdq_##type##_t *q);
121
+
122
+ #define kdq_init(type, km) kdq_init_##type(km)
123
+ #define kdq_destroy(type, q) kdq_destroy_##type(q)
124
+ #define kdq_resize(type, q, new_bits) kdq_resize_##type(q, new_bits)
125
+ #define kdq_pushp(type, q) kdq_pushp_##type(q)
126
+ #define kdq_push(type, q, v) kdq_push_##type(q, v)
127
+ #define kdq_pop(type, q) kdq_pop_##type(q)
128
+ #define kdq_unshiftp(type, q) kdq_unshiftp_##type(q)
129
+ #define kdq_unshift(type, q, v) kdq_unshift_##type(q, v)
130
+ #define kdq_shift(type, q) kdq_shift_##type(q)
131
+
132
+ #endif
@@ -0,0 +1,120 @@
1
+ #ifndef KETOPT_H
2
+ #define KETOPT_H
3
+
4
+ #include <string.h> /* for strchr() and strncmp() */
5
+
6
+ #define ko_no_argument 0
7
+ #define ko_required_argument 1
8
+ #define ko_optional_argument 2
9
+
10
+ typedef struct {
11
+ int ind; /* equivalent to optind */
12
+ int opt; /* equivalent to optopt */
13
+ char *arg; /* equivalent to optarg */
14
+ int longidx; /* index of a long option; or -1 if short */
15
+ /* private variables not intended for external uses */
16
+ int i, pos, n_args;
17
+ } ketopt_t;
18
+
19
+ typedef struct {
20
+ char *name;
21
+ int has_arg;
22
+ int val;
23
+ } ko_longopt_t;
24
+
25
+ static ketopt_t KETOPT_INIT = { 1, 0, 0, -1, 1, 0, 0 };
26
+
27
+ static void ketopt_permute(char *argv[], int j, int n) /* move argv[j] over n elements to the left */
28
+ {
29
+ int k;
30
+ char *p = argv[j];
31
+ for (k = 0; k < n; ++k)
32
+ argv[j - k] = argv[j - k - 1];
33
+ argv[j - k] = p;
34
+ }
35
+
36
+ /**
37
+ * Parse command-line options and arguments
38
+ *
39
+ * This fuction has a similar interface to GNU's getopt_long(). Each call
40
+ * parses one option and returns the option name. s->arg points to the option
41
+ * argument if present. The function returns -1 when all command-line arguments
42
+ * are parsed. In this case, s->ind is the index of the first non-option
43
+ * argument.
44
+ *
45
+ * @param s status; shall be initialized to KETOPT_INIT on the first call
46
+ * @param argc length of argv[]
47
+ * @param argv list of command-line arguments; argv[0] is ignored
48
+ * @param permute non-zero to move options ahead of non-option arguments
49
+ * @param ostr option string
50
+ * @param longopts long options
51
+ *
52
+ * @return ASCII for a short option; ko_longopt_t::val for a long option; -1 if
53
+ * argv[] is fully processed; '?' for an unknown option or an ambiguous
54
+ * long option; ':' if an option argument is missing
55
+ */
56
+ static int ketopt(ketopt_t *s, int argc, char *argv[], int permute, const char *ostr, const ko_longopt_t *longopts)
57
+ {
58
+ int opt = -1, i0, j;
59
+ if (permute) {
60
+ while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0'))
61
+ ++s->i, ++s->n_args;
62
+ }
63
+ s->arg = 0, s->longidx = -1, i0 = s->i;
64
+ if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') {
65
+ s->ind = s->i - s->n_args;
66
+ return -1;
67
+ }
68
+ if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */
69
+ if (argv[s->i][2] == '\0') { /* a bare "--" */
70
+ ketopt_permute(argv, s->i, s->n_args);
71
+ ++s->i, s->ind = s->i - s->n_args;
72
+ return -1;
73
+ }
74
+ s->opt = 0, opt = '?', s->pos = -1;
75
+ if (longopts) { /* parse long options */
76
+ int k, n_exact = 0, n_partial = 0;
77
+ const ko_longopt_t *o = 0, *o_exact = 0, *o_partial = 0;
78
+ for (j = 2; argv[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */
79
+ for (k = 0; longopts[k].name != 0; ++k)
80
+ if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0) {
81
+ if (longopts[k].name[j - 2] == 0) ++n_exact, o_exact = &longopts[k];
82
+ else ++n_partial, o_partial = &longopts[k];
83
+ }
84
+ if (n_exact > 1 || (n_exact == 0 && n_partial > 1)) return '?';
85
+ o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0;
86
+ if (o) {
87
+ s->opt = opt = o->val, s->longidx = o - longopts;
88
+ if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1];
89
+ if (o->has_arg == 1 && argv[s->i][j] == '\0') {
90
+ if (s->i < argc - 1) s->arg = argv[++s->i];
91
+ else opt = ':'; /* missing option argument */
92
+ }
93
+ }
94
+ }
95
+ } else { /* a short option */
96
+ char *p;
97
+ if (s->pos == 0) s->pos = 1;
98
+ opt = s->opt = argv[s->i][s->pos++];
99
+ p = strchr((char*)ostr, opt);
100
+ if (p == 0) {
101
+ opt = '?'; /* unknown option */
102
+ } else if (p[1] == ':') {
103
+ if (argv[s->i][s->pos] == 0) {
104
+ if (s->i < argc - 1) s->arg = argv[++s->i];
105
+ else opt = ':'; /* missing option argument */
106
+ } else s->arg = &argv[s->i][s->pos];
107
+ s->pos = -1;
108
+ }
109
+ }
110
+ if (s->pos < 0 || argv[s->i][s->pos] == 0) {
111
+ ++s->i, s->pos = 0;
112
+ if (s->n_args > 0) /* permute */
113
+ for (j = i0; j < s->i; ++j)
114
+ ketopt_permute(argv, j, s->n_args);
115
+ }
116
+ s->ind = s->i - s->n_args;
117
+ return opt;
118
+ }
119
+
120
+ #endif