forked from urbit/vere
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdefs.h
203 lines (179 loc) · 6.86 KB
/
defs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/// @file
#ifndef C3_DEFS_H
#define C3_DEFS_H
#include "portable.h"
#include "types.h"
#include <errno.h>
/** Loobeans - inverse booleans to match nock.
**/
# define c3y 0
# define c3n 1
# define _(x) (c3y == (x))
# define __(x) ((x) ? c3y : c3n)
# define c3a(x, y) __(_(x) && _(y))
# define c3o(x, y) __(_(x) || _(y))
/** Random useful C macros.
**/
/* Dessert. Debug assert. If a debugger is attached, it will break in and
execution can be allowed to proceed without aborting the process.
Otherwise, the unhandled SIGTRAP will dump core.
*/
#ifdef C3DBG
#if defined(__i386__) || defined(__x86_64__)
#define c3_dessert(x) do { if(!(x)) __asm__ volatile("int $3"); } while (0)
#elif defined(__thumb__)
#define c3_dessert(x) do { if(!(x)) __asm__ volatile(".inst 0xde01"); } while (0)
#elif defined(__aarch64__)
#define c3_dessert(x) do { if(!(x)) __asm__ volatile(".inst 0xd4200000"); } while (0)
#elif defined(__arm__)
#define c3_dessert(x) do { if(!(x)) __asm__ volatile(".inst 0xe7f001f0"); } while (0)
#else
STATIC_ASSERT(0, "debugger break instruction unimplemented");
#endif
#else
#define c3_dessert(x) ((void)(0))
#endif
/* Stub.
*/
# define c3_stub u3_assert(!"stub")
/* Size in words.
*/
# define c3_wiseof(x) (((sizeof (x)) + 3) >> 2)
/* Bit counting.
*/
# define c3_bits_word(w) ((w) ? (32 - __builtin_clz(w)) : 0)
/* Min and max.
*/
# define c3_max(x, y) ( ((x) > (y)) ? (x) : (y) )
# define c3_min(x, y) ( ((x) < (y)) ? (x) : (y) )
//! Round up/down (respectively).
//!
//! @param[in] x Integer to round.
//! @param[in] n Multiple to round to. Must be power of 2.
//!
//! @return `x` rounded to the nearest multiple of `n`.
# define c3_rop(x, n) (((x) + ((n) - 1)) & (~((n) - 1)))
# define c3_rod(x, n) ((x) & ~((n) - 1))
/* Rotate.
*/
# define c3_rotw(r, x) ( ((x) << (r)) | ((x) >> (32 - (r))) )
/* Fill 16 words (64 bytes) with high-quality entropy.
*/
void
c3_rand(c3_w* rad_w);
/* Short integers.
*/
# define c3_s1(a) ( (a) )
# define c3_s2(a, b) ( ((b) << 8) | c3_s1(a) )
# define c3_s3(a, b, c) ( ((c) << 16) | c3_s2(a, b) )
# define c3_s4(a, b, c, d) ( ((d) << 24) | c3_s3(a, b, c) )
# define c3_s5(a, b, c, d, e) \
( ((uint64_t)c3_s1(e) << 32ULL) | c3_s4(a, b, c, d) )
# define c3_s6(a, b, c, d, e, f) \
( ((uint64_t)c3_s2(e, f) << 32ULL) | c3_s4(a, b, c, d) )
# define c3_s7(a, b, c, d, e, f, g) \
( ((uint64_t)c3_s3(e, f, g) << 32ULL) | c3_s4(a, b, c, d) )
# define c3_s8(a, b, c, d, e, f, g, h) \
( ((uint64_t)c3_s4(e, f, g, h) << 32ULL) | c3_s4(a, b, c, d) )
/* Byte-order twiddling.
*/
# define c3_flip32(w) \
( (((w) >> 24) & 0xff) \
| (((w) >> 16) & 0xff) << 8 \
| (((w) >> 8) & 0xff) << 16 \
| ( (w) & 0xff) << 24 )
/* Asserting allocators.
*/
# define c3_free(s) free(s)
# define c3_malloc(s) ({ \
void* rut = malloc(s); \
if ( 0 == rut ) { \
fprintf(stderr, "c3_malloc(%" PRIu64 ") failed\r\n", \
(c3_d)s); \
u3_assert(!"memory lost"); \
} \
rut;})
# define c3_calloc(s) ({ \
void* rut = calloc(1,s); \
if ( 0 == rut ) { \
fprintf(stderr, "c3_calloc(%" PRIu64 ") failed\r\n", \
(c3_d)s); \
u3_assert(!"memory lost"); \
} \
rut;})
# define c3_realloc(a, b) ({ \
void* rut = realloc(a, b); \
if ( 0 == rut ) { \
fprintf(stderr, "c3_realloc(%" PRIu64 ") failed\r\n", \
(c3_d)b); \
u3_assert(!"memory lost"); \
} \
rut;})
/* Asserting unix fs wrappers.
**
** these all crash the process if passed a non-canonical
** path (i.e., one containing '.', '..', or the empty path
** component), so make sure you don't pass them one. if you
** find yourself fighting with them, then please delete them
** and do a sed search-and-replace to remove the `c3_` from
** their call sites; their goal is to decrease maintenance
** burden, not increase it.
*/
// defined in vere/io/unix.c.
c3_t u3_unix_cane(const c3_c* pax_c);
# define c3_open(a, ...) ({ \
open(a, __VA_ARGS__);})
# define c3_opendir(a) ({ \
opendir(a);})
# define c3_mkdir(a, b) ({ \
mkdir(a, b);})
# define c3_rmdir(a) ({ \
rmdir(a);})
# define c3_link(a, b) ({ \
link(a, b);})
# define c3_unlink(a) ({ \
unlink(a);})
# define c3_fopen(a, b) ({ \
fopen(a, b);})
# define c3_remove(a) ({ \
remove(a);})
# define c3_rename(a, b) ({ \
rename(a, b);})
/* c3_align(
x - the address/quantity to align,
al - the alignment,
hilo - [C3_ALGHI, C3_ALGLO] high or low align
)
hi or lo align x to al
unless effective type of x is c3_w or c3_d, assumes x is a pointer.
*/
#define c3_align(x, al, hilo) \
_Generic((x), \
c3_w : c3_align_w, \
c3_d : c3_align_d, \
default : c3_align_p) \
(x, al, hilo)
typedef enum { C3_ALGHI=1, C3_ALGLO=0 } align_dir;
inline c3_w
c3_align_w(c3_w x, c3_w al, align_dir hilo) {
c3_dessert(hilo <= C3_ALGHI && hilo >= C3_ALGLO);
x += hilo * (al - 1);
x &= ~(al - 1);
return x;
}
inline c3_d
c3_align_d(c3_d x, c3_d al, align_dir hilo) {
c3_dessert(hilo <= C3_ALGHI && hilo >= C3_ALGLO);
x += hilo * (al - 1);
x &= ~(al - 1);
return x;
}
inline void*
c3_align_p(void const * p, size_t al, align_dir hilo) {
uintptr_t x = (uintptr_t)p;
c3_dessert(hilo <= C3_ALGHI && hilo >= C3_ALGLO);
x += hilo * (al - 1);
x &= ~(al - 1);
return (void*)x;
}
#endif /* ifndef C3_DEFS_H */