+static void print_line_directive(const source_position_t *pos, const char *add);
+
+static bool open_input(const char *filename)
+{
+ FILE *file = fopen(filename, "r");
+ if (file == NULL)
+ return false;
+
+ input.file = file;
+ input.bufend = NULL;
+ input.bufpos = NULL;
+ input.had_non_space = false;
+ input.position.input_name = filename;
+ input.position.lineno = 1;
+
+ /* indicate that we're at a new input */
+ print_line_directive(&input.position, input_stack != NULL ? "1" : NULL);
+
+ counted_newlines = 0;
+ counted_spaces = 0;
+
+ /* read first char and first token */
+ next_char();
+ next_preprocessing_token();
+
+ return true;
+}
+
+static void close_input(void)
+{
+ /* ensure we have a newline at EOF */
+ if (input.had_non_space) {
+ fputc('\n', out);
+ }
+
+ assert(input.file != NULL);
+
+ fclose(input.file);
+ input.file = NULL;
+ input.bufend = NULL;
+ input.bufpos = NULL;
+ input.c = EOF;
+}
+
+static void push_input(void)
+{
+ pp_input_t *saved_input
+ = obstack_alloc(&input_obstack, sizeof(*saved_input));
+
+ memcpy(saved_input, &input, sizeof(*saved_input));
+
+ /* adjust buffer positions */
+ if (input.bufpos != NULL)
+ saved_input->bufpos = saved_input->buf + (input.bufpos - input.buf);
+ if (input.bufend != NULL)
+ saved_input->bufend = saved_input->buf + (input.bufend - input.buf);
+
+ saved_input->parent = input_stack;
+ input_stack = saved_input;
+ ++n_inputs;
+}
+
+static void pop_restore_input(void)
+{
+ assert(n_inputs > 0);
+ assert(input_stack != NULL);
+
+ pp_input_t *saved_input = input_stack;
+
+ memcpy(&input, saved_input, sizeof(input));
+ input.parent = NULL;
+
+ /* adjust buffer positions */
+ if (saved_input->bufpos != NULL)
+ input.bufpos = input.buf + (saved_input->bufpos - saved_input->buf);
+ if (saved_input->bufend != NULL)
+ input.bufend = input.buf + (saved_input->bufend - saved_input->buf);
+
+ input_stack = saved_input->parent;
+ obstack_free(&input_obstack, saved_input);
+ --n_inputs;
+}