about summary refs log tree commit diff stats
path: root/wrapperhelper/src
diff options
context:
space:
mode:
authorrajdakin <rajdakin@gmail.com>2024-09-07 20:53:51 +0200
committerGitHub <noreply@github.com>2024-09-07 20:53:51 +0200
commitf30d75ae5dba339bfc95229894b22fd73e3fdc14 (patch)
tree5cd75da181f43a7aaf29cab121069d9dba85aa2d /wrapperhelper/src
parente087e7782ca9b2ce6c8ec99706a352b1c6ca12bc (diff)
downloadbox64-f30d75ae5dba339bfc95229894b22fd73e3fdc14.tar.gz
box64-f30d75ae5dba339bfc95229894b22fd73e3fdc14.zip
[WRAPPERHELPER] General improvements (#1804)
* [WRAPPERHELPER] Automatic headers detection, various bug fixes, added some cast support

* [WRAPPERHELPER] Keep comments untouched
Diffstat (limited to 'wrapperhelper/src')
-rw-r--r--wrapperhelper/src/cstring.c19
-rw-r--r--wrapperhelper/src/cstring.h4
-rw-r--r--wrapperhelper/src/generator.c192
-rw-r--r--wrapperhelper/src/generator.h18
-rw-r--r--wrapperhelper/src/lang.c82
-rw-r--r--wrapperhelper/src/machine.c44
-rw-r--r--wrapperhelper/src/main.c24
-rw-r--r--wrapperhelper/src/parse.c66
-rw-r--r--wrapperhelper/src/prepare.c82
-rw-r--r--wrapperhelper/src/prepare.h4
-rw-r--r--wrapperhelper/src/preproc.c40
-rw-r--r--wrapperhelper/src/vector.c1
-rw-r--r--wrapperhelper/src/vector.h2
13 files changed, 440 insertions, 138 deletions
diff --git a/wrapperhelper/src/cstring.c b/wrapperhelper/src/cstring.c
index aecfb52e..86536915 100644
--- a/wrapperhelper/src/cstring.c
+++ b/wrapperhelper/src/cstring.c
@@ -71,6 +71,15 @@ int string_reserve_grow(string_t *s, size_t cap) {
 	return 1;
 }
 
+int string_trim(string_t *s) {
+	if (s->ssize == s->scap) return 1;
+	void *new_buf = realloc(s->buf, sizeof(char) * (s->ssize + 1));
+	if (!new_buf) return 0;
+	s->buf = new_buf;
+	s->scap = s->ssize;
+	return 1;
+}
+
 void string_del(string_t *s) {
 	if (s->buf) free(s->buf);
 	free(s);
@@ -118,6 +127,16 @@ void string_pop(string_t *s) {
 	}
 }
 
+void string_clear(string_t *s) {
+	if (!s->ssize) return;
+	if (!s->scap) return;
+	s->buf[s->ssize = 0] = '\0';
+	void *new_buf = realloc(s->buf, sizeof(char));
+	if (!new_buf) return; // We don't really care if the realloc fails, we just need to not update anything
+	s->buf = new_buf;
+	s->scap = 0;
+}
+
 string_t *string_dup(string_t const *s) {
 	string_t *ret = string_new_cap(s->ssize);
 	if (!ret) return NULL;
diff --git a/wrapperhelper/src/cstring.h b/wrapperhelper/src/cstring.h
index 12c7df4c..15ecd026 100644
--- a/wrapperhelper/src/cstring.h
+++ b/wrapperhelper/src/cstring.h
@@ -15,12 +15,14 @@
  * string_new_cap ------ Creates a new string with a given capacity. Takes the capacity.
  * string_new_cstr ----- Creates a new string from a given C string. Takes the string.
  * string_reserve ------ Ensures a string has at least a given capacity. Takes the string and the capacity.
+ * string_trim --------- Ensures a string has a capacity equal to its length. Takes the string. May reduce the string capacity.
  * string_del ---------- Frees a string. Takes the string.
  * string_steal -------- Frees a string, keeping the content alive. Takes the string. The content (also returned) needs to be freed separately.
  * string_add_char ----- Add a character at the end. Takes the string and the new character. May increase the string capacity.
  * string_add_string --- Add a string at the end in-place. Takes both strings. May increase the string capacity.
  * string_add_cstr ----- Add a C string at the end in-place. Takes both strings. May increase the string capacity.
  * string_pop ---------- Pops the last character. Takes the string. May reduce the string capacity.
+ * string_clear -------- Clears the string. Takes the string. May reduce the string capacity.
  * string_dup ---------- Duplicate a string. Takes the string. Does not free the old string.
  * string_concat ------- Concatenate two strings. Takes both strings. Does not free any string.
  * string_len ---------- String length. Takes the string.
@@ -62,12 +64,14 @@ string_t *string_new(void);
 string_t *string_new_cap(size_t cap);
 string_t *string_new_cstr(const char *s);
 int       string_reserve(string_t *s, size_t cap);
+int       string_trim(string_t *s);
 void      string_del(string_t *s);
 char     *string_steal(string_t *s);
 int       string_add_char(string_t *s, char elem);
 int       string_add_string(string_t *s1, string_t *s2);
 int       string_add_cstr(string_t *s1, const char *s2);
 void      string_pop(string_t *s);
+void      string_clear(string_t *s);
 string_t *string_dup(string_t const *s);
 string_t *string_concat(string_t const *l, string_t const *r);
 #define string_len(s) ((s)->ssize)
diff --git a/wrapperhelper/src/generator.c b/wrapperhelper/src/generator.c
index 3df744cb..98e254ed 100644
--- a/wrapperhelper/src/generator.c
+++ b/wrapperhelper/src/generator.c
@@ -136,7 +136,7 @@ void request_print_check(request_t *req) {
 		}
 	}
 }
