+/* Append a character to the token buffer */
+static void lex_tokench(lex_file *lex, int ch)
+{
+ vec_push(lex->tok.value, ch);
+}
+
+/* Append a trailing null-byte */
+static void lex_endtoken(lex_file *lex)
+{
+ vec_push(lex->tok.value, 0);
+ vec_shrinkby(lex->tok.value, 1);
+}
+
+static bool lex_try_pragma(lex_file *lex)
+{
+ int ch;
+ char *pragma = NULL;
+ char *command = NULL;
+ char *param = NULL;
+ size_t line;
+
+ if (lex->flags.preprocessing)
+ return false;
+
+ line = lex->line;
+
+ ch = lex_getch(lex);
+ if (ch != '#') {
+ lex_ungetch(lex, ch);
+ return false;
+ }
+
+ for (ch = lex_getch(lex); vec_size(pragma) < 8 && ch >= 'a' && ch <= 'z'; ch = lex_getch(lex))
+ vec_push(pragma, ch);
+ vec_push(pragma, 0);
+
+ if (ch != ' ' || strcmp(pragma, "pragma")) {
+ lex_ungetch(lex, ch);
+ goto unroll;
+ }
+
+ for (ch = lex_getch(lex); vec_size(command) < 32 && ch >= 'a' && ch <= 'z'; ch = lex_getch(lex))
+ vec_push(command, ch);
+ vec_push(command, 0);
+
+ if (ch != '(') {
+ lex_ungetch(lex, ch);
+ goto unroll;
+ }
+
+ for (ch = lex_getch(lex); vec_size(param) < 1024 && ch != ')' && ch != '\n'; ch = lex_getch(lex))
+ vec_push(param, ch);
+ vec_push(param, 0);
+
+ if (ch != ')') {
+ lex_ungetch(lex, ch);
+ goto unroll;
+ }
+
+ if (!strcmp(command, "push")) {
+ if (!strcmp(param, "line")) {
+ lex->push_line++;
+ if (lex->push_line == 1)
+ --line;
+ }
+ else
+ goto unroll;
+ }
+ else if (!strcmp(command, "pop")) {
+ if (!strcmp(param, "line")) {
+ if (lex->push_line)
+ lex->push_line--;
+ if (lex->push_line == 0)
+ --line;
+ }
+ else
+ goto unroll;
+ }
+ else if (!strcmp(command, "file")) {
+ lex->name = util_strdup(param);
+ vec_push(lex_filenames, lex->name);
+ }
+ else if (!strcmp(command, "line")) {
+ line = strtol(param, NULL, 0)-1;
+ }
+ else
+ goto unroll;
+
+ lex->line = line;
+ while (ch != '\n' && ch != EOF)
+ ch = lex_getch(lex);
+ return true;
+
+unroll:
+ if (command) {
+ vec_pop(command);
+ while (vec_size(command)) {
+ lex_ungetch(lex, vec_last(command));
+ vec_pop(command);
+ }
+ vec_free(command);
+ lex_ungetch(lex, ' ');
+ }
+ if (command) {
+ vec_pop(command);
+ while (vec_size(command)) {
+ lex_ungetch(lex, vec_last(command));
+ vec_pop(command);
+ }
+ vec_free(command);
+ lex_ungetch(lex, ' ');
+ }
+ if (pragma) {
+ vec_pop(pragma);
+ while (vec_size(pragma)) {
+ lex_ungetch(lex, vec_last(pragma));
+ vec_pop(pragma);
+ }
+ vec_free(pragma);
+ }
+ lex_ungetch(lex, '#');
+
+ lex->line = line;
+ return false;
+}
+