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
...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
--- this file gathers information on the environment it's
--- being compiled in, defining types that our code
--- needs. it will be emitted as <k/type.h>.
--- vim: ft=c
#ifndef KItype
#define KItype
typedef unsigned char kc_uint_min;
typedef signed char kc_sint_min;
typedef unsigned long long kc_uint_max;
typedef signed long long kc_sint_max;
[ifdef type_bit8]
typedef unsigned [type_bit8] u8;
typedef signed [type_bit8] s8;
[else]
typedef kc_uint_min u8;
typedef kc_sint_min s8;
[endif]
[ifdef type_bit16]
typedef unsigned [type_bit16] u16;
typedef signed [type_bit16] s16;
[else]
typedef kc_uint_max u16;
typedef kc_sint_max s16;
[endif]
[ifdef type_bit32]
typedef unsigned [type_bit32] u32;
typedef signed [type_bit32] s32;
[else]
typedef kc_uint_max u32;
typedef kc_sint_max s32;
[endif]
[ifdef type_bit64]
typedef unsigned [type_bit64] u64;
typedef signed [type_bit64] s64;
[ifndef type_bit128]
# if defined(__GNUC__) || defined(__clang__)
typedef unsigned __int128_t u128;
typedef signed __int128_t s128;
# else
typedef kc_uint_max u128;
typedef kc_sint_max s128;
# endif
[endif]
[else]
typedef kc_uint_max u64;
typedef kc_sint_max s64;
typedef kc_uint_max u128;
typedef kc_sint_max s128;
[endif]
[ifdef type_bit128]
typedef unsigned [type_bit128] u128;
typedef signed [type_bit128] s128;
[endif]
enum /* max-min values of each type */ {
/* assuming two's complement. TODO: check math */
/* TODO: figure out how to calc min */
kc_byte_bits = [byte_bits],
u8_min = 0, u8_max = ((u8)-1),
u16_min = 0, u16_max = ((u16)-1),
u32_min = 0, u32_max = ((u32)-1),
u64_min = 0, u32_max = ((u64)-1),
u128_min = 0, u128_max = ((u128)-1),
[define merge: $1$2]
[define [sspec type]:
[merge [type],_min] = 0 - ((1 << sizeof([type]) * kc_byte_bits) / 2),
[merge [type],_max] = (1 << sizeof([type]) * kc_byte_bits) / 2 - 1]
[sspec s8], [sspec s16], [sspec s32],
[sspec s64], [sspec s128],
kc_min_uchar = 0, kc_max_uchar = [type_max_u_char],
kc_min_ushort = 0, kc_max_ushort = [type_max_u_short],
kc_min_uint = 0, kc_max_uint = [type_max_u_int],
kc_min_ulong = 0, kc_max_ulong = [type_max_u_long],
kc_min_ullong = 0, kc_max_ullong = [type_max_u_llong],
kc_min_schar = [type_min_s_char], kc_max_schar = [type_max_s_char],
kc_min_sshort = [type_min_s_short], kc_max_sshort = [type_max_s_short],
kc_min_sint = [type_min_s_int], kc_max_sint = [type_max_s_int],
kc_min_slong = [type_min_s_long], kc_max_slong = [type_max_s_long],
kc_min_sllong = [type_min_s_llong], kc_max_sllong = [type_max_s_llong],
};
[ifdef type_sz]
typedef [type_sz] sz;
[else]
# ifdef __cplusplus
/* C++ gives us a clean, standardized way to do this */
................................................................................
# if defined(__GNUC__) || defined(__clang__)
typedef __typeof__ (sizeof(char)) sz;
# else
/* we're stumped - set sz to the safest possible value under
* the circumstances, and warn the user. */
# warning no authoritative sz (size_t) type definition \
available; defaulting to largest unsigned integer type
typedef kc_uint_max sz;
# endif
# endif
[endif]
[ifdef type_offset]
typedef [type_offset] offset;
[else]
................................................................................
# if defined(__GNUC__) || defined(__clang__)
typedef __typeof__ (((void*)10) - ((void*)5)) offset;
# else
/* no dice - set offset to the safest possible value under
* the circumstances, and warn the user. */
# warning no authoritative offset (ptrdiff_t) type definition \
available; defaulting to largest unsigned integer type
typedef kc_sint_max offset;
# endif
# endif
[endif]
// exit status integer types - pls use kbad in <k/magic.h> instead
[if [target_posix] == yes]
/* by convention, posix return values are 8-bit,
|
|
|
|
|
<
>
|
|
|
|
|
<
<
|
>
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
>
|
|
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
<
<
|
>
>
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
|
|
|
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
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
--- this file gathers information on the environment it's
--- being compiled in, defining types that our code
--- needs. it will be emitted as <k/type.h>.
--- vim: ft=c
#ifndef KItype
#define KItype
/* we define 64-bit types first due to an oddity in how
* 128-bit types are handled: we want kc_?big to reference
* the absolute largest type available to the compiler,
* but in some cases, 128-bits may not be among the
* standard C types despite being supported by the
* compiler. to work around this, we first check whether
* 64-bit types are available (__int128_t only works on
* 64-bit systems) and then whether the compiler is one
* that supports the 128-bit extension - but only if a
* native 128-bit type is not available.
*
* once this is done, we can be certain that u128 will
* reference the largest available integer type and can
* safely define kc_?big by reference to it. */
[ifdef type_bit64]
typedef unsigned [type_bit64] u64;
typedef signed [type_bit64] s64;
[ifndef type_bit128]
/* even if no native type is 128 bits long, clang and
* gcc have extensions to support 128 bit arithmetic
* on 64-bit hardware */
# if defined(__GNUC__) || defined(__clang__)
typedef unsigned __int128_t u128;
typedef signed __int128_t s128;
# else
/* if we don't have access to that extension
* or native 128-bit types, then we just use
* the largest native type specified in the
* C standard */
typedef unsigned long long u128;
typedef signed long long s128;
# endif
[endif]
[else]
typedef unsigned long long u64;
typedef signed long long s64;
typedef u64 u128;
typedef s64 s128;
[endif]
[ifdef type_bit128]
typedef unsigned [type_bit128] u128;
typedef signed [type_bit128] s128;
[endif]
typedef unsigned char ubyte;
typedef signed char sbyte;
typedef u128 ubig;
typedef s128 sbig;
[ifdef type_bit8]
typedef unsigned [type_bit8] u8;
typedef signed [type_bit8] s8;
[else]
typedef ubyte u8;
typedef sbyte s8;
[endif]
[ifdef type_bit16]
typedef unsigned [type_bit16] u16;
typedef signed [type_bit16] s16;
[else]
typedef ubig u16;
typedef sbig s16;
[endif]
[ifdef type_bit32]
typedef unsigned [type_bit32] u32;
typedef signed [type_bit32] s32;
[else]
typedef ubig u32;
typedef sbig s32;
[endif]
enum /* max-min values of each type */ {
byte_bits = [byte_bits],
u8_min = 0, u8_max = ((u8)-1),
u16_min = 0, u16_max = ((u16)-1),
u32_min = 0, u32_max = ((u32)-1),
u64_min = 0, u32_max = ((u64)-1),
u128_min = 0, u128_max = ((u128)-1),
/* assuming two's complement. TODO: check math */
[define merge: $1$2]
[define [sspec type]:
[merge [type],_min] = 0 - ((1 << sizeof([type]) * kc_byte_bits) / 2),
[merge [type],_max] = (1 << sizeof([type]) * kc_byte_bits) / 2 - 1]
[sspec s8], [sspec s16], [sspec s32],
[sspec s64], [sspec s128],
kc_uchar_min = 0, kc_uchar_max = [type_max_u_char],
kc_ushort_min = 0, kc_ushort_max = [type_max_u_short],
kc_uint_min = 0, kc_uint_max = [type_max_u_int],
kc_ulong_min = 0, kc_ulong_max = [type_max_u_long],
kc_ullong_min = 0, kc_ullong_max = [type_max_u_llong],
kc_schar_min = [type_min_s_char], kc_schar_max = [type_max_s_char],
kc_sshort_min = [type_min_s_short], kc_sshort_max = [type_max_s_short],
kc_sint_min = [type_min_s_int], kc_sint_max = [type_max_s_int],
kc_slong_min = [type_min_s_long], kc_slong_max = [type_max_s_long],
kc_sllong_min = [type_min_s_llong], kc_sllong_max = [type_max_s_llong],
ubig_min = u128_min, ubig_max = u128_max,
sbig_min = s128_min, sbig_max = s128_max,
ubyte_min = kc_uchar_min, ubyte_max = kc_uchar_max,
sbyte_min = kc_schar_min, sbyte_max = kc_schar_max,
};
[ifdef type_sz]
typedef [type_sz] sz;
[else]
# ifdef __cplusplus
/* C++ gives us a clean, standardized way to do this */
................................................................................
# if defined(__GNUC__) || defined(__clang__)
typedef __typeof__ (sizeof(char)) sz;
# else
/* we're stumped - set sz to the safest possible value under
* the circumstances, and warn the user. */
# warning no authoritative sz (size_t) type definition \
available; defaulting to largest unsigned integer type
typedef ubig sz;
# endif
# endif
[endif]
[ifdef type_offset]
typedef [type_offset] offset;
[else]
................................................................................
# if defined(__GNUC__) || defined(__clang__)
typedef __typeof__ (((void*)10) - ((void*)5)) offset;
# else
/* no dice - set offset to the safest possible value under
* the circumstances, and warn the user. */
# warning no authoritative offset (ptrdiff_t) type definition \
available; defaulting to largest unsigned integer type
typedef sbig offset;
# endif
# endif
[endif]
// exit status integer types - pls use kbad in <k/magic.h> instead
[if [target_posix] == yes]
/* by convention, posix return values are 8-bit,
|