-void request_del(request_t *req) {
+static void request_del(request_t *req) {
 	string_del(req->obj_name);
 	if (req->has_default) {
 		switch (req->def.rty) {
@@ -163,6 +163,16 @@ void request_del(request_t *req) {
 		}
 	}
 }
+static void reference_del(reference_t *ref) {
+	switch (ref->typ) {
+	case REF_REQ:
+		request_del(&ref->req);
+		break;
+	case REF_LINE:
+		string_del(ref->line);
+		break;
+	}
+}
 
 static int valid_reqtype(string_t *t) {
 	const char *s = string_content(t);
@@ -244,23 +254,34 @@ static void request_output(FILE *f, request_t *req) {
 		}
 	}
 }
-void output_from_requests(FILE *f, VECTOR(requests) *reqs) {
+static void reference_output(FILE *f, reference_t *ref) {
+	switch (ref->typ) {
+	case REF_REQ:
+		request_output(f, &ref->req);
+		break;
+	case REF_LINE:
+		fputs(string_content(ref->line), f);
+		fputc('\n', f);
+		break;
+	}
+}
+void output_from_references(FILE *f, VECTOR(references) *reqs) {
 	fprintf(f, "#if !(defined(GO) && defined(GOM) && defined(GO2) && defined(DATA))\n#error Meh...\n#endif\n\n");
-	vector_for(requests, req, reqs) {
-		request_output(f, req);
+	vector_for(references, req, reqs) {
+		reference_output(f, req);
 	}
 }
 
-VECTOR_IMPL(requests, request_del)
+VECTOR_IMPL(references, reference_del)
 
-VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
+VECTOR(references) *references_from_file(const char *filename, FILE *f) {
 	prepare_t *prep = prepare_new_file(f, filename);
 	if (!prep) {
-		printf("Failed to create the prepare structure for the requests file\n");
+		printf("Failed to create the prepare structure for the reference file\n");
 		return NULL;
 	}
 	
-	VECTOR(requests) *ret = vector_new(requests);
+	VECTOR(references) *ret = vector_new(references);
 	if (!ret) {
 		prepare_del(prep);
 		return NULL;
@@ -273,40 +294,80 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 	do {
 		tok = pre_next_token(prep, 0);
 		if (tok.tokt == PPTOK_NEWLINE) ++lineno;
+		else preproc_token_del(&tok); // NEWLINE has no destructor
 	} while (!preproc_token_isend(&tok) && (lineno < 4));
 	
 	// TODO: better conditionals handling
 	// Also, for now assume we have no definition
 	int if_depth = 0, entered_depth = 0;
+	string_t *line = string_new();
+	if (!line) {
+		printf("Error: failed to allocate new string for new reference line\n");
+	}
+	
+#define ADD_CHAR(c, has_destr, what) \
+		if (!string_add_char(line, c)) {               \
+			printf("Error: failed to add " what "\n"); \
+			if (has_destr) preproc_token_del(&tok);    \
+			goto failed;                               \
+		}
+#define ADD_CSTR(cstr, has_destr, what) \
+		if (!string_add_cstr(line, cstr)) {            \
+			printf("Error: failed to add " what "\n"); \
+			if (has_destr) preproc_token_del(&tok);    \
+			goto failed;                               \
+		}
+#define ADD_STR(str, has_destr, what) \
+		if (!string_add_string(line, str)) {              \
+			printf("Error: failed to add " what "\n"); \
+			if (has_destr) preproc_token_del(&tok);    \
+			goto failed;                               \
+		}
+#define PUSH_LINE(has_destr) \
+		string_trim(line);                                                                   \
+		if (!vector_push(references, ret, ((reference_t){.typ = REF_LINE, .line = line}))) { \
+			printf("Error: failed to memorize reference line %d\n", lineno);                 \
+			if (has_destr) preproc_token_del(&tok);                                          \
+			goto failed;                                                                     \
+		}                                                                                    \
+		line = string_new();                                                                 \
+		if (!line) {                                                                         \
+			printf("Error: failed to allocate new string for new reference line\n");         \
+		}
+	
 	while (1) {
 		int is_comment = 0;
 		tok = pre_next_token(prep, 1);
-		while (tok.tokt == PPTOK_START_LINE_COMMENT) {
+		if (tok.tokt == PPTOK_START_LINE_COMMENT) {
+			ADD_CSTR("//", 0, "start of comment")
 			is_comment = 1;
 			// Empty destructor
-			tok = pre_next_token(prep, 1);
+			tok = pre_next_token(prep, 0); // tok is IDENT, NEWLINE, INVALID or BLANK
+			while ((tok.tokt == PPTOK_BLANK) && ((tok.tokv.c == ' ') || (tok.tokv.c == '\t'))) {
+				ADD_CHAR(tok.tokv.c, 0, "start of comment")
+				// Empty destructor
+				tok = pre_next_token(prep, 0); // tok is IDENT, NEWLINE, INVALID or BLANK
+			}
 		}
 		if ((tok.tokt == PPTOK_SYM) && (tok.tokv.sym == SYM_HASH)) {
-			if (is_comment) {
-				preproc_token_del(&tok);
-				tok = pre_next_newline_token(prep); // Returns a newline
-				++lineno;
-				continue;
-			}
+			ADD_CHAR('#', 0, "start of preprocessor command")
 			tok = pre_next_token(prep, 0);
 			if (tok.tokt != PPTOK_IDENT) {
-				printf("Error: invalid requests file: invalid preprocessor line\n");
+				printf("Error: invalid reference file: invalid preprocessor line\n");
 				preproc_token_del(&tok);
 				goto failed;
 			}
+			ADD_STR(tok.tokv.str, 1, "preprocessor command")
 			if (!strcmp(string_content(tok.tokv.str), "ifdef")) {
 				string_del(tok.tokv.str);
 				tok = pre_next_token(prep, 0);
 				if (tok.tokt != PPTOK_IDENT) {
-					printf("Error: invalid requests file: invalid '#ifdef' line\n");
+					printf("Error: invalid reference file: invalid '#ifdef' line\n");
 					preproc_token_del(&tok);
 					goto failed;
 				}
+				ADD_CHAR(' ', 1, "preprocessor command")
+				ADD_STR(tok.tokv.str, 1, "preprocessor command")
 				++if_depth;
 				string_del(tok.tokv.str);
 				tok = pre_next_token(prep, 0);
@@ -314,10 +375,12 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				string_del(tok.tokv.str);
 				tok = pre_next_token(prep, 0);
 				if (tok.tokt != PPTOK_IDENT) {
-					printf("Error: invalid requests file: invalid '#ifndef' line\n");
+					printf("Error: invalid reference file: invalid '#ifndef' line\n");
 					preproc_token_del(&tok);
 					goto failed;
 				}
+				ADD_CHAR(' ', 1, "preprocessor command")
+				ADD_STR(tok.tokv.str, 1, "preprocessor command")
 				if (if_depth == entered_depth) ++entered_depth;
 				++if_depth;
 				string_del(tok.tokv.str);
@@ -333,7 +396,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				if (if_depth == entered_depth) --entered_depth;
 				--if_depth;
 			} else {
-				printf("Error: invalid requests file: invalid preprocessor command '%s'\n", string_content(tok.tokv.str));
+				printf("Error: invalid reference file: invalid preprocessor command '%s'\n", string_content(tok.tokv.str));
 				string_del(tok.tokv.str);
 				goto failed;
 			}
@@ -341,6 +404,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				preproc_token_del(&tok);
 				tok = pre_next_token(prep, 0);
 			}
+			PUSH_LINE(0)
 			++lineno;
 			if (preproc_token_isend(&tok)) {
 				if (tok.tokt == PPTOK_EOF) goto success;
@@ -350,6 +414,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				}
 			}
 		} else if (tok.tokt == PPTOK_NEWLINE) {
+			PUSH_LINE(0)
 			++lineno;
 		} else if (tok.tokt == PPTOK_EOF) {
 			goto success;
@@ -362,6 +427,8 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 		         || !strcmp(string_content(tok.tokv.str), "GOW2")
 		         || !strcmp(string_content(tok.tokv.str), "GOWD")
 		         || !strcmp(string_content(tok.tokv.str), "GOWM"))) {
+			string_clear(line);
+			if (is_comment) prepare_mark_nocomment(prep);
 			int isweak = (string_content(tok.tokv.str)[2] == 'W');
 			request_t req = {
 				.has_default = 0,
@@ -381,14 +448,14 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 			string_del(tok.tokv.str);
 			tok = pre_next_token(prep, 0);
 			if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_LPAREN)) {
-				printf("Error: invalid requests file: invalid GO line %d (lparen)\n", lineno);
+				printf("Error: invalid reference file: invalid GO line %d (lparen)\n", lineno);
 				preproc_token_del(&tok);
 				goto failed;
 			}
 			// Empty destructor
 			tok = pre_next_token(prep, 0);
 			if (tok.tokt != PPTOK_IDENT) {
-				printf("Error: invalid requests file: invalid GO line %d (obj_name)\n", lineno);
+				printf("Error: invalid reference file: invalid GO line %d (obj_name)\n", lineno);
 				preproc_token_del(&tok);
 				goto failed;
 			}
@@ -396,7 +463,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 			// Token moved
 			tok = pre_next_token(prep, 0);
 			if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_COMMA)) {
-				printf("Error: invalid requests file: invalid GO line %d (comma)\n", lineno);
+				printf("Error: invalid reference file: invalid GO line %d (comma)\n", lineno);
 				string_del(req.obj_name);
 				preproc_token_del(&tok);
 				goto failed;
@@ -410,7 +477,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				tok = pre_next_token(prep, 0);
 				if ((req.def.rty == RQT_FUN_2) || (req.def.rty == RQT_FUN_D)) {
 					if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_COMMA)) {
-						printf("Error: invalid requests file: invalid GO line %d (comma 2)\n", lineno);
+						printf("Error: invalid reference file: invalid GO line %d (comma 2)\n", lineno);
 						string_del(req.obj_name);
 						string_del(req.def.fun.typ);
 						preproc_token_del(&tok);
@@ -419,7 +486,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 					// Empty destructor
 					tok = pre_next_token(prep, 0);
 					if (tok.tokt != PPTOK_IDENT) {
-						printf("Error: invalid requests file: invalid GO line %d (redirect)\n", lineno);
+						printf("Error: invalid reference file: invalid GO line %d (redirect)\n", lineno);
 						string_del(req.obj_name);
 						string_del(req.def.fun.typ);
 						preproc_token_del(&tok);
@@ -430,7 +497,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 					tok = pre_next_token(prep, 0);
 				}
 				if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_RPAREN)) {
-					printf("Error: invalid requests file: invalid GO line %d (rparen)\n", lineno);
+					printf("Error: invalid reference file: invalid GO line %d (rparen)\n", lineno);
 					string_del(req.obj_name);
 					string_del(req.def.fun.typ);
 					if (req.def.fun.fun2) string_del(req.def.fun.fun2);
@@ -441,7 +508,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				tok = pre_next_token(prep, 0);
 			}
 			if (tok.tokt != PPTOK_NEWLINE) {
-				printf("Error: invalid requests file: invalid GO line %d (newline)\n", lineno);
+				printf("Error: invalid reference file: invalid GO line %d (newline)\n", lineno);
 				string_del(req.obj_name);
 				if (req.def.fun.typ) string_del(req.def.fun.typ);
 				if (req.def.fun.fun2) string_del(req.def.fun.fun2);
@@ -449,14 +516,16 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				goto failed;
 			}
 			if (if_depth == entered_depth) {
-				if (!vector_push(requests, ret, req)) {
-					printf("Error: failed to add request for %s\n", string_content(req.obj_name));
+				if (!vector_push(references, ret, ((reference_t){.typ = REF_REQ, .req = req}))) {
+					printf("Error: failed to add reference for %s\n", string_content(req.obj_name));
 					string_del(req.obj_name);
 					if (req.def.fun.typ) string_del(req.def.fun.typ);
 					if (req.def.fun.fun2) string_del(req.def.fun.fun2);
 					// Empty destructor
 					goto failed;
 				}
+			} else {
+				request_del(&req);
 			}
 			++lineno;
 		} else if ((tok.tokt == PPTOK_IDENT)
@@ -464,6 +533,8 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 		         || !strcmp(string_content(tok.tokv.str), "DATAV")
 		         || !strcmp(string_content(tok.tokv.str), "DATAB")
 		         || !strcmp(string_content(tok.tokv.str), "DATAM"))) {
+			string_clear(line);
+			if (is_comment) prepare_mark_nocomment(prep);
 			request_t req = {
 				.has_default = 1,
 				.default_comment = is_comment,
@@ -482,14 +553,14 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 			string_del(tok.tokv.str);
 			tok = pre_next_token(prep, 0);
 			if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_LPAREN)) {
-				printf("Error: invalid requests file: invalid DATA line %d (lparen)\n", lineno);
+				printf("Error: invalid reference file: invalid DATA line %d (lparen)\n", lineno);
 				preproc_token_del(&tok);
 				goto failed;
 			}
 			// Empty destructor
 			tok = pre_next_token(prep, 0);
 			if (tok.tokt != PPTOK_IDENT) {
-				printf("Error: invalid requests file: invalid DATA line %d (obj_name)\n", lineno);
+				printf("Error: invalid reference file: invalid DATA line %d (obj_name)\n", lineno);
 				preproc_token_del(&tok);
 				goto failed;
 			}
