+ const char *end = file->buf + file->size;
+ while(pos < end) {
+ /* Lookup the character */
+ int size = 1;
+ int c = *pos;
+ /* Is this a trigraph? */
+ if (file->trigraphs &&
+ (c == '?') && ((end - pos) >= 3) && (pos[1] == '?'))
+ {
+ switch(pos[2]) {
+ case '=': c = '#'; break;
+ case '/': c = '\\'; break;
+ case '\'': c = '^'; break;
+ case '(': c = '['; break;
+ case ')': c = ']'; break;
+ case '!': c = '!'; break;
+ case '<': c = '{'; break;
+ case '>': c = '}'; break;
+ case '-': c = '~'; break;
+ }
+ if (c != '?') {
+ size = 3;
+ }
+ }
+ /* Is this an escaped newline? */
+ if (file->join_lines &&
+ (c == '\\') && (pos + size < end) && ((pos[1] == '\n') || ((pos[1] == '\r') && (pos[2] == '\n'))))
+ {
+ int cr_offset = ((pos[1] == '\r') && (pos[2] == '\n'))?1:0;
+ /* At the start of a line just eat it */
+ if (pos == file->pos) {
+ file->line++;
+ file->report_line++;
+ file->line_start = pos + size + 1 + cr_offset;
+ }
+ pos += size + 1 + cr_offset;
+ }
+ /* Do I need to ga any farther? */
+ else if (index == 0) {
+ break;
+ }
+ /* Process a normal character */
+ else {
+ pos += size;
+ index -= 1;
+ }
+ }
+ return pos;
+}
+
+static int get_char(struct file_state *file, const char *pos)
+{
+ const char *end = file->buf + file->size;
+ int c;
+ c = -1;
+ pos = next_char(file, pos, 0);
+ if (pos < end) {
+ /* Lookup the character */
+ c = *pos;
+ /* If it is a trigraph get the trigraph value */
+ if (file->trigraphs &&
+ (c == '?') && ((end - pos) >= 3) && (pos[1] == '?'))
+ {
+ switch(pos[2]) {
+ case '=': c = '#'; break;
+ case '/': c = '\\'; break;
+ case '\'': c = '^'; break;
+ case '(': c = '['; break;
+ case ')': c = ']'; break;
+ case '!': c = '!'; break;
+ case '<': c = '{'; break;
+ case '>': c = '}'; break;
+ case '-': c = '~'; break;
+ }
+ }
+ }
+ return c;
+}
+
+static void eat_chars(struct file_state *file, const char *targ)
+{
+ const char *pos = file->pos;
+ while(pos < targ) {
+ /* Do we have a newline? */
+ if (pos[0] == '\n') {
+ file->line++;
+ file->report_line++;
+ file->line_start = pos + 1;
+ }
+ pos++;
+ }
+ file->pos = pos;
+}
+
+
+static size_t char_strlen(struct file_state *file, const char *src, const char *end)
+{
+ size_t len;
+ len = 0;
+ while(src < end) {
+ src = next_char(file, src, 1);
+ len++;
+ }
+ return len;
+}
+
+static void char_strcpy(char *dest,
+ struct file_state *file, const char *src, const char *end)
+{
+ while(src < end) {
+ int c;
+ c = get_char(file, src);
+ src = next_char(file, src, 1);
+ *dest++ = c;
+ }
+}
+
+static char *char_strdup(struct file_state *file,
+ const char *start, const char *end, const char *id)
+{
+ char *str;
+ size_t str_len;
+ str_len = char_strlen(file, start, end);
+ str = xcmalloc(str_len + 1, id);
+ char_strcpy(str, file, start, end);
+ str[str_len] = '\0';
+ return str;
+}
+
+static const char *after_digits(struct file_state *file, const char *ptr)
+{
+ while(digitp(get_char(file, ptr))) {
+ ptr = next_char(file, ptr, 1);