1/* toolchain utility library: memory, paths, containers, option parsing */
2
3#ifndef ARUU_TCUTIL_H
4#define ARUU_TCUTIL_H
5
6#include <stddef.h> /* size_t */
7#include <stdint.h> /* intptr_t */
8#include <stdio.h> /* FILE */
9#include <sys/types.h> /* ssize_t */
10
11/* macros also defined by shared/util.h, undef to avoid redefinition warning */
12#undef MIN
13#undef MAX
14#undef ALIGN
15
16#define MIN(a, b) ((a) < (b) ? (a) : (b))
17#define MAX(a, b) ((a) > (b) ? (a) : (b))
18#define ALIGN(x, align) (((x) + (align) - 1) & -(align)) /* align must be power of 2 */
19#define UNUSED(x) ((void)(x))
20#define IS_POWER_OF_2(x) ((x) > 0 && ((x) & ((x) - 1)) == 0)
21#define INT2VOIDP(i) ((void *)(intptr_t)(i))
22#define UINT2VOIDP(i) ((void *)(uintptr_t)(i))
23#define VOIDP2INT(p) ((intptr_t)(p))
24#define VOIDP2UINT(p) ((uintptr_t)(p))
25#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
26
27struct Name;
28
29/* character classification */
30int isalnum_(int c);
31int isutf8first(int c);
32int isutf8follow(int c);
33int isoctal(int c);
34int xvalue(char c);
35
36/* string and path helpers */
37int starts_with(const char *str, const char *prefix);
38int is_fullpath(const char *filename);
39char *join_paths(const char *paths[]);
40char *get_ext(const char *filename);
41char *change_ext(const char *path, const char *ext);
42const char *skip_whitespaces(const char *s);
43const char *block_comment_start(const char *p);
44const char *block_comment_end(const char *p);
45
46/* file I/O helpers */
47void *read_or_die(FILE *fp, void *buf, long offset, size_t size, const char *msg);
48void put_padding(FILE *fp, long start);
49int is_file(const char *path);
50ssize_t getline_chomp(char **lineptr, size_t *n, FILE *stream);
51ssize_t getline_cont(char **lineptr, size_t *n, FILE *stream, int *plineno);
52
53/* memory: toolchain-local, same contract as aruu emalloc/ecalloc/erealloc
54 * kept separate so the toolchain can build standalone without libutil */
55void *malloc_or_die(size_t size);
56void *calloc_or_die(size_t size);
57void *realloc_or_die(void *ptr, size_t size);
58
59/* diagnostics */
60void show_version(const char *exe, int arch);
61_Noreturn void error(const char *fmt, ...);
62void show_error_line(const char *line, const char *p, int len);
63
64/* value range checks for immediate operands */
65int is_im8(int64_t x);
66int is_im16(int64_t x);
67int is_im32(int64_t x);
68int64_t wrap_value(int64_t value, int size, int is_unsigned);
69int most_significant_bit(size_t x);
70
71/* name interning (see table.h for struct name) */
72const struct Name *alloc_label(void);
73
74/* container: growable pointer vector */
75struct Vector {
76 void **data;
77 int capacity;
78 int len;
79};
80
81struct Vector *new_vector(void);
82void free_vector(struct Vector *vec);
83void vec_init(struct Vector *vec);
84void vec_clear(struct Vector *vec);
85void vec_push(struct Vector *vec, const void *elem);
86void *vec_pop(struct Vector *vec);
87void vec_insert(struct Vector *vec, int pos, const void *elem);
88void vec_remove_at(struct Vector *vec, int index);
89int vec_contains(struct Vector *vec, void *elem);
90void vec_concat(struct Vector *dst, const struct Vector *src);
91
92/* container: growable byte buffer */
93struct DataStorage {
94 struct Vector *chunk_stack;
95 unsigned char *buf;
96 size_t capacity;
97 size_t len;
98};
99
100void data_release(struct DataStorage *data);
101void data_init(struct DataStorage *data);
102void data_reserve(struct DataStorage *data, size_t capacity);
103void data_insert(struct DataStorage *data, ssize_t pos, const void *buf, size_t size);
104void data_append(struct DataStorage *data, const void *buf, size_t size);
105void data_push(struct DataStorage *data, unsigned char c);
106void data_align(struct DataStorage *data, int align);
107void data_concat(struct DataStorage *dst, struct DataStorage *src);
108void data_leb128(struct DataStorage *data, ssize_t pos, int64_t val);
109void data_uleb128(struct DataStorage *data, ssize_t pos, uint64_t val);
110void data_string(struct DataStorage *data, const void *str, size_t len);
111void data_open_chunk(struct DataStorage *data);
112void data_close_chunk(struct DataStorage *data, ssize_t num);
113void data_varint32(struct DataStorage *data, ssize_t pos, int64_t val);
114void data_varuint32(struct DataStorage *data, ssize_t pos, uint64_t val);
115
116/* container: rope-style string builder */
117struct StringBuffer {
118 struct Vector *elems;
119};
120
121void sb_init(struct StringBuffer *sb);
122void sb_clear(struct StringBuffer *sb);
123int sb_empty(struct StringBuffer *sb);
124void sb_insert(struct StringBuffer *sb, int pos, const char *start, const char *end);
125char *sb_join(struct StringBuffer *sb, const char *separator);
126
127static inline void
128sb_append(struct StringBuffer *sb, const char *start, const char *end)
129{
130 sb_insert(sb, sb->elems->len, start, end);
131}
132
133static inline void
134sb_prepend(struct StringBuffer *sb, const char *start, const char *end)
135{
136 sb_insert(sb, 0, start, end);
137}
138
139static inline char *
140sb_to_string(struct StringBuffer *sb)
141{
142 return sb_join(sb, NULL);
143}
144
145void escape_string(const char *str, size_t size, struct StringBuffer *sb);
146
147/* convenience macro for join_paths */
148#define JOIN_PATHS(...) join_paths((const char *[]){__VA_ARGS__, NULL})
149
150/* option parser: long-option style for toolchain commands
151 * has_arg values: 0 = none, 1 = required, 2 = optional */
152#define no_argument 0
153#define required_argument 1
154#define optional_argument 2
155
156struct option {
157 const char *name;
158 int has_arg;
159 int val;
160};
161
162extern int optind;
163extern int opterr;
164extern int optopt;
165extern char *optarg;
166
167int optparse(int argc, char *const argv[], const struct option *opts);
168
169#endif /* ARUU_TCUTIL_H */