@@ -497,7 +568,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 			// Token moved
 			tok = pre_next_token(prep, 0);
 			if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_COMMA)) {
-				printf("Error: invalid requests file: invalid DATA line %d (comma)\n", lineno);
+				printf("Error: invalid reference file: invalid DATA line %d (comma)\n", lineno);
 				string_del(req.obj_name);
 				preproc_token_del(&tok);
 				goto failed;
@@ -507,7 +578,7 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 			if (tok.tokt == PPTOK_NUM) {
 				num_constant_t cst;
 				if (!num_constant_convert(tok.tokv.str, &cst)) {
-					printf("Error: invalid requests file: invalid DATA line %d (num conversion)\n", lineno);
+					printf("Error: invalid reference file: invalid DATA line %d (num conversion)\n", lineno);
 					string_del(req.obj_name);
 					preproc_token_del(&tok);
 					goto failed;
@@ -516,9 +587,9 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				case NCT_FLOAT:
 				case NCT_DOUBLE:
 				case NCT_LDOUBLE:
-					printf("Error: invalid requests file: invalid DATA line %d (num conversion)\n", lineno);
+					printf("Error: invalid reference file: invalid DATA line %d (num conversion)\n", lineno);
 					string_del(req.obj_name);
-					preproc_token_del(&tok);
+					string_del(tok.tokv.str);
 					goto failed;
 				case NCT_INT32:  req.def.dat.sz = (size_t)cst.val.i32; break;
 				case NCT_UINT32: req.def.dat.sz = (size_t)cst.val.u32; break;
@@ -526,10 +597,10 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				case NCT_UINT64: req.def.dat.sz = (size_t)cst.val.u64; break;
 				}
 				req.def.dat.has_size = 1;
-				// Token moved
+				string_del(tok.tokv.str); // Delete token
 				tok = pre_next_token(prep, 0);
 				if ((tok.tokt != PPTOK_SYM) || (tok.tokv.sym != SYM_RPAREN)) {
-					printf("Error: invalid requests file: invalid DATA line %d (rparen)\n", lineno);
+					printf("Error: invalid reference file: invalid DATA line %d (rparen)\n", lineno);
 					string_del(req.obj_name);
 					preproc_token_del(&tok);
 					goto failed;
@@ -538,28 +609,41 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 				tok = pre_next_token(prep, 0);
 			}
 			if (tok.tokt != PPTOK_NEWLINE) {
-				printf("Error: invalid requests file: invalid DATA line %d (newline)\n", lineno);
+				printf("Error: invalid reference file: invalid DATA line %d (newline)\n", lineno);
 				string_del(req.obj_name);
 				preproc_token_del(&tok);
 				goto failed;
 			}
 			if (if_depth == entered_depth) {
-				if (!vector_push(requests, ret, req)) {
-					printf("Error: failed to add request for %s\n", string_content(req.obj_name));
-					string_del(req.obj_name);
+				if (!vector_push(references, ret, ((reference_t){.typ = REF_REQ, .req = req}))) {
+					printf("Error: failed to add reference for %s\n", string_content(req.obj_name));
+					request_del(&req);
 					// Empty destructor
 					goto failed;
 				}
+			} else {
+				request_del(&req);
 			}
 			++lineno;
-		} else {
-			if (is_comment) {
+		} else if (is_comment) {
+			if (tok.tokt == PPTOK_IDENT) {
+				ADD_STR(tok.tokv.str, 1, "comment content")
+				string_del(tok.tokv.str);
+			} else if (tok.tokt == PPTOK_BLANK) {
+				ADD_CHAR(tok.tokv.c, 0, "comment content")
+			} else {
+				printf("Error: unknown token type in comment %u\n", tok.tokt);
 				preproc_token_del(&tok);
-				tok = pre_next_newline_token(prep); // Returns a newline
-				++lineno;
-				continue;
+				goto failed;
 			}
-			printf("Error: invalid requests file: invalid token:\n");
+			if (!pre_next_newline_token(prep, line)) {
+				printf("Error: failed to add comment content\n");
+				goto failed;
+			}
+			PUSH_LINE(0)
+			++lineno;
+		} else {
+			printf("Error: invalid reference file: invalid token:\n");
 			preproc_token_print(&tok);
 			preproc_token_del(&tok);
 			goto failed;
@@ -567,11 +651,13 @@ VECTOR(requests) *requests_from_file(const char *filename, FILE *f) {
 	}
 	
 failed:
+	string_del(line);
 	prepare_del(prep);
-	vector_del(requests, ret);
+	vector_del(references, ret);
 	return NULL;
 	
 success:
+	string_del(line);
 	prepare_del(prep);
 	return ret;
 }
@@ -692,7 +778,7 @@ static int convert_type(string_t *dest, type_t *typ, int is_ret, int *needs_D, i
 		case BTT_LONGDOUBLE: *needs_D = 1; has_char = 1; c = 'D'; break;
 		case BTT_CLONGDOUBLE: *needs_D = 1; has_char = 1; c = 'Y'; break;
 		case BTT_ILONGDOUBLE: *needs_D = 1; has_char = 1; c = 'D'; break;
-		case BTT_VA_LIST: has_char = 1; c = 'A'; break;
+		case BTT_VA_LIST: *needs_my = 1; has_char = 1; c = 'A'; break;
 		default:
 			printf("Error: convert_type on unknown builtin %u\n", typ->val.builtin);
 			return 0;
@@ -847,6 +933,7 @@ int solve_request(request_t *req, type_t *typ) {
 				if (!convert_type(req->val.fun.typ, typ->val.fun.args[i], 0, &needs_D, &needs_my, req->obj_name)) goto fun_fail;
 			}
 			if (typ->val.fun.has_varargs) {
+				needs_my = 1;
 				if (!string_add_char(req->val.fun.typ, 'V')) {
 					printf("Error: failed to add type char for %s\n", builtin2str[typ->val.builtin]);
 					goto fun_fail;
@@ -913,10 +1000,11 @@ int solve_request_map(request_t *req, khash_t(type_map) *decl_map) {
 	}
 	return solve_request(req, kh_val(decl_map, it));
 }
-int solve_requests(VECTOR(requests) *reqs, khash_t(type_map) *decl_map) {
+int solve_references(VECTOR(references) *refs, khash_t(type_map) *decl_map) {
 	int ret = 1;
-	vector_for(requests, req, reqs) {
-		if (!solve_request_map(req, decl_map)) ret = 0;
+	vector_for(references, ref, refs) {
+		if (ref->typ != REF_REQ) continue;
+		if (!solve_request_map(&ref->req, decl_map)) ret = 0;
 	}
 	return ret;
 }
diff --git a/wrapperhelper/src/generator.h b/wrapperhelper/src/generator.h
index ef27ad0a..fd41862d 100644
--- a/wrapperhelper/src/generator.h
+++ b/wrapperhelper/src/generator.h
@@ -37,14 +37,24 @@ typedef struct request_s {
 		};
 	} def, val;
 } request_t;
-VECTOR_DECLARE(requests, request_t)
+typedef struct reference_s {
+	enum {
+		REF_REQ,
+		REF_LINE,
+	} typ;
+	union {
+		request_t req;
+		string_t *line;
+	};
+} reference_t;
+VECTOR_DECLARE(references, reference_t)
 void request_print(request_t *req);
 void request_print_check(request_t *req);
-void output_from_requests(FILE *f, VECTOR(requests) *reqs);
+void output_from_references(FILE *f, VECTOR(references) *reqs);
 
-VECTOR(requests) *requests_from_file(const char *filename, FILE *f); // Takes ownership of f
+VECTOR(references) *references_from_file(const char *filename, FILE *f); // Takes ownership of f
 int solve_request(request_t *req, type_t *typ);
 int solve_request_map(request_t *req, khash_t(type_map) *decl_map);
-int solve_requests(VECTOR(requests) *reqs, khash_t(type_map) *decl_map);
+int solve_references(VECTOR(references) *reqs, khash_t(type_map) *decl_map);
 
 #endif // GENERATOR_H
diff --git a/wrapperhelper/src/lang.c b/wrapperhelper/src/lang.c
index 1c4cba6c..3e9f2a78 100644
--- a/wrapperhelper/src/lang.c
+++ b/wrapperhelper/src/lang.c
@@ -349,9 +349,9 @@ int init_str2kw(void) {
 		printf("Failed to create the string to keyword map (init)\n");
 		return 0;
 	}
+	int iret; khiter_t it;
 	for (enum token_keyword_type_e kw = 0; kw <= LAST_KEYWORD; ++kw) {
-		int iret;
-		khiter_t it = kh_put(str2kw, str2kw, kw2str[kw], &iret);
+		it = kh_put(str2kw, str2kw, kw2str[kw], &iret);
 		if (iret < 0) {
 			printf("Failed to create the string to keyword map (keyword %u)\n", kw);
 			kh_destroy(str2kw, str2kw);
@@ -359,6 +359,35 @@ int init_str2kw(void) {
 		}
 		kh_val(str2kw, it) = kw;
 	}
+#define ADD_ALIAS(alias, k) \
+	it = kh_put(str2kw, str2kw, #alias, &iret);                                            \
+	if (iret < 0) {                                                                        \
+		printf("Failed to create the string to keyword map (keyword alias " #alias ")\n"); \
+		kh_destroy(str2kw, str2kw);                                                        \
+		return 0;                                                                          \
+	}                                                                                      \
+	kh_val(str2kw, it) = KW_ ## k;
+	ADD_ALIAS(__alignof__,   ALIGNOF)
+	// ADD_ALIAS(__asm,         asm)
+	// ADD_ALIAS(__asm__,       asm)
+	ADD_ALIAS(__complex,     COMPLEX)
+	ADD_ALIAS(__complex__,   COMPLEX)
+	ADD_ALIAS(__const,       CONST)
+	ADD_ALIAS(__const__,     CONST)
+	// ADD_ALIAS(__decltype,    decltype)
+	// ADD_ALIAS(__imag__,      __imag)
+	ADD_ALIAS(__inline,      INLINE)
+	ADD_ALIAS(__inline__,    INLINE)
+	// ADD_ALIAS(__nullptr,     nullptr)
+	// ADD_ALIAS(__real__,      __real)
+	ADD_ALIAS(__restrict,    RESTRICT)
+	ADD_ALIAS(__restrict__,  RESTRICT)
+	ADD_ALIAS(__signed,      SIGNED)
+	ADD_ALIAS(__signed__,    SIGNED)
+	// ADD_ALIAS(__typeof,      typeof)
+	// ADD_ALIAS(__typeof__,    typeof)
+	ADD_ALIAS(__volatile,    VOLATILE)
+	ADD_ALIAS(__volatile__,  VOLATILE)
 	return 1;
 }
 void del_str2kw(void) {
@@ -1109,7 +1138,7 @@ file_t *file_new(void) {
 	}
 	
 	// Now fill in the builtin types
-	int iret;
+	int iret; khiter_t it;
 	for (enum type_builtin_e i = 0; i < LAST_BUILTIN + 1; ++i) {
 		type_t *t = malloc(sizeof *t);
 		if (!t) {
@@ -1162,26 +1191,33 @@ file_t *file_new(void) {
 	}
 	// ret is valid
 	
-	// Add __builtin_va_list as a typedef
-	char *sdup = strdup("__builtin_va_list");
-	if (!sdup) {
-		printf("Failed to create a new translation unit structure (va_list name)\n");
-		file_del(ret);
-		return NULL;
-	}
-	khiter_t it = kh_put(type_map, ret->type_map, sdup, &iret);
-	if (iret < 0) {
-		printf("Failed to create a new translation unit structure (add va_list typedef)\n");
-		free(sdup);
-		file_del(ret);
-		return NULL;
-	} else if (iret == 0) {
-		printf("Failed to create a new translation unit structure (__builtin_va_list is already a typedef)\n");
-		file_del(ret);
-		return NULL;
-	}
-	kh_val(ret->type_map, it) = ret->builtins[BTT_VA_LIST];
-	++ret->builtins[BTT_VA_LIST]->nrefs;
+	// Add __builtin_va_list, __int128_t, __uint128_t as typedef
+	char *sdup;
+#define ADD_TYPEDEF(name, btt) \
+	sdup = strdup(#name);                                                                               \
+	if (!sdup) {                                                                                        \
+		printf("Failed to create a new translation unit structure (" #name " name)\n");                 \
+		file_del(ret);                                                                                  \
+		return NULL;                                                                                    \
+	}                                                                                                   \
+	it = kh_put(type_map, ret->type_map, sdup, &iret);                                                  \
+	if (iret < 0) {                                                                                     \
+		printf("Failed to create a new translation unit structure (add " #name " typedef)\n");          \
+		free(sdup);                                                                                     \
+		file_del(ret);                                                                                  \
+		return NULL;                                                                                    \
+	} else if (iret == 0) {                                                                             \
+		printf("Failed to create a new translation unit structure (" #name " is already a typedef)\n"); \
+		free(sdup);                                                                                     \
+		file_del(ret);                                                                                  \
+		return NULL;                                                                                    \
+	}                                                                                                   \
+	kh_val(ret->type_map, it) = ret->builtins[BTT_ ## btt];                                             \
+	++ret->builtins[BTT_ ## btt]->nrefs;
+	
+	ADD_TYPEDEF(__builtin_va_list, VA_LIST)
+	ADD_TYPEDEF(__int128_t, INT128)
+	ADD_TYPEDEF(__uint128_t, UINT128)
 	
 	return ret;
 }
diff --git a/wrapperhelper/src/machine.c b/wrapperhelper/src/machine.c
index bd209bb6..7637a5d3 100644
--- a/wrapperhelper/src/machine.c
+++ b/wrapperhelper/src/machine.c
@@ -11,18 +11,23 @@ machine_t machine_x86_64;
 #define STRINGIFY2(a) #a
 #define STRINGIFY(a) STRINGIFY2(a)
 #define MACHINE_STR STRINGIFY(CUR_MACHINE)
-#define EXTRA_PATHS \
-	PASTE(machine_, CUR_MACHINE).npaths = PASTE(CUR_MACHINE, _NPATHS) + npaths;                                  \
-	if (!(PASTE(machine_, CUR_MACHINE).include_path =                                                            \
-	      malloc((PASTE(CUR_MACHINE, _NPATHS) + npaths) * sizeof *PASTE(machine_, CUR_MACHINE).include_path))) { \
-		printf("Failed to add include path to " MACHINE_STR " platform\n");                                      \
-		goto PASTE(failed_, PASTE(CUR_MACHINE, _nopath));                                                        \
-	}                                                                                                            \
-	for (failure_id = 0; failure_id < npaths; ++failure_id) {                                                    \
-		if (!(PASTE(machine_, CUR_MACHINE).include_path[failure_id] = strdup(extra_include_path[failure_id]))) { \
-			printf("Failed to add include path to " MACHINE_STR " platform\n");                                  \
-			goto PASTE(failed_, PASTE(CUR_MACHINE, _paths));                                                     \
-		}                                                                                                        \
+#define INIT_PATHS \
+	PASTE(machine_, CUR_MACHINE).npaths = 1 + npaths;
+#define INCR_NPATHS(_path) \
+	++PASTE(machine_, CUR_MACHINE).npaths;
+#define DO_PATHS \
+	if (!(PASTE(machine_, CUR_MACHINE).include_path =                                                                \
+	      malloc(PASTE(machine_, CUR_MACHINE).npaths * sizeof *PASTE(machine_, CUR_MACHINE).include_path))) {        \
+		printf("Failed to add include path to " MACHINE_STR " platform\n");                                          \
+		goto PASTE(failed_, PASTE(CUR_MACHINE, _nopath));                                                            \
+	}                                                                                                                \
+	failure_id = 0;                                                                                                  \
+	ADD_PATH("include-fixed")                                                                                        \
+	for (; failure_id < npaths + 1; ++failure_id) {                                                                  \
+		if (!(PASTE(machine_, CUR_MACHINE).include_path[failure_id] = strdup(extra_include_path[failure_id - 1]))) { \
+			printf("Failed to add include path to " MACHINE_STR " platform\n");                                      \
+			goto PASTE(failed_, PASTE(CUR_MACHINE, _paths));                                                         \
+		}                                                                                                            \
 	}
 #define ADD_PATH(path) \
 	if (!(PASTE(machine_, CUR_MACHINE).include_path[failure_id] = strdup(path))) { \
@@ -97,13 +102,14 @@ int init_machines(size_t npaths, const char *const *extra_include_path) {
 #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
 #define CUR_MACHINE x86_64
 	machine_x86_64.size_long = 8;
-#define x86_64_NPATHS 5
-	EXTRA_PATHS
-	ADD_PATH("include-fixed")
-	ADD_PATH("/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.1/include")
-	ADD_PATH("/usr/local/include")
-	ADD_PATH("/usr/lib/gcc/x86_64-pc-linux-gnu/14.2.1/include-fixed")
-	ADD_PATH("/usr/include")
+	INIT_PATHS
+#define DO_PATH INCR_NPATHS
+#include "machine.gen"
+#undef DO_PATH
+	DO_PATHS
+#define DO_PATH ADD_PATH
+#include "machine.gen"
+#undef DO_PATH
 #define x86_64_NPREDEFS 9
 	EXTRA_MACROS
 	ADD_NAME(__x86_64__)
diff --git a/wrapperhelper/src/main.c b/wrapperhelper/src/main.c
index ffe09146..1b5b2db2 100644
--- a/wrapperhelper/src/main.c
+++ b/wrapperhelper/src/main.c
@@ -12,12 +12,13 @@
 
 static void help(char *arg0) {
 	printf("Usage: %s --help\n"
-	       "       %s [--prepare|--preproc|--proc] <filename_in>\n"
-	       "       %s <filename_in> <filename_reqs> <filename_out>\n"
+	       "       %s {-I/path/to/include}* [--prepare|--preproc|--proc] <filename_in>\n"
+	       "       %s {-I/path/to/include}* <filename_in> <filename_reqs> <filename_out>\n"
 	       "\n"
 	       "  --prepare  Dump all preprocessor tokens (prepare phase)\n"
 	       "  --preproc  Dump all processor tokens (preprocessor phase)\n"
 	       "  --proc     Dump all typedefs, declarations and constants (processor phase)\n"
+	       "  -I         Add a path to the list of system includes\n"
 	       "\n"
 	       "  <filename_in>    Parsing file\n"
 	       "  <filename_reqs>  Reference file (example: wrappedlibc_private.h)\n"
@@ -53,11 +54,14 @@ int main(int argc, char **argv) {
 			ms = MAIN_PREPROC;
 		} else if (!strcmp(argv[i], "--proc")) {
 			ms = MAIN_PROC;
+		} else if (!strcmp(argv[i], "-pthread")) {
+			// Ignore
 		} else if (!strcmp(argv[i], "-I") && (i + 1 < argc)) {
 			if (!vector_push(charp, paths, argv[i + 1])) {
 				printf("Error: failed to add path to buffer\n");
 				return 2;
 			}
+			++i;
 		} else if ((argv[i][0] == '-') && (argv[i][1] == 'I') && (argv[i][2] != '\0')) {
 			if (!vector_push(charp, paths, argv[i] + 2)) {
 				printf("Error: failed to add path to buffer\n");
@@ -127,31 +131,31 @@ int main(int argc, char **argv) {
 			del_str2kw();
 			return 2;
 		}
-		VECTOR(requests) *reqs = requests_from_file(ref_file, ref);
+		VECTOR(references) *reqs = references_from_file(ref_file, ref);
 		if (!reqs) {
 			file_del(content);
 			del_machines();
 			del_str2kw();
 			return 2;
 		}
-		// vector_for(requests, req, reqs) request_print(req);
-		if (!solve_requests(reqs, content->decl_map)) {
+		// vector_for(references, req, reqs) request_print(req);
+		if (!solve_references(reqs, content->decl_map)) {
 			printf("Warning: failed to solve all default requests\n");
 		}
-		// vector_for(requests, req, reqs) request_print(req);
-		//vector_for(requests, req, reqs) request_print_check(req);
+		// vector_for(references, req, reqs) request_print(req);
+		//vector_for(references, req, reqs) request_print_check(req);
 		FILE *out = fopen(out_file, "w");
 		if (!out) {
 			err(2, "Error: failed to open %s", ref_file);
 			file_del(content);
-			vector_del(requests, reqs);
+			vector_del(references, reqs);
 			del_machines();
 			del_str2kw();
 			return 2;
 		}
-		output_from_requests(out, reqs);
+		output_from_references(out, reqs);
 		fclose(out);
-		vector_del(requests, reqs);
+		vector_del(references, reqs);
 		file_del(content);
 		del_machines();
 		del_str2kw();
diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c
index 83167bd9..cce0a115 100644
--- a/wrapperhelper/src/parse.c
+++ b/wrapperhelper/src/parse.c
@@ -685,6 +685,30 @@ expr_new_token:
 		string_del(tok->tokv.str);
 		*tok = proc_next_token(prep);
 		goto expr_new_token;
+	} else if ((tok->tokt == PTOK_STRING) && !tok->tokv.sisstr) {
+		if (has_level != -1) {
+			printf("Error: invalid expression: unexpected character constant '%s'\n", string_content(tok->tokv.sstr));
+			string_del(tok->tokv.sstr);
+			goto failed;
+		}
+		if (string_len(tok->tokv.sstr) != 1) {
+			printf("Error: TODO: invalid expression: multibyte character constant '%s'\n", string_content(tok->tokv.sstr));
+			string_del(tok->tokv.sstr);
+			goto failed;
+		}
+		has_level = 0;
+		e = malloc(sizeof *e);
+		if (!e) {
+			printf("Error: failed to create new expression atom\n");
+			string_del(tok->tokv.sstr);
+			goto failed;
+		}
+		e->typ = ETY_CONST;
+		e->val.cst.typ = NCT_INT32;
+		e->val.cst.val.i32 = (int32_t)string_content(tok->tokv.sstr)[0];
+		string_del(tok->tokv.sstr);
+		*tok = proc_next_token(prep);
+		goto expr_new_token;
 	}
 	
 #define UNOP(toksym, opt, main_lv, right_lv) \
@@ -1397,6 +1421,18 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan
 		
 		if (e->val.cast.typ->typ == TYPE_BUILTIN) {
 			switch (e->val.cast.typ->val.builtin) {
+			case BTT_UCHAR:
+				switch (dest->typ) {
+				case NCT_FLOAT:   dest->val.u32 = (uint8_t)dest->val.f; break;
+				case NCT_DOUBLE:  dest->val.u32 = (uint8_t)dest->val.d; break;
+				case NCT_LDOUBLE: dest->val.u32 = (uint8_t)dest->val.l; break;
+				case NCT_INT32:   dest->val.u32 = (uint8_t)dest->val.i32; break;
+				case NCT_UINT32:  dest->val.u32 = (uint8_t)dest->val.u32; break;
+				case NCT_INT64:   dest->val.u32 = (uint8_t)dest->val.i64; break;
+				case NCT_UINT64:  dest->val.u32 = (uint8_t)dest->val.u64; break;
+				}
+				dest->typ = NCT_UINT32;
+				return 1;
 			case BTT_INT:
 				switch (dest->typ) {
 				case NCT_FLOAT:   dest->val.i32 = (int32_t)dest->val.f; break;
@@ -1409,11 +1445,35 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan
 				}
 				dest->typ = NCT_INT32;
 				return 1;
+			case BTT_ULONG:
+				// Warning: assuming sizeof(long) == 8 on the current target
+				switch (dest->typ) {
+				case NCT_FLOAT:   dest->val.u64 = (uint64_t)dest->val.f; break;
+				case NCT_DOUBLE:  dest->val.u64 = (uint64_t)dest->val.d; break;
+				case NCT_LDOUBLE: dest->val.u64 = (uint64_t)dest->val.l; break;
+				case NCT_INT32:   dest->val.u64 = (uint64_t)dest->val.i32; break;
+				case NCT_UINT32:  dest->val.u64 = (uint64_t)dest->val.u32; break;
+				case NCT_INT64:   dest->val.u64 = (uint64_t)dest->val.i64; break;
+				case NCT_UINT64: break;
+				}
+				dest->typ = NCT_UINT64;
+				return 1;
+			case BTT_U32:
+				switch (dest->typ) {
+				case NCT_FLOAT:   dest->val.u32 = (uint32_t)dest->val.f; break;
+				case NCT_DOUBLE:  dest->val.u32 = (uint32_t)dest->val.d; break;
+				case NCT_LDOUBLE: dest->val.u32 = (uint32_t)dest->val.l; break;
+				case NCT_INT32:   dest->val.u32 = (uint32_t)dest->val.i32; break;
+				case NCT_UINT32: break;
+				case NCT_INT64:   dest->val.u32 = (uint32_t)dest->val.i64; break;
+				case NCT_UINT64:  dest->val.u32 = (uint32_t)dest->val.u64; break;
+				}
+				dest->typ = NCT_UINT32;
+				return 1;
 			case BTT_VOID:
 			case BTT_BOOL:
 			case BTT_CHAR:
 			case BTT_SCHAR:
-			case BTT_UCHAR:
 			case BTT_SHORT:
 			case BTT_SSHORT:
 			case BTT_USHORT:
@@ -1421,7 +1481,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan
 			case BTT_UINT:
 			case BTT_LONG:
 			case BTT_SLONG:
-			case BTT_ULONG:
 			case BTT_LONGLONG:
 			case BTT_SLONGLONG:
 			case BTT_ULONGLONG:
@@ -1433,7 +1492,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan
 			case BTT_S16:
 			case BTT_U16:
 			case BTT_S32:
-			case BTT_U32:
 			case BTT_S64:
 			case BTT_U64:
 			case BTT_FLOAT:
@@ -1447,7 +1505,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan
 			case BTT_ILONGDOUBLE:
 			case BTT_VA_LIST:
 			default:
-				printf("Error: TODO: cast to builtin in constant expression\n");
+				printf("Error: TODO: cast to builtin %s in constant expression\n", builtin2str[e->val.cast.typ->val.builtin]);
 				return 0;
 			}
 		} else {
diff --git a/wrapperhelper/src/prepare.c b/wrapperhelper/src/prepare.c
index 994d8292..616f2332 100644
--- a/wrapperhelper/src/prepare.c
+++ b/wrapperhelper/src/prepare.c
@@ -14,6 +14,7 @@ struct prepare_s {
 		PREPST_INCL,
 		PREPST_DEF,
 		PREPST_DEFID,
+		PREPST_COMMENT,
 	} st;
 };
 
@@ -154,6 +155,37 @@ static const struct symbs_s {
 };
 
 preproc_token_t pre_next_token(prepare_t *src, int allow_comments) {
+	if (src->st == PREPST_COMMENT) {
+		// In comments, keep everything as 'BLANK' except for idents, newlines and EOF
+		int c = get_char(src);
+		if (c == EOF) {
+			// Force newline at EOF
+			unget_char(src, c);
+			src->st = PREPST_NL;
+			return (preproc_token_t){
+				.tokt = PPTOK_NEWLINE,
+				.tokv.c = (char)c
+			};
+		} else if ((c == '_') || ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) {
+			preproc_token_t ret;
+			ret.tokt = PPTOK_IDENT;
+			ret.tokv.str = string_new_cap(1);
+			string_add_char(ret.tokv.str, (char)c);
+			fill_ident(src, ret.tokv.str);
+			return ret;
+		} else if ((c >= 0) && (c <= 0x7F)) {
+			return (preproc_token_t){
+				.tokt = PPTOK_BLANK,
+				.tokv.c = (char)c
+			};
+		} else {
+			return (preproc_token_t){
+				.tokt = PPTOK_INVALID,
+				.tokv.c = (char)c
+			};
+		}
+	}
+	
 start_next_token:
 	int c = get_char(src);
 	if (c == EOF) {
@@ -259,7 +291,7 @@ start_next_token:
 		c = get_char(src);
 		if (c == '/') {
 			if (allow_comments) {
-				src->st = PREPST_NONE;
+				src->st = PREPST_COMMENT;
 				return (preproc_token_t){
 					.tokt = PPTOK_START_LINE_COMMENT,
 					.tokv.c = '/'
@@ -288,6 +320,14 @@ start_next_token:
 				.tokv.c = (char)c
 			};
 		} else if (c == '*') {
+			if (allow_comments) {
+				printf("Unsupported multiline comment with allow_comment in %s\n", src->srcn);
+				return (preproc_token_t){
+					.tokt = PPTOK_INVALID,
+					.tokv.c = (char)c
+				};
+			}
+			
 			c = get_char(src);
 			int last_star = 0;
 			while ((c != EOF) && (!last_star || (c != '/'))) {
@@ -349,24 +389,26 @@ start_next_token:
 		.tokv.c = (char)c
 	};
 }
-preproc_token_t pre_next_newline_token(prepare_t *src) {
-start_next_token:
-	int c = get_char(src);
-	if (c == EOF) {
-		// Force newline at EOF
-		unget_char(src, c);
-		src->st = PREPST_NL;
-		return (preproc_token_t){
-			.tokt = PPTOK_NEWLINE,
-			.tokv.c = (char)c
-		};
-	}
-	if (c == '\n') {
-		src->st = PREPST_NL;
-		return (preproc_token_t){
-			.tokt = PPTOK_NEWLINE,
-			.tokv.c = (char)c
-		};
+
+// Warning: unsafe method
+void prepare_mark_nocomment(prepare_t *src) {
+	src->st = PREPST_NONE;
+}
+int pre_next_newline_token(prepare_t *src, string_t *buf) {
+	while (1) {
+		int c = get_char(src);
+		if (c == EOF) {
+			// Force newline at EOF
+			unget_char(src, c);
+			src->st = PREPST_NL;
+			return 1;
+		} else if (c == '\n') {
+			src->st = PREPST_NL;
+			return 1;
+		} else if ((c >= 0) && (c <= 0x7F)) {
+			if (!string_add_char(buf, (char)c)) return 0;
+		} else {
+			return 0;
+		}
 	}
-	goto start_next_token;
 }
diff --git a/wrapperhelper/src/prepare.h b/wrapperhelper/src/prepare.h
index ccb57a5f..c8424261 100644
--- a/wrapperhelper/src/prepare.h
+++ b/wrapperhelper/src/prepare.h
@@ -13,6 +13,8 @@ typedef struct prepare_s prepare_t;
 prepare_t *prepare_new_file(FILE *f, const char *filename); // Takes ownership of f
 void prepare_del(prepare_t *src);
 preproc_token_t pre_next_token(prepare_t *src, int allow_comments);
-preproc_token_t pre_next_newline_token(prepare_t *src); // In a comment ignore everything until the EOL or EOF
+
+void prepare_mark_nocomment(prepare_t *src); // Change the state (usually from COMMENT) to NONE
+int pre_next_newline_token(prepare_t *src, string_t *buf); // In a comment append everything until the EOL or EOF to the buffer
 
 #endif // PREPARE_H
diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c
index cdff0a4e..fddf2d1c 100644
--- a/wrapperhelper/src/preproc.c
+++ b/wrapperhelper/src/preproc.c
@@ -1000,6 +1000,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const
 
 #define OPLVL_MUL 2
 #define OPLVL_DIV 2
+#define OPLVL_MOD 2
 #define OPLVL_ADD 3
 #define OPLVL_SUB 3
 #define OPLVL_LSL 4
@@ -1017,6 +1018,7 @@ static VECTOR(preproc) *proc_do_expand(const khash_t(macros_map) *macros, const
 #define OPLVL_BOR 11 // Boolean
 #define OPTYP_MUL 1
 #define OPTYP_DIV 2
+#define OPTYP_MOD 3
 #define OPTYP_ADD 1
 #define OPTYP_SUB 2
 #define OPTYP_LSL 1
@@ -1188,6 +1190,16 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) {
 					op_typ = OPTYP_DIV;
 					break;
 				}
+			case SYM_PERCENT:
+				// Binary (st0 != 0)
+				if (vector_last(ppeaux, stack).st0 == 0) {
+					printf("Invalid %snary '%s' in #if expression\n", "bi", sym2str[tok->tokv.sym]);
+					goto eval_fail;
+				} else {
+					op_lvl = OPLVL_MOD;
+					op_typ = OPTYP_MOD;
+					break;
+				}
 			case SYM_HAT:
 				// Binary (st0 != 0)
 				if (vector_last(ppeaux, stack).st0 == 0) {
@@ -1360,6 +1372,13 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) {
 					}
 					acc = vector_last(ppeaux, stack).v2 / acc;
 					vector_last(ppeaux, stack).st2 = 0;
+				} else if (vector_last(ppeaux, stack).st2 == OPTYP_MOD) {
+					if (!acc) {
+						printf("Error: division by zero\n");
+						goto eval_fail;
+					}
+					acc = vector_last(ppeaux, stack).v2 % acc;
+					vector_last(ppeaux, stack).st2 = 0;
 				} else if (vector_last(ppeaux, stack).st2) {
 					printf("<internal error> Unknown st2 %d during #if evaluation\n", vector_last(ppeaux, stack).st2);
 					goto eval_fail;
@@ -1518,7 +1537,6 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) {
 			case SYM_VARIADIC:
 			case SYM_DOT:
 			case SYM_DASHGT:
-			case SYM_PERCENT:
 			case SYM_EQ:
 			case SYM_PLUSEQ:
 			case SYM_DASHEQ:
@@ -1558,6 +1576,13 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) {
 				}
 				acc = vector_last(ppeaux, stack).v2 / acc;
 				vector_last(ppeaux, stack).st2 = 0;
+			} else if (vector_last(ppeaux, stack).st2 == OPTYP_MOD) {
+				if (!acc) {
+					printf("Error: division by zero\n");
+					goto eval_fail;
+				}
+				acc = vector_last(ppeaux, stack).v2 % acc;
+				vector_last(ppeaux, stack).st2 = 0;
 			} else if (vector_last(ppeaux, stack).st2) {
 				printf("<internal error> Unknown st2 %d during #if evaluation\n", vector_last(ppeaux, stack).st2);
 				goto eval_fail;
@@ -1793,6 +1818,13 @@ done_complete_stack:
 		}
 		acc = vector_last(ppeaux, stack).v2 / acc;
 		vector_last(ppeaux, stack).st2 = 0;
+	} else if (vector_last(ppeaux, stack).st2 == OPTYP_MOD) {
+		if (!acc) {
+			printf("Error: division by zero\n");
+			goto eval_fail;
+		}
+		acc = vector_last(ppeaux, stack).v2 % acc;
+		vector_last(ppeaux, stack).st2 = 0;
 	} else if (vector_last(ppeaux, stack).st2) {
 		printf("<internal error> Unknown st2 %d during #if evaluation\n", vector_last(ppeaux, stack).st2);
 		goto eval_fail;
@@ -2068,6 +2100,7 @@ check_if_depth:
 						// Forbidding this code would require another 64-bits bitfield, which is redundant, thus not implemented.
 						// Also, we only need to goto check_if_depth if we actually update ok_depth
 						if ((ppsrc->srcv.prep.ok_depth == ppsrc->srcv.prep.cond_depth - 1) && !ppsrc->srcv.prep.entered_next_ok_cond) {
+							vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1;
 							++ppsrc->srcv.prep.ok_depth;
 							goto preproc_ignore_remaining_goto;
 						} else goto preproc_ignore_remaining;
@@ -2297,7 +2330,7 @@ start_cur_token:
 				if (tok.tokt == PPTOK_INCL) {
 					incl_file = tok.tokv.sstr;
 					// Assume we only have one #include "..." path, so include_next is always a system include
-					is_sys = is_next || src->is_sys || !tok.tokv.sisstr;
+					is_sys = is_next || !tok.tokv.sisstr;
 					tok = ppsrc_next_token(src); // Token was moved
 					while ((tok.tokt != PPTOK_NEWLINE) && (tok.tokt != PPTOK_EOF) && (tok.tokt != PPTOK_INVALID)) {
 						printf("Warning: ignored tokens after #include directive (%s)\n", src->cur_file);
@@ -2435,7 +2468,6 @@ start_cur_token:
 					src->st = PPST_NONE;
 					ret.tokt = PTOK_INVALID;
 					ret.tokv = (union proc_token_val_u){.c = tok.tokv.sisstr ? '<' : '"'};
-					string_del(tok.tokv.sstr);
 					return ret;
 				}
 				string_del(incl_file);
@@ -3133,7 +3165,7 @@ proc_token_t proc_next_token(preproc_t *src) {
 	if ((ret.tokt == PTOK_STRING) && ret.tokv.sisstr) {
 		while (1) {
 			proc_token_t ret2 = proc_next_token_aux(src);
-			if ((ret.tokt == PTOK_STRING) && ret.tokv.sisstr) {
+			if ((ret2.tokt == PTOK_STRING) && ret2.tokv.sisstr) {
 				if (!string_add_string(ret.tokv.sstr, ret2.tokv.sstr)) {
 					printf("Error: failed to concatenate adjacent strings\n");
 					string_del(ret.tokv.sstr);
diff --git a/wrapperhelper/src/vector.c b/wrapperhelper/src/vector.c
index dffcb493..c3f710d7 100644
--- a/wrapperhelper/src/vector.c
+++ b/wrapperhelper/src/vector.c
@@ -40,6 +40,7 @@ int vector_reserve_impl(VECTOR(voidp) *v, size_t elem_size, size_t cap) {
 }
 
 int vector_trim_impl(VECTOR(voidp) *v, size_t elem_size) {
+	if (v->vsize == v->vcap) return 1;
 	if (v->vsize) {
 		void *new_content_v = realloc(v->content_v, elem_size * v->vsize);
 		if (!new_content_v) return 0;
diff --git a/wrapperhelper/src/vector.h b/wrapperhelper/src/vector.h
index 70319cc2..6e0c124a 100644
--- a/wrapperhelper/src/vector.h
+++ b/wrapperhelper/src/vector.h
@@ -26,7 +26,7 @@
  * vector_new --------------- Creates a new vector. Takes the name.
  * vector_new_cap ----------- Creates a new vector with a given capacity. Takes the name and the capacity.
  * vector_reserve ----------- Ensures a vector has at least a given capacity. Takes the name, the vector and the capacity. May not reduce the vector capacity.
- * vector_trim -------------- Ensures a vector has a capacity equal to its size. Takes the name, the vector. May reduce the vector capacity.
+ * vector_trim -------------- Ensures a vector has a capacity equal to its size. Takes the name and the vector. May reduce the vector capacity.
  * vector_del --------------- Frees a vector. Takes the name and the vector. Destructs the content of the vector.
  * vector_steal ------------- Frees a vector and returns the content. Takes the name and the vector. May reduce the vector capacity.
  * vector_del_freed --------- Frees a vector without freeing the content. Takes the name and the vector. Does not interact with the content of the vector.