-static
-int replace_trigraph(lexer_t *this)
-{
-#define MATCH_TRIGRAPH(ch,replacement) \
- case ch: \
- this->c = replacement; \
- return 1;
-
- switch(this->c) {
- MATCH_TRIGRAPH('=', '#')
- MATCH_TRIGRAPH('(', '[')
- MATCH_TRIGRAPH('/', '\\')
- MATCH_TRIGRAPH(')', ']')
- MATCH_TRIGRAPH('\'', '^')
- MATCH_TRIGRAPH('<', '{')
- MATCH_TRIGRAPH('!', '|')
- MATCH_TRIGRAPH('>', '}')
- MATCH_TRIGRAPH('-', '~')
+static inline void next_char(void);
+
+#define MATCH_NEWLINE(code) \
+ case '\r': \
+ next_char(); \
+ if(c == '\n') { \
+ next_char(); \
+ } \
+ lexer_token.source_position.linenr++; \
+ code; \
+ case '\n': \
+ next_char(); \
+ lexer_token.source_position.linenr++; \
+ code;
+
+static inline void eat(char c_type)
+{
+ assert(c == c_type);
+ next_char();
+}
+
+static void maybe_concat_lines(void)
+{
+ eat('\\');
+
+ switch(c) {
+ MATCH_NEWLINE(return;)
+
+ default:
+ break;
+ }
+
+ put_back(c);
+ c = '\\';
+}
+
+static inline void next_char(void)
+{
+ next_real_char();
+
+ /* filter trigraphs */
+ if(UNLIKELY(c == '\\')) {
+ maybe_concat_lines();
+ goto end_of_next_char;
+ }
+
+ if(LIKELY(c != '?'))
+ goto end_of_next_char;
+
+ next_real_char();
+ if(LIKELY(c != '?')) {
+ put_back(c);
+ c = '?';
+ goto end_of_next_char;
+ }
+
+ next_real_char();
+ switch(c) {
+ case '=': c = '#'; break;
+ case '(': c = '['; break;
+ case '/': c = '\\'; maybe_concat_lines(); break;
+ case ')': c = ']'; break;
+ case '\'': c = '^'; break;
+ case '<': c = '{'; break;
+ case '!': c = '|'; break;
+ case '>': c = '}'; break;
+ case '-': c = '~'; break;