|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.15 root 7: //
8: // 基本ヘッダ
9: //
10:
1.1 root 11: #pragma once
12:
13: #define NONO_MAJOR_VER (0)
1.1.1.19! root 14: #define NONO_MINOR_VER (7)
1.1.1.15 root 15: #define NONO_PATCH_VER (0)
1.1.1.19! root 16: #define NONO_DATE "2024/02/21"
1.1 root 17:
1.1.1.3 root 18: #include "config-nono.h"
1.1 root 19: #include <cassert>
20: #include <cctype>
21: #include <cerrno>
22: #include <cstdarg>
23: #include <cstdio>
24: #include <cstdint>
25: #include <cstdlib>
26: #include <cstring>
1.1.1.3 root 27: #include <memory>
1.1 root 28: #include <string>
29:
30: #include <err.h>
31: #include <inttypes.h>
32: #include <unistd.h>
33: #include <sys/cdefs.h>
34: #include <sys/types.h>
35:
1.1.1.4 root 36: using uint8 = uint8_t;
37: using uint16 = uint16_t;
38: using uint32 = uint32_t;
39: using uint64 = uint64_t;
40: using int8 = int8_t;
41: using int16 = int16_t;
42: using int32 = int32_t;
43: using int64 = int64_t;
1.1 root 44:
45: #if defined(HAVE_BSD_BSD_H)
46: #include <bsd/bsd.h>
47: #endif
48:
1.1.1.15 root 49: #include "myendian.h"
50:
1.1 root 51: #if !defined(__printflike)
52: #if defined(HAVE___ATTRIBUTE_FORMAT)
53: # define __printflike(a,b) __attribute__((__format__(__printf__, (a), (b))))
54: #else
55: # define __printflike(a,b)
56: #endif
57: #endif
58:
59: #if !defined(__unreachable)
60: #if defined(HAVE___BUILTIN_UNREACHABLE)
61: # define __unreachable() __builtin_unreachable()
62: #else
63: # define __unreachable() ((void)0)
64: #endif
65: #endif
66:
67: // gcc でコンパイラに最適化の条件を与える。
68: #if defined(HAVE___BUILTIN_ASSUME)
69: #define __assume(cond) __builtin_assume(cond)
70: #else
71: #define __assume(cond) if (!(cond)) __unreachable()
72: #endif
73:
74: #if !defined(__packed)
75: #if defined(HAVE___ATTRIBUTE_PACKED)
76: # define __packed __attribute__((__packed__))
77: #else
78: # error not tested.
79: #endif
80: #endif
81:
1.1.1.16 root 82: // FreeBSD(12.1) の __predict_true/false は定義がいまいちで使えない。
83: // __builtin_expect() があることが分かればどの環境でも自前で定義できるので
84: // 既存定義は取り消す。
1.1 root 85: #if defined(HAVE___BUILTIN_EXPECT)
1.1.1.16 root 86: # undef __predict_true
87: # undef __predict_false
1.1 root 88: # define __predict_true(exp) __builtin_expect((exp) != 0, 1)
89: # define __predict_false(exp) __builtin_expect((exp) != 0, 0)
1.1.1.16 root 90: #elif !defined(__predict_true)
1.1 root 91: # define __predict_true(exp) (exp)
92: # define __predict_false(exp) (exp)
93: #endif
94:
95: #if !defined(__unused)
96: #if defined(HAVE___ATTRIBUTE_UNUSED)
97: # define __unused __attribute__((__unused__))
98: #else
99: # define __unused
100: #endif
101: #endif
102:
1.1.1.4 root 103: #if defined(__clang__)
104: # define FALLTHROUGH [[clang::fallthrough]]
105: #elif defined(HAVE___ATTRIBUTE_FALLTHROUGH)
1.1 root 106: # define FALLTHROUGH __attribute__((__fallthrough__))
107: #else
108: # define FALLTHROUGH ((void)0)
109: #endif
110:
111: #if defined(HAVE___ATTRIBUTE_NO_SANITIZE)
112: # define NO_SANITIZE(x) __attribute__((no_sanitize(x)))
113: #else
114: # define NO_SANITIZE(x)
115: #endif
116:
1.1.1.5 root 117: // x86_64 では SSE のために16バイト境界に整列させたいが、ほかの
118: // アーキテクチャでは alignas(16) がエラーになる場合がある。この場合の
119: // alignas() は SSE のために必要なので、他アーキテクチャではそもそも
120: // 指定しなくていい。ということで x86_64 の時に限って指定したい時に使う。
121: // うーん、なんだこれ。
122: #if defined(__x86_64__)
123: #define ALIGNAS_IF_X86(n) alignas(n)
124: #else
125: #define ALIGNAS_IF_X86(n) /**/
126: #endif
127:
1.1.1.3 root 128: // 64ビット数と2つの32ビット数を扱う共用体。
129: // 構造はまったく同じだが名前だけ場所に合わせてつけたい。
1.1.1.15 root 130: #if BYTE_ORDER == LITTLE_ENDIAN
1.1.1.3 root 131: #define DEF_UNION64(NAME, Q, H, L) \
132: union NAME { \
133: uint64 Q; \
134: struct { uint32 L, H; }; \
135: }
136: #else
137: #define DEF_UNION64(NAME, Q, H, L) \
138: union NAME { \
139: uint64 Q; \
140: struct { uint32 H, L; }; \
141: }
142: #endif
143:
144: DEF_UNION64(union64, q, h, l);
145:
1.1 root 146: #ifndef countof
147: #define countof(x) (sizeof(x) / sizeof(x[0]))
148: #endif
149:
1.1.1.5 root 150: #ifndef roundup
151: #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
152: #endif
153:
1.1.1.15 root 154: #ifndef rounddown
155: #define rounddown(x, y) (((x)/(y))*(y))
156: #endif
157:
1.1.1.3 root 158: // メッセージ付きの assert。
1.1.1.5 root 159: // 本当は後ろに足したいのだがそれは無理なので、せめてそれっぽく1行にしてみる。
1.1.1.15 root 160: #if !defined(NDEBUG)
1.1.1.5 root 161: #define assertmsg(expr, ...) do { \
1.1.1.3 root 162: if (__predict_false(!(expr))) { \
1.1.1.5 root 163: fprintf(stderr, __VA_ARGS__); \
164: fprintf(stderr, ": "); \
1.1.1.3 root 165: assert(expr); \
166: } \
167: } while (0)
1.1.1.15 root 168: #else
169: #define assertmsg(expr, ...)
170: #endif
1.1.1.3 root 171:
1.1.1.17 root 172: // iconv() の第2引数の型は OS によって違う…
173: #if defined(HAVE_ICONV_CONST)
174: #define ICONV(cd, s, slen, d, dlen) iconv((cd), (s), (slen), (d), (dlen))
175: #else
176: #define ICONV(cd, s, slen, d, dlen) \
177: iconv((cd), const_cast<char **>(s), (slen), (d), (dlen))
178: #endif
1.1 root 179:
1.1.1.15 root 180: // パニック (PC を表示しない)
1.1.1.17 root 181: #define PANIC(...) panic_func(__PRETTY_FUNCTION__, __VA_ARGS__)
182: [[noreturn]] extern void panic_func(const char *funcname, const char *fmt, ...)
1.1 root 183: __printflike(2, 3);
1.1.1.15 root 184:
185: // VM 用パニック (PC を表示する)
1.1.1.17 root 186: #define VMPANIC(...) vmpanic_func(__PRETTY_FUNCTION__, __VA_ARGS__)
187: [[noreturn]] extern void vmpanic_func(const char *funcname, const char *fmt,
188: ...) __printflike(2, 3);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.