summaryrefslogtreecommitdiff
path: root/src/base.h
blob: 83d086cb6776429165fa46038111316369417f64 (plain)
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
#pragma once

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <sysexits.h>
#include <errno.h>
#include <string.h>
#include <err.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>

typedef uint64_t u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t  u8;
typedef int64_t  s64;
typedef int32_t  s32;
typedef int16_t  s16;
typedef int8_t   s8;
typedef float    f32;
typedef double   f64;
typedef int      fd;
typedef int      jid_t;

#define ArrayCount(x) (sizeof(x) / sizeof(*(x)))

#define PARENS ()

#define EVAL3(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__))))
#define EVAL2(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__))))
#define EVAL1(...) EVAL0(EVAL0(EVAL0(EVAL0(__VA_ARGS__))))
#define EVAL0(...) __VA_ARGS__

#define FOR_EACH(f, ...)         __VA_OPT__(EVAL3(FOR_EACH_STEP(f, __VA_ARGS__)))
#define FOR_EACH_STEP(f, x, ...) f(x) __VA_OPT__(FOR_EACH_AGAIN PARENS(f, __VA_ARGS__))
#define FOR_EACH_AGAIN()         FOR_EACH_STEP

#define FOR_EACH_1(f, s, ...)         __VA_OPT__(EVAL3(FOR_EACH_1_STEP(f, s __VA_ARGS__)))
#define FOR_EACH_1_STEP(f, s, x, ...) f(s, x) __VA_OPT__(FOR_EACH_1_AGAIN PARENS(f, s, __VA_ARGS__))
#define FOR_EACH_1_AGAIN()            FOR_EACH_1_STEP

#define DO_PRAGMA(x)            _Pragma(#x)
#define WARNINGS_RESTORE        DO_PRAGMA(clang diagnostic pop)
#define WARNINGS_IGNORE_STEP(x) DO_PRAGMA(clang diagnostic ignored x)
#define WARNINGS_IGNORE(...)         \
	DO_PRAGMA(clang diagnostic push) \
	FOR_EACH(WARNINGS_IGNORE_STEP, __VA_ARGS__)

#define UNUSED(...) (void)sizeof(__VA_ARGS__ __VA_OPT__(, ) 0) // NOLINT(bugprone-sizeof-expression)

#define OffsetOf(x, y)                    __builtin_offsetof(x, y)
#define ContainerOf(Member, type, member) (type *)(void *)((u8 *)(Member)-OffsetOf(type, member))

WARNINGS_IGNORE("-Wdocumentation")
#include <ucl.h>
WARNINGS_RESTORE

#define UCL_CHECK_HELPER_INT     "an integer"
#define UCL_CHECK_HELPER_STRING  "a string"
#define UCL_CHECK_HELPER_OBJECT  "an object"
#define UCL_CHECK_HELPER_ARRAY   "an array"
#define UCL_CHECK_HELPER_BOOLEAN "a boolean"
#define UCL_CHECK_HELPER_(x)     UCL_CHECK_HELPER_##x
#define UCL_CHECK_HELPER(x)      UCL_CHECK_HELPER_(x)
#define UCL_CHECK_ROOT(type_)                                                 \
	do {                                                                      \
		if(root == NULL || root->type != UCL_##type_)                         \
		{                                                                     \
			if(*Position == '\0') Position = ".";                             \
			asprintf(&Error, "%s is not " UCL_CHECK_HELPER(type_), Position); \
			goto error;                                                       \
		}                                                                     \
	} while(0)
#define UCL_CHECK(x, type_)                                                          \
	do {                                                                             \
		if(x == NULL || x->type != UCL_##type_)                                      \
		{                                                                            \
			asprintf(&Error, "%s." #x " is not " UCL_CHECK_HELPER(type_), Position); \
			goto error;                                                              \
		}                                                                            \
	} while(0)
#define UCL_CHECK_OPTIONAL(x, type_)                                                 \
	do {                                                                             \
		if(x != NULL && x->type != UCL_##type_)                                      \
		{                                                                            \
			asprintf(&Error, "%s." #x " is not " UCL_CHECK_HELPER(type_), Position); \
			goto error;                                                              \
		}                                                                            \
	} while(0)

#define CONCAT_ENUM_NAMES(a, b) a##_##b,
#define STRING_(...)            #__VA_ARGS__
#define STRING(...)             STRING_(__VA_ARGS__)
#define LISTIFY(...)            __VA_ARGS__,
#define STRING_LISTIFY(...)     LISTIFY(STRING(__VA_ARGS__))
#define REQUIRE_SEMICOLON_(x)   struct dummy_struct_##x
#define REQUIRE_SEMICOLON(x)    REQUIRE_SEMICOLON_(x)
#define NAMED_ENUM(x, ...)                                                                    \
	enum                                                                                      \
	{                                                                                         \
		FOR_EACH_1(CONCAT_ENUM_NAMES, x, __VA_OPT__(, ) __VA_ARGS__) x##_COUNT                \
	} typedef x;                                                                              \
	WARNINGS_IGNORE("-Wunused-variable")                                                      \
	static char const *x##_Names[] = { FOR_EACH(STRING_LISTIFY __VA_OPT__(, ) __VA_ARGS__) }; \
	WARNINGS_RESTORE                                                                          \
	REQUIRE_SEMICOLON(x)

static inline bool
isprints(char const *String)
{
	for(char const *At = String; *At; ++At)
		if(isprint(*At) == false) return false;
	return true;
}