type: Make an assert()ion independent of the last entry of an enum.
[cparser] / preprocessor.c
index 6e3daf3..5d4213b 100644 (file)
@@ -1,3 +1,7 @@
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
+ */
 #include <config.h>
 
 #include <assert.h>
@@ -38,7 +42,7 @@ typedef struct whitespace_info_t {
 
 struct pp_definition_t {
        symbol_t          *symbol;
-       source_position_t  source_position;
+       position_t         pos;
        pp_definition_t   *parent_expansion;
        size_t             expand_pos;
        whitespace_info_t  expand_info;
@@ -57,7 +61,7 @@ struct pp_definition_t {
 
 typedef struct pp_conditional_t pp_conditional_t;
 struct pp_conditional_t {
-       source_position_t  source_position;
+       position_t         pos;
        bool               condition;
        bool               in_else;
        /** conditional in skip mode (then+else gets skipped) */
@@ -73,7 +77,7 @@ struct pp_input_t {
        utf32               buf[1024+MAX_PUTBACK];
        const utf32        *bufend;
        const utf32        *bufpos;
-       source_position_t   position;
+       position_t          pos;
        pp_input_t         *parent;
        unsigned            output_line;
        searchpath_entry_t *path;
@@ -102,7 +106,7 @@ static FILE             *out;
 static struct obstack    pp_obstack;
 static struct obstack    config_obstack;
 static const char       *printed_input_name = NULL;
-static source_position_t expansion_pos;
+static position_t        expansion_pos;
 static pp_definition_t  *current_expansion  = NULL;
 static pp_definition_t  *current_call       = NULL;
 static pp_definition_t  *current_argument   = NULL;
@@ -127,7 +131,7 @@ static whitespace_info_t info;
 
 static inline void next_char(void);
 static void next_input_token(void);
-static void print_line_directive(const source_position_t *pos, const char *add);
+static void print_line_directive(const position_t *pos, const char *add);
 
 static symbol_t *symbol_colongreater;
 static symbol_t *symbol_lesscolon;
@@ -136,6 +140,11 @@ static symbol_t *symbol_percentcolon;
 static symbol_t *symbol_percentcolonpercentcolon;
 static symbol_t *symbol_percentgreater;
 
+static symbol_t *symbol_L;
+static symbol_t *symbol_U;
+static symbol_t *symbol_u;
+static symbol_t *symbol_u8;
+
 static void init_symbols(void)
 {
        symbol_colongreater             = symbol_table_insert(":>");
@@ -144,26 +153,31 @@ static void init_symbols(void)
        symbol_percentcolon             = symbol_table_insert("%:");
        symbol_percentcolonpercentcolon = symbol_table_insert("%:%:");
        symbol_percentgreater           = symbol_table_insert("%>");
+
+       symbol_L  = symbol_table_insert("L");
+       symbol_U  = symbol_table_insert("U");
+       symbol_u  = symbol_table_insert("u");
+       symbol_u8 = symbol_table_insert("u8");
 }
 
 void switch_pp_input(FILE *const file, char const *const filename, searchpath_entry_t *const path, bool const is_system_header)
 {
-       input.file                      = file;
-       input.input                     = input_from_stream(file, NULL);
-       input.bufend                    = NULL;
-       input.bufpos                    = NULL;
-       input.output_line               = 0;
-       input.position.input_name       = filename;
-       input.position.lineno           = 1;
-       input.position.is_system_header = is_system_header;
-       input.path                      = path;
+       input.file                 = file;
+       input.input                = input_from_stream(file, NULL);
+       input.bufend               = NULL;
+       input.bufpos               = NULL;
+       input.output_line          = 0;
+       input.pos.input_name       = filename;
+       input.pos.lineno           = 1;
+       input.pos.is_system_header = is_system_header;
+       input.path                 = path;
 
        /* indicate that we're at a new input */
-       print_line_directive(&input.position, input_stack != NULL ? "1" : NULL);
+       print_line_directive(&input.pos, input_stack != NULL ? "1" : NULL);
 
        /* place a virtual '\n' so we realize we're at line begin */
-       input.position.lineno = 0;
-       input.c               = '\n';
+       input.pos.lineno = 0;
+       input.c          = '\n';
 }
 
 FILE *close_pp_input(void)
@@ -225,7 +239,7 @@ static void pop_restore_input(void)
  */
 static void parse_error(const char *msg)
 {
-       errorf(&pp_token.base.source_position,  "%s", msg);
+       errorf(&pp_token.base.pos,  "%s", msg);
 }
 
 static inline void next_real_char(void)
@@ -241,7 +255,7 @@ static inline void next_real_char(void)
                input.bufend = input.bufpos + n;
        }
        input.c = *input.bufpos++;
-       ++input.position.colno;
+       ++input.pos.colno;
 }
 
 /**
@@ -253,7 +267,7 @@ static inline void put_back(utf32 const pc)
 {
        assert(input.bufpos > input.buf);
        *(--input.bufpos - input.buf + input.buf) = (char) pc;
-       --input.position.colno;
+       --input.pos.colno;
 }
 
 #define NEWLINE \
@@ -263,8 +277,8 @@ static inline void put_back(utf32 const pc)
        case '\n': \
                        next_char(); \
                } \
-               ++input.position.lineno; \
-               input.position.colno = 1; \
+               ++input.pos.lineno; \
+               input.pos.colno = 1; \
                goto newline; \
                newline // Let it look like an ordinary case label.
 
@@ -445,14 +459,14 @@ static utf32 parse_universal_char(unsigned const n_digits)
                                obstack_1grow(&symbol_obstack, input.c);
                        next_char();
                } else {
-                       errorf(&input.position,
+                       errorf(&input.pos,
                               "short universal character name, expected %u more digits",
                                   k);
                        break;
                }
        }
        if (!is_universal_char_valid(v)) {
-               errorf(&input.position,
+               errorf(&input.pos,
                       "\\%c%0*X is not a valid universal character name",
                       n_digits == 4 ? 'u' : 'U', (int)n_digits, v);
        }
@@ -684,23 +698,35 @@ string_t make_string(char const *const string)
        return sym_make_string(STRING_ENCODING_CHAR);
 }
 
+static utf32 get_string_encoding_limit(string_encoding_t const enc)
+{
+       switch (enc) {
+       case STRING_ENCODING_CHAR:   return 0xFF;
+       case STRING_ENCODING_CHAR16: return 0xFFFF;
+       case STRING_ENCODING_CHAR32: return 0xFFFFFFFF;
+       case STRING_ENCODING_UTF8:   return 0xFFFFFFFF;
+       case STRING_ENCODING_WIDE:   return 0xFFFFFFFF; // FIXME depends on settings
+       }
+       panic("invalid string encoding");
+}
+
 static void parse_string(utf32 const delimiter, token_kind_t const kind,
                          string_encoding_t const enc,
                          char const *const context)
 {
-       const unsigned start_linenr = input.position.lineno;
-
        eat(delimiter);
 
+       utf32 const limit = get_string_encoding_limit(enc);
        while (true) {
                switch (input.c) {
                case '\\': {
                        if (resolve_escape_sequences) {
                                utf32 const tc = parse_escape_sequence();
+                               if (tc > limit) {
+                                       warningf(WARN_OTHER, &pp_token.base.pos,
+                                                "escape sequence out of range");
+                               }
                                if (enc == STRING_ENCODING_CHAR) {
-                                       if (tc >= 0x100) {
-                                               warningf(WARN_OTHER, &pp_token.base.source_position, "escape sequence out of range");
-                                       }
                                        obstack_1grow(&symbol_obstack, tc);
                                } else {
                                        obstack_grow_utf8(&symbol_obstack, tc);
@@ -715,16 +741,12 @@ static void parse_string(utf32 const delimiter, token_kind_t const kind,
                }
 
                case NEWLINE:
-                       errorf(&pp_token.base.source_position, "newline while parsing %s", context);
+                       errorf(&pp_token.base.pos, "newline while parsing %s", context);
                        break;
 
-               case EOF: {
-                       source_position_t source_position;
-                       source_position.input_name = pp_token.base.source_position.input_name;
-                       source_position.lineno     = start_linenr;
-                       errorf(&source_position, "EOF while parsing %s", context);
+               case EOF:
+                       errorf(&pp_token.base.pos, "EOF while parsing %s", context);
                        goto end_of_string;
-               }
 
                default:
                        if (input.c == delimiter) {
@@ -963,7 +985,7 @@ restart:;
        if (current_expansion->expand_pos > 0)
                info.had_whitespace = saved->had_whitespace;
        current_expansion->expand_pos = pos;
-       pp_token.base.source_position = expansion_pos;
+       pp_token.base.pos             = expansion_pos;
 
        return true;
 }
@@ -1004,7 +1026,7 @@ static void skip_multiline_comment(void)
 {
        info.had_whitespace = true;
 
-       unsigned start_linenr = input.position.lineno;
+       position_t const start_pos = input.pos;
        while (true) {
                switch (input.c) {
                case '/':
@@ -1016,8 +1038,8 @@ static void skip_multiline_comment(void)
                case '*':
                        next_char();
                        if (input.c == '/') {
-                               if (input.position.lineno != input.output_line)
-                                       info.whitespace_at_line_begin = input.position.colno;
+                               if (input.pos.lineno != input.output_line)
+                                       info.whitespace_at_line_begin = input.pos.colno;
                                next_char();
                                return;
                        }
@@ -1026,13 +1048,9 @@ static void skip_multiline_comment(void)
                case NEWLINE:
                        break;
 
-               case EOF: {
-                       source_position_t source_position;
-                       source_position.input_name = pp_token.base.source_position.input_name;
-                       source_position.lineno     = start_linenr;
-                       errorf(&source_position, "at end of file while looking for comment end");
+               case EOF:
+                       errorf(&start_pos, "at end of file while looking for comment end");
                        return;
-               }
 
                default:
                        next_char();
@@ -1133,6 +1151,17 @@ static inline void eat_token(token_kind_t const kind)
        next_input_token();
 }
 
+static string_encoding_t identify_encoding_prefix(symbol_t *const sym)
+{
+       if (sym == symbol_L) return STRING_ENCODING_WIDE;
+       if (c_mode & _C11) {
+               if (sym == symbol_U)  return STRING_ENCODING_CHAR32;
+               if (sym == symbol_u)  return STRING_ENCODING_CHAR16;
+               if (sym == symbol_u8) return STRING_ENCODING_UTF8;
+       }
+       return STRING_ENCODING_CHAR;
+}
+
 static void parse_symbol(void)
 {
        assert(obstack_object_size(&symbol_obstack) == 0);
@@ -1160,12 +1189,12 @@ universal:
                                utf32 const v = parse_universal_char(n);
                                if (!is_universal_char_valid_identifier(v)) {
                                        if (is_universal_char_valid(v)) {
-                                               errorf(&input.position,
+                                               errorf(&input.pos,
                                                           "universal character \\%c%0*X is not valid in an identifier",
                                                           n == 4 ? 'u' : 'U', (int)n, v);
                                        }
                                } else if (obstack_object_size(&symbol_obstack) == 0 && is_universal_char_invalid_identifier_start(v)) {
-                                       errorf(&input.position,
+                                       errorf(&input.pos,
                                                   "universal character \\%c%0*X is not valid as start of an identifier",
                                                   n == 4 ? 'u' : 'U', (int)n, v);
                                } else if (resolve_escape_sequences) {
@@ -1190,19 +1219,27 @@ end_symbol:
        obstack_1grow(&symbol_obstack, '\0');
        char *string = obstack_finish(&symbol_obstack);
 
-       /* might be a wide string or character constant ( L"string"/L'c' ) */
-       if (input.c == '"' && string[0] == 'L' && string[1] == '\0') {
-               obstack_free(&symbol_obstack, string);
-               parse_string_literal(STRING_ENCODING_WIDE);
-               return;
-       } else if (input.c == '\'' && string[0] == 'L' && string[1] == '\0') {
-               obstack_free(&symbol_obstack, string);
-               parse_character_constant(STRING_ENCODING_WIDE);
-               return;
-       }
-
        symbol_t *symbol = symbol_table_insert(string);
 
+       /* Might be a prefixed string or character constant: L/U/u/u8"string". */
+       if (input.c == '"') {
+               string_encoding_t const enc = identify_encoding_prefix(symbol);
+               if (enc != STRING_ENCODING_CHAR) {
+                       parse_string_literal(enc);
+                       return;
+               }
+       } else if (input.c == '\'') {
+               string_encoding_t const enc = identify_encoding_prefix(symbol);
+               if (enc != STRING_ENCODING_CHAR) {
+                       if (enc == STRING_ENCODING_UTF8) {
+                               errorf(&pp_token.base.pos,
+                                      "'u8' is not a valid encoding for a chracter constant");
+                       }
+                       parse_character_constant(enc);
+                       return;
+               }
+       }
+
        pp_token.kind        = symbol->ID;
        pp_token.base.symbol = symbol;
 
@@ -1285,8 +1322,8 @@ static void next_input_token(void)
                info.had_whitespace = false;
        }
 restart:
-       pp_token.base.source_position = input.position;
-       pp_token.base.symbol          = NULL;
+       pp_token.base.pos    = input.pos;
+       pp_token.base.symbol = NULL;
 
        switch (input.c) {
        case ' ':
@@ -1469,8 +1506,8 @@ digraph_percentcolon:
                        if (out)
                                fputc('\n', out);
                        if (input.c == (utf32)EOF)
-                               --input.position.lineno;
-                       print_line_directive(&input.position, "2");
+                               --input.pos.lineno;
+                       print_line_directive(&input.pos, "2");
                        goto restart;
                } else {
                        info.at_line_begin = true;
@@ -1491,8 +1528,7 @@ digraph_percentcolon:
        default:
 dollar_sign:
                if (error_on_unknown_chars) {
-                       errorf(&pp_token.base.source_position,
-                              "unknown character '%lc' found\n", input.c);
+                       errorf(&pp_token.base.pos, "unknown character '%lc' found", input.c);
                        next_char();
                        goto restart;
                } else {
@@ -1539,7 +1575,7 @@ static void print_quoted_string(const char *const string)
        fputc('"', out);
 }
 
-static void print_line_directive(const source_position_t *pos, const char *add)
+static void print_line_directive(const position_t *pos, const char *add)
 {
        if (!out)
                return;
@@ -1563,20 +1599,20 @@ static bool emit_newlines(void)
        if (!out)
                return true;
 
-       unsigned delta = pp_token.base.source_position.lineno - input.output_line;
+       unsigned delta = pp_token.base.pos.lineno - input.output_line;
        if (delta == 0)
                return false;
 
        if (delta >= 9) {
                fputc('\n', out);
-               print_line_directive(&pp_token.base.source_position, NULL);
+               print_line_directive(&pp_token.base.pos, NULL);
                fputc('\n', out);
        } else {
                for (unsigned i = 0; i < delta; ++i) {
                        fputc('\n', out);
                }
        }
-       input.output_line = pp_token.base.source_position.lineno;
+       input.output_line = pp_token.base.pos.lineno;
 
        unsigned whitespace = info.whitespace_at_line_begin;
        /* make sure there is at least 1 whitespace before a (macro-expanded)
@@ -1698,14 +1734,13 @@ static bool pp_definitions_equal(const pp_definition_t *definition1,
 
 static void missing_macro_param_error(void)
 {
-       errorf(&pp_token.base.source_position,
-              "'#' is not followed by a macro parameter");
+       errorf(&pp_token.base.pos, "'#' is not followed by a macro parameter");
 }
 
 static bool is_defineable_token(char const *const context)
 {
        if (info.at_line_begin) {
-               errorf(&pp_token.base.source_position, "unexpected end of line after %s", context);
+               errorf(&pp_token.base.pos, "unexpected end of line after %s", context);
        }
 
        symbol_t *const symbol = pp_token.base.symbol;
@@ -1720,7 +1755,8 @@ dollar_sign:
 
                default:
 no_ident:
-                       errorf(&pp_token.base.source_position, "expected identifier after %s, got %K", context, &pp_token);
+                       errorf(&pp_token.base.pos, "expected identifier after %s, got %K",
+                              context, &pp_token);
                        return false;
                }
        }
@@ -1729,7 +1765,8 @@ no_ident:
        switch (symbol->pp_ID) {
        /* Â§6.10.8:4 */
        case TP_defined:
-               errorf(&pp_token.base.source_position, "%K cannot be used as macro name in %s", &pp_token, context);
+               errorf(&pp_token.base.pos, "%K cannot be used as macro name in %s",
+                      &pp_token, context);
                return false;
 
        default:
@@ -1754,8 +1791,8 @@ static void parse_define_directive(void)
        pp_definition_t *new_definition
                = obstack_alloc(&pp_obstack, sizeof(new_definition[0]));
        memset(new_definition, 0, sizeof(new_definition[0]));
-       new_definition->symbol          = symbol;
-       new_definition->source_position = input.position;
+       new_definition->symbol = symbol;
+       new_definition->pos    = input.pos;
 
        /* this is probably the only place where spaces are significant in the
         * lexer (except for the fact that they separate tokens). #define b(x)
@@ -1770,7 +1807,7 @@ static void parse_define_directive(void)
                                new_definition->is_variadic = true;
                                eat_token(T_DOTDOTDOT);
                                if (pp_token.kind != ')') {
-                                       errorf(&input.position,
+                                       errorf(&input.pos,
                                                        "'...' not at end of macro argument list");
                                        goto error_out;
                                }
@@ -1779,9 +1816,9 @@ static void parse_define_directive(void)
                        case T_IDENTIFIER: {
                                pp_definition_t parameter;
                                memset(&parameter, 0, sizeof(parameter));
-                               parameter.source_position = pp_token.base.source_position;
-                               parameter.symbol          = pp_token.base.symbol;
-                               parameter.is_parameter    = true;
+                               parameter.pos          = pp_token.base.pos;
+                               parameter.symbol       = pp_token.base.symbol;
+                               parameter.is_parameter = true;
                                obstack_grow(&pp_obstack, &parameter, sizeof(parameter));
                                eat_token(T_IDENTIFIER);
 
@@ -1791,7 +1828,7 @@ static void parse_define_directive(void)
                                }
 
                                if (pp_token.kind != ')') {
-                                       errorf(&pp_token.base.source_position,
+                                       errorf(&pp_token.base.pos,
                                               "expected ',' or ')' after identifier, got %K",
                                               &pp_token);
                                        goto error_out;
@@ -1804,7 +1841,7 @@ static void parse_define_directive(void)
                                goto finish_argument_list;
 
                        default:
-                               errorf(&pp_token.base.source_position,
+                               errorf(&pp_token.base.pos,
                                       "expected identifier, '...' or ')' in #define argument list, got %K",
                                       &pp_token);
                                goto error_out;
@@ -1818,19 +1855,18 @@ static void parse_define_directive(void)
                        = size / sizeof(new_definition->parameters[0]);
                new_definition->parameters = obstack_finish(&pp_obstack);
                for (size_t i = 0; i < new_definition->n_parameters; ++i) {
-                       pp_definition_t *param    = &new_definition->parameters[i];
-                       symbol_t        *symbol   = param->symbol;
-                       pp_definition_t *previous = symbol->pp_definition;
+                       pp_definition_t *const param     = &new_definition->parameters[i];
+                       symbol_t        *const param_sym = param->symbol;
+                       pp_definition_t *const previous  = param_sym->pp_definition;
                        if (previous != NULL
                            && previous->function_definition == new_definition) {
-                               errorf(&param->source_position,
-                                      "duplicate macro parameter '%Y'", symbol);
+                               errorf(&param->pos, "duplicate macro parameter '%Y'", param_sym);
                                param->symbol = sym_anonymous;
                                continue;
                        }
                        param->parent_expansion    = previous;
                        param->function_definition = new_definition;
-                       symbol->pp_definition      = param;
+                       param_sym->pp_definition   = param;
                }
        } else {
                next_input_token();
@@ -1841,8 +1877,7 @@ static void parse_define_directive(void)
        bool next_must_be_param = false;
        while (!info.at_line_begin) {
                if (pp_token.kind == T_IDENTIFIER) {
-                       const symbol_t  *symbol     = pp_token.base.symbol;
-                       pp_definition_t *definition = symbol->pp_definition;
+                       pp_definition_t *const definition = pp_token.base.symbol->pp_definition;
                        if (definition != NULL
                            && definition->function_definition == new_definition) {
                            pp_token.kind                = T_MACRO_PARAMETER;
@@ -1869,21 +1904,23 @@ static void parse_define_directive(void)
 
        if (new_definition->has_parameters) {
                for (size_t i = 0; i < new_definition->n_parameters; ++i) {
-                       pp_definition_t *param      = &new_definition->parameters[i];
-                       symbol_t        *symbol     = param->symbol;
-                       if (symbol == sym_anonymous)
+                       pp_definition_t *const param     = &new_definition->parameters[i];
+                       symbol_t        *const param_sym = param->symbol;
+                       if (param_sym == sym_anonymous)
                                continue;
-                       assert(symbol->pp_definition == param);
+                       assert(param_sym->pp_definition == param);
                        assert(param->function_definition == new_definition);
-                       symbol->pp_definition   = param->parent_expansion;
-                       param->parent_expansion = NULL;
+                       param_sym->pp_definition = param->parent_expansion;
+                       param->parent_expansion  = NULL;
                }
        }
 
        pp_definition_t *old_definition = symbol->pp_definition;
        if (old_definition != NULL) {
                if (!pp_definitions_equal(old_definition, new_definition)) {
-                       warningf(WARN_OTHER, &input.position, "multiple definition of macro '%Y' (first defined %P)", symbol, &old_definition->source_position);
+                       warningf(WARN_OTHER, &input.pos,
+                                "multiple definition of macro '%Y' (first defined %P)",
+                                symbol, &old_definition->pos);
                } else {
                        /* reuse the old definition */
                        obstack_free(&pp_obstack, new_definition);
@@ -1919,7 +1956,7 @@ static void parse_undef_directive(void)
        next_input_token();
 
        if (!info.at_line_begin) {
-               warningf(WARN_OTHER, &input.position, "extra tokens at end of #undef directive");
+               warningf(WARN_OTHER, &input.pos, "extra tokens at end of #undef directive");
        }
        eat_pp_directive();
 }
@@ -1935,8 +1972,8 @@ static const char *parse_headername(bool *system_include)
                return NULL;
        }
 
-       /* check wether we have a "... or <... headername */
-       source_position_t position = input.position;
+       /* check whether we have a "... or <... headername */
+       position_t pos = input.pos;
        switch (input.c) {
        {
                utf32 delimiter;
@@ -1953,7 +1990,7 @@ parse_name:
                                        char *dummy = obstack_finish(&symbol_obstack);
                                        obstack_free(&symbol_obstack, dummy);
                                }
-                               errorf(&pp_token.base.source_position,
+                               errorf(&pp_token.base.pos,
                                       "header name without closing '%c'", (char)delimiter);
                                return NULL;
 
@@ -2022,7 +2059,7 @@ error_invalid_input:
                                obstack_free(&symbol_obstack, dummy);
                        }
 
-                       errorf(&pp_token.base.source_position,
+                       errorf(&pp_token.base.pos,
                               "expected \"FILENAME\" or <FILENAME> after #include");
                        return NULL;
                }
@@ -2032,7 +2069,7 @@ finish_headername:
        obstack_1grow(&symbol_obstack, '\0');
        char *const  headername = obstack_finish(&symbol_obstack);
        const char  *identified = identify_string(headername);
-       pp_token.base.source_position = position;
+       pp_token.base.pos = pos;
        return identified;
 }
 
@@ -2047,7 +2084,7 @@ static bool do_include(bool const bracket_include, bool const include_next, char
        } else {
                if (!bracket_include) {
                        /* put dirname of current input on obstack */
-                       const char *filename   = input.position.input_name;
+                       const char *filename   = input.pos.input_name;
                        const char *last_slash = strrchr(filename, '/');
                        const char *full_name;
                        if (last_slash != NULL) {
@@ -2114,12 +2151,12 @@ static void parse_include_directive(bool const include_next)
 
        bool had_nonwhitespace = skip_till_newline(false);
        if (had_nonwhitespace) {
-               warningf(WARN_OTHER, &input.position,
+               warningf(WARN_OTHER, &input.pos,
                         "extra tokens at end of #include directive");
        }
 
        if (n_inputs > INCLUDE_LIMIT) {
-               errorf(&pp_token.base.source_position, "#include nested too deeply");
+               errorf(&pp_token.base.pos, "#include nested too deeply");
                /* eat \n or EOF */
                next_input_token();
                return;
@@ -2135,7 +2172,7 @@ static void parse_include_directive(bool const include_next)
        if (res) {
                next_input_token();
        } else {
-               errorf(&pp_token.base.source_position, "failed including '%s': %s", headername, strerror(errno));
+               errorf(&pp_token.base.pos, "failed including '%s': %s", headername, strerror(errno));
                pop_restore_input();
        }
 }
@@ -2164,9 +2201,9 @@ void check_unclosed_conditionals(void)
                pp_conditional_t *conditional = conditional_stack;
 
                if (conditional->in_else) {
-                       errorf(&conditional->source_position, "unterminated #else");
+                       errorf(&conditional->pos, "unterminated #else");
                } else {
-                       errorf(&conditional->source_position, "unterminated condition");
+                       errorf(&conditional->pos, "unterminated condition");
                }
                pop_conditional();
        }
@@ -2180,35 +2217,33 @@ static void parse_ifdef_ifndef_directive(bool const is_ifdef)
        if (skip_mode) {
                eat_pp_directive();
                pp_conditional_t *conditional = push_conditional();
-               conditional->source_position  = pp_token.base.source_position;
-               conditional->skip             = true;
+               conditional->pos  = pp_token.base.pos;
+               conditional->skip = true;
                return;
        }
 
        if (pp_token.kind != T_IDENTIFIER || info.at_line_begin) {
-               errorf(&pp_token.base.source_position,
-                      "expected identifier after #%s, got %K",
+               errorf(&pp_token.base.pos, "expected identifier after #%s, got %K",
                       is_ifdef ? "ifdef" : "ifndef", &pp_token);
                eat_pp_directive();
 
                /* just take the true case in the hope to avoid further errors */
                condition = true;
        } else {
-               /* evaluate wether we are in true or false case */
+               /* evaluate whether we are in true or false case */
                condition = (bool)pp_token.base.symbol->pp_definition == is_ifdef;
                eat_token(T_IDENTIFIER);
 
                if (!info.at_line_begin) {
-                       errorf(&pp_token.base.source_position,
-                              "extra tokens at end of #%s",
+                       errorf(&pp_token.base.pos, "extra tokens at end of #%s",
                               is_ifdef ? "ifdef" : "ifndef");
                        eat_pp_directive();
                }
        }
 
        pp_conditional_t *conditional = push_conditional();
-       conditional->source_position  = pp_token.base.source_position;
-       conditional->condition        = condition;
+       conditional->pos       = pp_token.base.pos;
+       conditional->condition = condition;
 
        if (!condition) {
                skip_mode = true;
@@ -2221,21 +2256,21 @@ static void parse_else_directive(void)
 
        if (!info.at_line_begin) {
                if (!skip_mode) {
-                       warningf(WARN_OTHER, &pp_token.base.source_position, "extra tokens at end of #else");
+                       warningf(WARN_OTHER, &pp_token.base.pos, "extra tokens at end of #else");
                }
                eat_pp_directive();
        }
 
        pp_conditional_t *conditional = conditional_stack;
        if (conditional == NULL) {
-               errorf(&pp_token.base.source_position, "#else without prior #if");
+               errorf(&pp_token.base.pos, "#else without prior #if");
                return;
        }
 
        if (conditional->in_else) {
-               errorf(&pp_token.base.source_position,
+               errorf(&pp_token.base.pos,
                       "#else after #else (condition started %P)",
-                      &conditional->source_position);
+                      &conditional->pos);
                skip_mode = true;
                return;
        }
@@ -2244,7 +2279,7 @@ static void parse_else_directive(void)
        if (!conditional->skip) {
                skip_mode = conditional->condition;
        }
-       conditional->source_position = pp_token.base.source_position;
+       conditional->pos = pp_token.base.pos;
 }
 
 static void parse_endif_directive(void)
@@ -2253,14 +2288,14 @@ static void parse_endif_directive(void)
 
        if (!info.at_line_begin) {
                if (!skip_mode) {
-                       warningf(WARN_OTHER, &pp_token.base.source_position, "extra tokens at end of #endif");
+                       warningf(WARN_OTHER, &pp_token.base.pos, "extra tokens at end of #endif");
                }
                eat_pp_directive();
        }
 
        pp_conditional_t *conditional = conditional_stack;
        if (conditional == NULL) {
-               errorf(&pp_token.base.source_position, "#endif without prior #if");
+               errorf(&pp_token.base.pos, "#endif without prior #if");
                return;
        }
 
@@ -2293,7 +2328,7 @@ static void parse_pragma_directive(void)
        }
 
        if (pp_token.kind != T_IDENTIFIER) {
-               warningf(WARN_UNKNOWN_PRAGMAS, &pp_token.base.source_position,
+               warningf(WARN_UNKNOWN_PRAGMAS, &pp_token.base.pos,
                         "expected identifier after #pragma");
                eat_pp_directive();
                return;
@@ -2321,13 +2356,13 @@ static void parse_pragma_directive(void)
                        }
                        if (value == STDC_VALUE_UNKNOWN) {
                                kind = STDC_UNKNOWN;
-                               errorf(&pp_token.base.source_position, "bad STDC pragma argument");
+                               errorf(&pp_token.base.pos, "bad STDC pragma argument");
                        }
                }
        }
        eat_pp_directive();
        if (kind == STDC_UNKNOWN) {
-               warningf(WARN_UNKNOWN_PRAGMAS, &pp_token.base.source_position,
+               warningf(WARN_UNKNOWN_PRAGMAS, &pp_token.base.pos,
                         "encountered unknown #pragma");
        }
 }
@@ -2342,12 +2377,12 @@ static void parse_line_directive(void)
                long const line = strtol(pp_token.literal.string.begin, &end, 0);
                if (*end == '\0') {
                        /* use offset -1 as this is about the next line */
-                       input.position.lineno = line - 1;
+                       input.pos.lineno = line - 1;
                        /* force output of line */
-                       input.output_line = input.position.lineno - 20;
+                       input.output_line = input.pos.lineno - 20;
                } else {
                        if (!skip_mode) {
-                               errorf(&input.position, "'%S' is not a valid line number",
+                               errorf(&input.pos, "'%S' is not a valid line number",
                                           &pp_token.literal.string);
                        }
                }
@@ -2357,8 +2392,8 @@ static void parse_line_directive(void)
        }
        if (pp_token.kind == T_STRING_LITERAL
            && pp_token.literal.string.encoding == STRING_ENCODING_CHAR) {
-               input.position.input_name       = pp_token.literal.string.begin;
-               input.position.is_system_header = false;
+               input.pos.input_name       = pp_token.literal.string.begin;
+               input.pos.is_system_header = false;
                next_input_token();
 
                /* attempt to parse numeric flags as outputted by gcc preprocessor */
@@ -2372,7 +2407,7 @@ static void parse_line_directive(void)
                         * currently we're only interested in "3"
                         */
                        if (streq(pp_token.literal.string.begin, "3")) {
-                               input.position.is_system_header = true;
+                               input.pos.is_system_header = true;
                        }
                        next_input_token();
                }
@@ -2391,7 +2426,7 @@ static void parse_error_directive(void)
        bool const old_resolve_escape_sequences = resolve_escape_sequences;
        resolve_escape_sequences = false;
 
-       source_position_t const pos = pp_token.base.source_position;
+       position_t const pos = pp_token.base.pos;
        do {
                if (info.had_whitespace && obstack_object_size(&pp_obstack) != 0)
                        obstack_1grow(&pp_obstack, ' ');
@@ -2462,7 +2497,7 @@ line_directive:
        } else {
 skip:
                if (!skip_mode) {
-                       errorf(&pp_token.base.source_position, "invalid preprocessing directive #%K", &pp_token);
+                       errorf(&pp_token.base.pos, "invalid preprocessing directive #%K", &pp_token);
                }
                eat_pp_directive();
        }
@@ -2519,7 +2554,7 @@ restart:
 
                                        if (next_token == '(') {
                                                if (current_expansion == NULL)
-                                                       expansion_pos = pp_token.base.source_position;
+                                                       expansion_pos = pp_token.base.pos;
                                                next_preprocessing_token();
                                                assert(pp_token.kind == '(');
 
@@ -2541,7 +2576,7 @@ restart:
                                        }
                                } else {
                                        if (current_expansion == NULL)
-                                               expansion_pos = pp_token.base.source_position;
+                                               expansion_pos = pp_token.base.pos;
                                        start_expanding(pp_definition);
                                        goto restart;
                                }
@@ -2569,7 +2604,7 @@ restart:
                        finish_current_argument();
                        current_call->expand_pos++;
                        if (current_call->expand_pos >= current_call->n_parameters) {
-                               errorf(&pp_token.base.source_position,
+                               errorf(&pp_token.base.pos,
                                           "too many arguments passed for macro '%Y'",
                                           current_call->symbol);
                                current_argument = NULL;
@@ -2637,7 +2672,7 @@ static void append_env_paths(searchpath_t *paths, const char *envvar)
                        /* skip : */
                        if (*begin == ':')
                                ++begin;
-               } while(*c != '\0');
+               } while (*c != '\0');
        }
 }
 
@@ -2664,7 +2699,7 @@ static void setup_include_path(void)
 
 static void input_error(unsigned const delta_lines, unsigned const delta_cols, char const *const message)
 {
-       source_position_t pos = pp_token.base.source_position;
+       position_t pos = pp_token.base.pos;
        pos.lineno += delta_lines;
        pos.colno  += delta_cols;
        errorf(&pos, "%s", message);