diff --git a/src/acme.c b/src/acme.c
index 5e2190e..53510ad 100644
--- a/src/acme.c
+++ b/src/acme.c
@@ -349,7 +349,7 @@ static void perform_pass(void)
 	// Process toplevel files
 	for (ii = 0; ii < toplevel_src_count; ++ii) {
 		if ((fd = fopen(toplevel_sources_plat[ii], FILE_READBINARY))) {
-			input_parse_and_close_platform_file(toplevel_sources_plat[ii], fd);
+			parse_and_close_platform_file(fd, toplevel_sources_plat[ii]);
 		} else {
 			fprintf(stderr, "Error: Cannot open toplevel file \"%s\".\n", toplevel_sources_plat[ii]);
 			if (toplevel_sources_plat[ii][0] == '-')
diff --git a/src/global.c b/src/global.c
index 4f91dff..eb7be59 100644
--- a/src/global.c
+++ b/src/global.c
@@ -430,6 +430,32 @@ int parse_optional_block(void)
 	return TRUE;
 }
 
+// parse a whole source code file
+// file name must be given in platform style, i.e.
+// "directory/basename.extension" on linux,
+// "directory.basename/extension" on RISC OS, etc.
+// and the pointer must remain valid forever!
+void parse_and_close_platform_file(FILE *fd, const char *eternal_plat_filename)
+{
+	struct inputchange_buf	icb;
+
+	// be verbose
+	if (config.process_verbosity >= 3)
+		printf("Parsing source file \"%s\".\n", eternal_plat_filename);
+	// set up new input
+	inputchange_new_file(&icb, fd, eternal_plat_filename);
+	// parse block and check end reason
+	parse_until_eob_or_eof();
+	if (GotByte != CHAR_EOF)
+		Throw_error("Expected EOF, found '}' instead." );
+	// close sublevel src
+	// (this looks like we could just use "fd" as arg, but maybe the file
+	// has been replaced with a different one in the meantime...)
+	fclose(input_now->src.fd);
+	// restore outer input
+	inputchange_back(&icb);
+}
+
 
 // Error handling
 
diff --git a/src/global.h b/src/global.h
index c483e92..d2fad49 100644
--- a/src/global.h
+++ b/src/global.h
@@ -190,8 +190,15 @@ extern void parse_until_eob_or_eof(void);
 // Don't forget to call EnsureEOL() afterwards.
 extern int parse_optional_block(void);
 
+// parse a whole source code file
+// file name must be given in platform style, i.e.
+// "directory/basename.extension" on linux,
+// "directory.basename/extension" on RISC OS, etc.
+// and the pointer must remain valid forever!
+extern void parse_and_close_platform_file(FILE *fd, const char *eternal_plat_filename);
+
 // generate a debug/info/warning/error message
-void throw_message(enum debuglevel level, const char msg[]);
+extern void throw_message(enum debuglevel level, const char msg[]);
 
 // output a warning (something looks wrong, like "label name starts with shift-space character")
 #define Throw_warning(msg)	throw_message(DEBUGLEVEL_WARNING, msg)
diff --git a/src/input.c b/src/input.c
index 008db22..d45b6f6 100644
--- a/src/input.c
+++ b/src/input.c
@@ -46,43 +46,6 @@ char		GotByte;			// last byte read (processed)
 
 // functions
 
-// parse a whole source code file
-// file name must be given in platform style, i.e.
-// "directory/basename.extension" on linux,
-// "directory.basename/extension" on RISC OS, etc.
-// and the pointer must remain valid forever!
-void input_parse_and_close_platform_file(const char *eternal_plat_filename, FILE *fd)
-{
-	struct input	new_input,
-			*outer_input;
-
-	// be verbose
-	if (config.process_verbosity >= 3)
-		printf("Parsing source file \"%s\".\n", eternal_plat_filename);
-	// set up new input
-	new_input.plat_pathref_filename		= eternal_plat_filename;
-	new_input.location.plat_filename	= eternal_plat_filename;
-	new_input.location.line_number		= 1;
-	new_input.source		= INPUTSRC_FILE;
-	new_input.state			= INPUTSTATE_SOF;
-	new_input.src.fd		= fd;
-	// remember where outer input struct is
-	outer_input = input_now;
-	// activate new input struct
-	input_now = &new_input;
-	// parse block and check end reason
-	parse_until_eob_or_eof();
-	if (GotByte != CHAR_EOF)
-		Throw_error("Expected EOF, found '}' instead." );
-	// close sublevel src
-	// (this looks like we could just use "fd" as arg, but maybe the file
-	// has been replaced with a different one in the meantime...)
-	fclose(input_now->src.fd);
-	// restore outer input struct
-	input_now = outer_input;
-}
-
-
 // remember source code character for report generator
 #define HEXBUFSIZE	9	// actually, 4+1 is enough, but for systems without snprintf(), let's be extra-safe.
 #define IF_WANTED_REPORT_SRCCHAR(c)	do { if (report->fd) report_srcchar(c); } while(0)
@@ -874,6 +837,34 @@ int input_read_output_filename(void)
 }
 
 
+// "input change" stuff:
+
+// save current input struct in buffer, then switch input to new source code file
+void inputchange_new_file(struct inputchange_buf *icb, FILE *fd, const char *eternal_plat_filename)
+{
+	// TODO: in future, really buffer old data here! (instead of storing new data and changing pointer)
+	// setup new input
+	icb->new_input.plat_pathref_filename	= eternal_plat_filename;
+	icb->new_input.location.plat_filename	= eternal_plat_filename;
+	icb->new_input.location.line_number	= 1;
+	icb->new_input.source		= INPUTSRC_FILE;
+	icb->new_input.state		= INPUTSTATE_SOF;
+	icb->new_input.src.fd		= fd;
+	// remember where outer input struct is
+	icb->outer_input = input_now;
+	// activate new input
+	icb->gb = GotByte;
+	input_now = &icb->new_input;
+}
+
+// restore input struct from buffer
+void inputchange_back(struct inputchange_buf *icb)
+{
+	input_now = icb->outer_input;
+	GotByte = icb->gb;
+}
+
+
 // "include path" stuff:
 
 // ring list struct for "include path items"
diff --git a/src/input.h b/src/input.h
index c5901e6..96a5367 100644
--- a/src/input.h
+++ b/src/input.h
@@ -13,7 +13,7 @@
 
 // type definitions
 
-// values for input component "src.state"
+// values for input component "src.state" (FIXME - try to move this into .c file!)
 enum inputstate {
 	INPUTSTATE_SOF,		// start of file (check for hashbang)
 	INPUTSTATE_NORMAL,	// everything's fine
@@ -71,13 +71,6 @@ extern char		GotByte;	// last byte read (processed)
 
 // Prototypes
 
-// parse a whole source code file
-// file name must be given in platform style, i.e.
-// "directory/basename.extension" on linux,
-// "directory.basename/extension" on RISC OS, etc.
-// and the pointer must remain valid forever!
-extern void input_parse_and_close_platform_file(const char *eternal_plat_filename, FILE *fd);
-
 // get next byte from currently active byte source in shortened high-level
 // format. When inside quotes, use input_quoted_to_dynabuf() instead!
 extern char GetByte(void);
@@ -167,6 +160,22 @@ extern int input_expect(int chr);
 extern bits input_get_force_bit(void);
 
 
+// "input change" stuff:
+
+// treat this struct as opaque, its components should only be referenced by inputchange_* functions!
+struct inputchange_buf {
+	struct input	new_input,
+			*outer_input;
+	char		gb;	// buffer for GotByte
+};
+
+// save current input struct in buffer, then switch input to new source code file
+extern void inputchange_new_file(struct inputchange_buf *icb, FILE *fd, const char *eternal_plat_filename);
+
+// restore input struct from buffer
+extern void inputchange_back(struct inputchange_buf *icb);
+
+
 // "include path" stuff:
 
 // add entry
diff --git a/src/pseudoopcodes.c b/src/pseudoopcodes.c
index 8243f83..ccaa36c 100644
--- a/src/pseudoopcodes.c
+++ b/src/pseudoopcodes.c
@@ -897,7 +897,6 @@ static enum eos po_source(void)	// now GotByte = illegal char
 	struct filespecflags	flags;
 	FILE		*stream;
 	const char	*eternal_plat_filename;
-	char		local_gotbyte;
 
 	// enter new nesting level
 	// quit program if recursion too deep
@@ -912,9 +911,7 @@ static enum eos po_source(void)	// now GotByte = illegal char
 	stream = includepaths_open_ro(&flags);
 	if (stream) {
 		eternal_plat_filename = dynabuf_get_copy(GlobalDynaBuf);
-		local_gotbyte = GotByte;	// CAUTION - ugly kluge
-		input_parse_and_close_platform_file(eternal_plat_filename, stream);
-		GotByte = local_gotbyte;	// CAUTION - ugly kluge
+		parse_and_close_platform_file(stream, eternal_plat_filename);
 	}
 	// leave nesting level
 	++sanity.source_recursions_left;
diff --git a/src/version.h b/src/version.h
index a96aff9..a3aa8c1 100644
--- a/src/version.h
+++ b/src/version.h
@@ -9,7 +9,7 @@
 
 #define RELEASE		"0.97"		// update before release	FIXME
 #define CODENAME	"Zem"		// update before release
-#define CHANGE_DATE	"15 Jul"	// update before release	FIXME
+#define CHANGE_DATE	"16 Jul"	// update before release	FIXME
 #define CHANGE_YEAR	"2024"		// update before release
 //#define HOME_PAGE	"http://home.pages.de/~mac_bacon/smorbrod/acme/"
 #define HOME_PAGE	"http://sourceforge.net/p/acme-crossass/"	// FIXME