From 19cff41eb4261b20374058f16807a229af46f304 Mon Sep 17 00:00:00 2001
From: Clifford Wolf <clifford@clifford.at>
Date: Sat, 23 Aug 2014 15:03:55 +0200
Subject: [PATCH] Changed frontend-api from FILE to std::istream

---
 backends/intersynth/intersynth.cc      |  8 +++---
 frontends/ilang/ilang_frontend.cc      |  5 ++--
 frontends/ilang/ilang_frontend.h       |  5 ++--
 frontends/ilang/lexer.l                |  5 +++-
 frontends/ilang/parser.y               |  1 +
 frontends/liberty/liberty.cc           |  4 +--
 frontends/verilog/lexer.l              |  3 ++
 frontends/verilog/parser.y             |  1 +
 frontends/verilog/preproc.cc           | 31 ++++++++++----------
 frontends/verilog/verilog_frontend.cc  | 12 ++++----
 frontends/verilog/verilog_frontend.h   |  5 +++-
 frontends/vhdl2verilog/vhdl2verilog.cc |  8 +++---
 kernel/register.cc                     | 23 +++++++++------
 kernel/register.h                      |  8 +++---
 kernel/yosys.h                         |  1 +
 passes/cmds/show.cc                    |  8 +++---
 passes/cmds/write_file.cc              |  4 +--
 passes/techmap/dfflibmap.cc            |  7 +++--
 passes/techmap/extract.cc              |  9 +++---
 passes/techmap/libparse.cc             | 40 +++++++++++++++-----------
 passes/techmap/libparse.h              |  4 +--
 passes/techmap/techmap.cc              | 13 ++++-----
 22 files changed, 116 insertions(+), 89 deletions(-)

diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc
index 97ead3c64..8502d90fc 100644
--- a/backends/intersynth/intersynth.cc
+++ b/backends/intersynth/intersynth.cc
@@ -101,13 +101,13 @@ struct IntersynthBackend : public Backend {
 		log("Output filename: %s\n", filename.c_str());
 
 		for (auto filename : libfiles) {
-			FILE *f = fopen(filename.c_str(), "rt");
-			if (f == NULL)
+			std::ifstream f;
+			f.open(filename.c_str());
+			if (f.fail())
 				log_error("Can't open lib file `%s'.\n", filename.c_str());
 			RTLIL::Design *lib = new RTLIL::Design;
-			Frontend::frontend_call(lib, f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
+			Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
 			libs.push_back(lib);
-			fclose(f);
 		}
 
 		if (libs.size() > 0)
diff --git a/frontends/ilang/ilang_frontend.cc b/frontends/ilang/ilang_frontend.cc
index 2d4b99c52..f6f926db1 100644
--- a/frontends/ilang/ilang_frontend.cc
+++ b/frontends/ilang/ilang_frontend.cc
@@ -45,15 +45,16 @@ struct IlangFrontend : public Frontend {
 		log("representation of a design in yosys's internal format.)\n");
 		log("\n");
 	}
-	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+	virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
 	{
 		log_header("Executing ILANG frontend.\n");
 		extra_args(f, filename, args, 1);
 		log("Input filename: %s\n", filename.c_str());
 
+		ILANG_FRONTEND::lexin = f;
 		ILANG_FRONTEND::current_design = design;
 		rtlil_frontend_ilang_yydebug = false;
-		rtlil_frontend_ilang_yyrestart(f);
+		rtlil_frontend_ilang_yyrestart(NULL);
 		rtlil_frontend_ilang_yyparse();
 		rtlil_frontend_ilang_yylex_destroy();
 	}
diff --git a/frontends/ilang/ilang_frontend.h b/frontends/ilang/ilang_frontend.h
index 317ec0d51..b04d6c512 100644
--- a/frontends/ilang/ilang_frontend.h
+++ b/frontends/ilang/ilang_frontend.h
@@ -26,12 +26,11 @@
 #define ILANG_FRONTEND_H
 
 #include "kernel/yosys.h"
-#include <stdio.h>
 
 YOSYS_NAMESPACE_BEGIN
 
 namespace ILANG_FRONTEND {
-	void ilang_frontend(FILE *f, RTLIL::Design *design);
+	extern std::istream *lexin;
 	extern RTLIL::Design *current_design;
 }
 
@@ -42,7 +41,7 @@ int rtlil_frontend_ilang_yylex(void);
 void rtlil_frontend_ilang_yyerror(char const *s);
 void rtlil_frontend_ilang_yyrestart(FILE *f);
 int rtlil_frontend_ilang_yyparse(void);
-void rtlil_frontend_ilang_yylex_destroy(void);
+int rtlil_frontend_ilang_yylex_destroy(void);
 int rtlil_frontend_ilang_yyget_lineno(void);
 
 #endif
diff --git a/frontends/ilang/lexer.l b/frontends/ilang/lexer.l
index f3bdeb1a4..4109cd4bc 100644
--- a/frontends/ilang/lexer.l
+++ b/frontends/ilang/lexer.l
@@ -29,9 +29,12 @@
 #pragma clang diagnostic ignored "-Wdeprecated-register"
 #endif
 
-#include "kernel/rtlil.h"
+#include "ilang_frontend.h"
 #include "parser.tab.h"
 
+#define YY_INPUT(buf,result,max_size) \
+        result = ILANG_FRONTEND::lexin->readsome(buf, max_size);
+
 %}
 
 %option yylineno
diff --git a/frontends/ilang/parser.y b/frontends/ilang/parser.y
index e1ef39a55..a5cc06898 100644
--- a/frontends/ilang/parser.y
+++ b/frontends/ilang/parser.y
@@ -27,6 +27,7 @@
 #include "ilang_frontend.h"
 YOSYS_NAMESPACE_BEGIN
 namespace ILANG_FRONTEND {
+	std::istream *lexin;
 	RTLIL::Design *current_design;
 	RTLIL::Module *current_module;
 	RTLIL::Wire *current_wire;
diff --git a/frontends/liberty/liberty.cc b/frontends/liberty/liberty.cc
index 83bfce371..a9ab022a4 100644
--- a/frontends/liberty/liberty.cc
+++ b/frontends/liberty/liberty.cc
@@ -430,7 +430,7 @@ struct LibertyFrontend : public Frontend {
 		log("        set the specified attribute (to the value 1) on all loaded modules\n");
 		log("\n");
 	}
-	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+	virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
 	{
 		bool flag_lib = false;
 		bool flag_ignore_redef = false;
@@ -467,7 +467,7 @@ struct LibertyFrontend : public Frontend {
 		}
 		extra_args(f, filename, args, argidx);
 
-		LibertyParser parser(f);
+		LibertyParser parser(*f);
 		int cell_count = 0;
 
 		for (auto cell : parser.ast->children)
diff --git a/frontends/verilog/lexer.l b/frontends/verilog/lexer.l
index f79f81a9c..c9302aba8 100644
--- a/frontends/verilog/lexer.l
+++ b/frontends/verilog/lexer.l
@@ -63,6 +63,9 @@ YOSYS_NAMESPACE_END
 	frontend_verilog_yylval.string = new std::string(std::string("\\") + yytext); \
 	return TOK_ID;
 
+#define YY_INPUT(buf,result,max_size) \
+	result = lexin->readsome(buf, max_size);
+
 %}
 
 %option yylineno
diff --git a/frontends/verilog/parser.y b/frontends/verilog/parser.y
index 3512538ca..a9f69a49c 100644
--- a/frontends/verilog/parser.y
+++ b/frontends/verilog/parser.y
@@ -58,6 +58,7 @@ namespace VERILOG_FRONTEND {
 	bool do_not_require_port_stubs;
 	bool default_nettype_wire;
 	bool sv_mode;
+	std::istream *lexin;
 }
 YOSYS_NAMESPACE_END
 
diff --git a/frontends/verilog/preproc.cc b/frontends/verilog/preproc.cc
index ae139741a..f83433219 100644
--- a/frontends/verilog/preproc.cc
+++ b/frontends/verilog/preproc.cc
@@ -193,7 +193,7 @@ static std::string next_token(bool pass_newline = false)
 	return token;
 }
 
-static void input_file(FILE *f, std::string filename)
+static void input_file(std::istream &f, std::string filename)
 {
 	char buffer[513];
 	int rc;
@@ -202,14 +202,14 @@ static void input_file(FILE *f, std::string filename)
 	auto it = input_buffer.begin();
 
 	input_buffer.insert(it, "`file_push " + filename + "\n");
-	while ((rc = fread(buffer, 1, sizeof(buffer)-1, f)) > 0) {
+	while ((rc = f.readsome(buffer, sizeof(buffer)-1)) > 0) {
 		buffer[rc] = 0;
 		input_buffer.insert(it, buffer);
 	}
 	input_buffer.insert(it, "\n`file_pop\n");
 }
 
-std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::map<std::string, std::string> pre_defines_map, const std::list<std::string> include_dirs)
+std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map<std::string, std::string> pre_defines_map, const std::list<std::string> include_dirs)
 {
 	std::set<std::string> defines_with_args;
 	std::map<std::string, std::string> defines_map(pre_defines_map);
@@ -288,27 +288,28 @@ std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::m
 				else
 					fn = fn.substr(0, pos) + fn.substr(pos+1);
 			}
-			FILE *fp = fopen(fn.c_str(), "r");
-			if (fp == NULL && fn.size() > 0 && fn[0] != '/' && filename.find('/') != std::string::npos) {
+			std::ifstream ff;
+			ff.clear();
+			ff.open(fn.c_str());
+			if (ff.fail() && fn.size() > 0 && fn[0] != '/' && filename.find('/') != std::string::npos) {
 				// if the include file was not found, it is not given with an absolute path, and the
 				// currently read file is given with a path, then try again relative to its directory
-				std::string fn2 = filename.substr(0, filename.rfind('/')+1) + fn;
-				fp = fopen(fn2.c_str(), "r");
+				ff.clear();
+				ff.open(filename.substr(0, filename.rfind('/')+1) + fn);
 			}
-			if (fp == NULL && fn.size() > 0 && fn[0] != '/') {
+			if (ff.fail() && fn.size() > 0 && fn[0] != '/') {
 				// if the include file was not found and it is not given with an absolute path, then
 				// search it in the include path
 				for (auto incdir : include_dirs) {
-					std::string fn2 = incdir + '/' + fn;
-					fp = fopen(fn2.c_str(), "r");
-					if (fp != NULL) break;
+					ff.clear();
+					ff.open(incdir + '/' + fn);
+					if (!ff.fail()) break;
 				}
 			}
-			if (fp != NULL) {
-				input_file(fp, fn);
-				fclose(fp);
-			} else
+			if (ff.fail())
 				output_code.push_back("`file_notfound " + fn);
+			else
+				input_file(ff, fn);
 			continue;
 		}
 
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 195789086..c63fbb08a 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -136,7 +136,7 @@ struct VerilogFrontend : public Frontend {
 		log("the syntax of the code, rather than to rely on read_verilog for that.\n");
 		log("\n");
 	}
-	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
+	virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
 	{
 		bool flag_dump_ast1 = false;
 		bool flag_dump_ast2 = false;
@@ -269,18 +269,18 @@ struct VerilogFrontend : public Frontend {
 		current_ast = new AST::AstNode(AST::AST_DESIGN);
 		default_nettype_wire = true;
 
-		FILE *fp = f;
+		lexin = f;
 		std::string code_after_preproc;
 
 		if (!flag_nopp) {
-			code_after_preproc = frontend_verilog_preproc(f, filename, defines_map, include_dirs);
+			code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, include_dirs);
 			if (flag_ppdump)
 				log("-- Verilog code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc.c_str());
-			fp = fmemopen((void*)code_after_preproc.c_str(), code_after_preproc.size(), "r");
+			lexin = new std::istringstream(code_after_preproc);
 		}
 
 		frontend_verilog_yyset_lineno(1);
-		frontend_verilog_yyrestart(fp);
+		frontend_verilog_yyrestart(NULL);
 		frontend_verilog_yyparse();
 		frontend_verilog_yylex_destroy();
 
@@ -294,7 +294,7 @@ struct VerilogFrontend : public Frontend {
 		AST::process(design, current_ast, flag_dump_ast1, flag_dump_ast2, flag_dump_vlog, flag_nolatches, flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_ignore_redef, flag_defer, default_nettype_wire);
 
 		if (!flag_nopp)
-			fclose(fp);
+			delete lexin;
 
 		delete current_ast;
 		current_ast = NULL;
diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h
index dac5b3d02..af6495f8f 100644
--- a/frontends/verilog/verilog_frontend.h
+++ b/frontends/verilog/verilog_frontend.h
@@ -50,10 +50,13 @@ namespace VERILOG_FRONTEND
 
 	// running in SystemVerilog mode
 	extern bool sv_mode;
+
+	// lexer input stream
+	extern std::istream *lexin;
 }
 
 // the pre-processor
-std::string frontend_verilog_preproc(FILE *f, std::string filename, const std::map<std::string, std::string> pre_defines_map, const std::list<std::string> include_dirs);
+std::string frontend_verilog_preproc(std::istream &f, std::string filename, const std::map<std::string, std::string> pre_defines_map, const std::list<std::string> include_dirs);
 
 YOSYS_NAMESPACE_END
 
diff --git a/frontends/vhdl2verilog/vhdl2verilog.cc b/frontends/vhdl2verilog/vhdl2verilog.cc
index f0545700a..8b6f62a63 100644
--- a/frontends/vhdl2verilog/vhdl2verilog.cc
+++ b/frontends/vhdl2verilog/vhdl2verilog.cc
@@ -177,11 +177,11 @@ struct Vhdl2verilogPass : public Pass {
 			log_error("Execution of command \"%s\" failed: the shell returned %d\n", command.c_str(), WEXITSTATUS(ret));
 
 		if (out_file.empty()) {
-			f = fopen(stringf("%s/vhdl2verilog_output.v", tempdir_name).c_str(), "rt");
-			if (f == NULL)
+			std::ifstream ff;
+			ff.open(stringf("%s/vhdl2verilog_output.v", tempdir_name).c_str());
+			if (ff.fail())
 				log_error("Can't open vhdl2verilog output file `vhdl2verilog_output.v'.\n");
-			Frontend::frontend_call(design, f, stringf("%s/vhdl2verilog_output.v", tempdir_name), "verilog");
-			fclose(f);
+			Frontend::frontend_call(design, &ff, stringf("%s/vhdl2verilog_output.v", tempdir_name), "verilog");
 		}
 
 		log_header("Removing temp directory `%s':\n", tempdir_name);
diff --git a/kernel/register.cc b/kernel/register.cc
index 95ed0cbd1..5f4e71d1f 100644
--- a/kernel/register.cc
+++ b/kernel/register.cc
@@ -286,20 +286,20 @@ void Frontend::execute(std::vector<std::string> args, RTLIL::Design *design)
 {
 	log_assert(next_args.empty());
 	do {
-		FILE *f = NULL;
+		std::istream *f = NULL;
 		next_args.clear();
 		auto state = pre_execute();
 		execute(f, std::string(), args, design);
 		post_execute(state);
 		args = next_args;
-		fclose(f);
+		delete f;
 	} while (!args.empty());
 }
 
 FILE *Frontend::current_script_file = NULL;
 std::string Frontend::last_here_document;
 
-void Frontend::extra_args(FILE *&f, std::string &filename, std::vector<std::string> args, size_t argidx)
+void Frontend::extra_args(std::istream *&f, std::string &filename, std::vector<std::string> args, size_t argidx)
 {
 	bool called_with_fp = f != NULL;
 
@@ -338,11 +338,16 @@ void Frontend::extra_args(FILE *&f, std::string &filename, std::vector<std::stri
 					break;
 				last_here_document += buffer;
 			}
-			f = fmemopen((void*)last_here_document.c_str(), last_here_document.size(), "r");
+			f = new std::istringstream(last_here_document);
 		} else {
 			if (filename.substr(0, 2) == "+/")
 				filename = proc_share_dirname() + filename.substr(1);
-			f = fopen(filename.c_str(), "r");
+			std::ifstream *ff = new std::ifstream;
+			ff->open(filename.c_str());
+			if (ff->fail())
+				delete ff;
+			else
+				f = ff;
 		}
 		if (f == NULL)
 			log_cmd_error("Can't open input file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
@@ -367,7 +372,7 @@ void Frontend::extra_args(FILE *&f, std::string &filename, std::vector<std::stri
 	// cmd_log_args(args);
 }
 
-void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::string command)
+void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string filename, std::string command)
 {
 	std::vector<std::string> args;
 	char *s = strdup(command.c_str());
@@ -377,7 +382,7 @@ void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filenam
 	frontend_call(design, f, filename, args);
 }
 
-void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::vector<std::string> args)
+void Frontend::frontend_call(RTLIL::Design *design, std::istream *f, std::string filename, std::vector<std::string> args)
 {
 	if (args.size() == 0)
 		return;
@@ -389,9 +394,9 @@ void Frontend::frontend_call(RTLIL::Design *design, FILE *f, std::string filenam
 		frontend_register[args[0]]->execute(f, filename, args, design);
 		frontend_register[args[0]]->post_execute(state);
 	} else if (filename == "-") {
-		FILE *f_stdin = stdin; // workaround for OpenBSD 'stdin' implementation
+		std::istream *f_cin = &std::cin;
 		auto state = frontend_register[args[0]]->pre_execute();
-		frontend_register[args[0]]->execute(f_stdin, "<stdin>", args, design);
+		frontend_register[args[0]]->execute(f_cin, "<stdin>", args, design);
 		frontend_register[args[0]]->post_execute(state);
 	} else {
 		if (!filename.empty())
diff --git a/kernel/register.h b/kernel/register.h
index f2c6ad29e..a49675ed2 100644
--- a/kernel/register.h
+++ b/kernel/register.h
@@ -74,13 +74,13 @@ struct Frontend : Pass
 	virtual void run_register();
 	virtual ~Frontend();
 	virtual void execute(std::vector<std::string> args, RTLIL::Design *design) OVERRIDE FINAL;
-	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
+	virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) = 0;
 
 	static std::vector<std::string> next_args;
-	void extra_args(FILE *&f, std::string &filename, std::vector<std::string> args, size_t argidx);
+	void extra_args(std::istream *&f, std::string &filename, std::vector<std::string> args, size_t argidx);
 
-	static void frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::string command);
-	static void frontend_call(RTLIL::Design *design, FILE *f, std::string filename, std::vector<std::string> args);
+	static void frontend_call(RTLIL::Design *design, std::istream *f, std::string filename, std::string command);
+	static void frontend_call(RTLIL::Design *design, std::istream *f, std::string filename, std::vector<std::string> args);
 };
 
 struct Backend : Pass
diff --git a/kernel/yosys.h b/kernel/yosys.h
index bfadb5ffc..87c99d1f6 100644
--- a/kernel/yosys.h
+++ b/kernel/yosys.h
@@ -47,6 +47,7 @@
 
 #include <sstream>
 #include <fstream>
+#include <istream>
 #include <ostream>
 #include <iostream>
 
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index fc6e972ee..3468eae78 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -720,13 +720,13 @@ struct ShowPass : public Pass {
 		}
 
 		for (auto filename : libfiles) {
-			FILE *f = fopen(filename.c_str(), "rt");
-			if (f == NULL)
+			std::ifstream f;
+			f.open(filename.c_str());
+			if (f.fail())
 				log_error("Can't open lib file `%s'.\n", filename.c_str());
 			RTLIL::Design *lib = new RTLIL::Design;
-			Frontend::frontend_call(lib, f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
+			Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
 			libs.push_back(lib);
-			fclose(f);
 		}
 
 		if (libs.size() > 0)
diff --git a/passes/cmds/write_file.cc b/passes/cmds/write_file.cc
index a7cd7b438..813e215ba 100644
--- a/passes/cmds/write_file.cc
+++ b/passes/cmds/write_file.cc
@@ -41,7 +41,7 @@ struct WriteFileFrontend : public Frontend {
 		log("    EOT\n");
 		log("\n");
 	}
-	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*)
+	virtual void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design*)
 	{
 		bool append_mode = false;
 		std::string output_filename;
@@ -67,7 +67,7 @@ struct WriteFileFrontend : public Frontend {
 		char buffer[64 * 1024];
 		size_t bytes;
 
-		while (0 < (bytes = fread(buffer, 1, sizeof(buffer), f)))
+		while (0 < (bytes = f->readsome(buffer, sizeof(buffer))))
 			fwrite(buffer, bytes, 1, of);
 
 		fclose(of);
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 6ce771ac4..7e39040c4 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -463,11 +463,12 @@ struct DfflibmapPass : public Pass {
 		if (liberty_file.empty())
 			log_cmd_error("Missing `-liberty liberty_file' option!\n");
 
-		FILE *f = fopen(liberty_file.c_str(), "r");
-		if (f == NULL)
+		std::ifstream f;
+		f.open(liberty_file.c_str());
+		if (f.fail())
 			log_cmd_error("Can't open liberty file `%s': %s\n", liberty_file.c_str(), strerror(errno));
 		LibertyParser libparser(f);
-		fclose(f);
+		f.close();
 
 		find_cell(libparser.ast, "$_DFF_N_", false, false, false, false);
 		find_cell(libparser.ast, "$_DFF_P_", true, false, false, false);
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index eaa0f9fa3..221e9e49d 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -609,13 +609,14 @@ struct ExtractPass : public Pass {
 				}
 				else
 				{
-					FILE *f = fopen(filename.c_str(), "rt");
-					if (f == NULL) {
+					std::ifstream f;
+					f.open(filename.c_str());
+					if (f.fail()) {
 						delete map;
 						log_cmd_error("Can't open map file `%s'.\n", filename.c_str());
 					}
-					Frontend::frontend_call(map, f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
-					fclose(f);
+					Frontend::frontend_call(map, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog");
+					f.close();
 
 					if (filename.size() <= 3 || filename.substr(filename.size()-3) != ".il") {
 						Pass::call(map, "proc");
diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc
index 2ff551537..612fa1117 100644
--- a/passes/techmap/libparse.cc
+++ b/passes/techmap/libparse.cc
@@ -21,6 +21,10 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <istream>
+#include <fstream>
+#include <iostream>
+
 #ifndef FILTERLIB
 #include "kernel/log.h"
 #endif
@@ -85,19 +89,19 @@ int LibertyParser::lexer(std::string &str)
 	int c;
 
 	do {
-		c = fgetc(f);
+		c = f.get();
 	} while (c == ' ' || c == '\t' || c == '\r');
 
 	if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.') {
 		str = c;
 		while (1) {
-			c = fgetc(f);
+			c = f.get();
 			if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_' || c == '-' || c == '+' || c == '.')
 				str += c;
 			else
 				break;
 		}
-		ungetc(c, f);
+		f.unget();
 		// fprintf(stderr, "LEX: identifier >>%s<<\n", str.c_str());
 		return 'v';
 	}
@@ -105,7 +109,7 @@ int LibertyParser::lexer(std::string &str)
 	if (c == '"') {
 		str = c;
 		while (1) {
-			c = fgetc(f);
+			c = f.get();
 			if (c == '\n')
 				line++;
 			str += c;
@@ -117,34 +121,34 @@ int LibertyParser::lexer(std::string &str)
 	}
 
 	if (c == '/') {
-		c = fgetc(f);
+		c = f.get();
 		if (c == '*') {
 			int last_c = 0;
 			while (c > 0 && (last_c != '*' || c != '/')) {
 				last_c = c;
-				c = fgetc(f);
+				c = f.get();
 				if (c == '\n')
 					line++;
 			}
 			return lexer(str);
 		} else if (c == '/') {
 			while (c > 0 && c != '\n')
-				c = fgetc(f);
+				c = f.get();
 			line++;
 			return lexer(str);
 		}
-		ungetc(c, f);
+		f.unget();
 		// fprintf(stderr, "LEX: char >>/<<\n");
 		return '/';
 	}
 
 	if (c == '\\') {
-		c = fgetc(f);
+		c = f.get();
 		if (c == '\r')
-			c = fgetc(f);
+			c = f.get();
 		if (c == '\n')
 			return lexer(str);
-		ungetc(c, f);
+		f.unget();
 		return '\\';
 	}
 
@@ -608,16 +612,20 @@ int main(int argc, char **argv)
 		}
 	}
 
-	FILE *f = stdin;
+	std::istream *f = &std::cin;
+
 	if (argc == 3) {
-		f = fopen(argv[2], "r");
-		if (f == NULL) {
+		std::ifstream *ff = new std::ifstream;
+		ff->open(argv[2]);
+		if (ff->fail()) {
+			delete ff;
 			fprintf(stderr, "Can't open liberty file `%s'.\n", argv[2]);
 			usage();
 		}
+		f = ff;
 	}
 
-	LibertyParser parser(f);
+	LibertyParser parser(*f);
 	if (parser.ast) {
 		if (flag_verilogsim)
 			gen_verilogsim(parser.ast);
@@ -626,7 +634,7 @@ int main(int argc, char **argv)
 	}
 
 	if (argc == 3)
-		fclose(f);
+		delete f;
 
 	return 0;
 }
diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h
index eff268bbb..247487424 100644
--- a/passes/techmap/libparse.h
+++ b/passes/techmap/libparse.h
@@ -41,10 +41,10 @@ namespace PASS_DFFLIBMAP
 
 	struct LibertyParser
 	{
-		FILE *f;
+		std::istream &f;
 		int line;
 		LibertyAst *ast;
-		LibertyParser(FILE *f) : f(f), line(1), ast(parse()) {}
+		LibertyParser(std::istream &f) : f(f), line(1), ast(parse()) {}
 		~LibertyParser() { if (ast) delete ast; }
 		int lexer(std::string &str);
 		LibertyAst *parse();
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index d9d8ddd6a..beacdfa6f 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -869,9 +869,8 @@ struct TechmapPass : public Pass {
 
 		RTLIL::Design *map = new RTLIL::Design;
 		if (map_files.empty()) {
-			FILE *f = fmemopen(stdcells_code, strlen(stdcells_code), "rt");
-			Frontend::frontend_call(map, f, "<techmap.v>", verilog_frontend);
-			fclose(f);
+			std::istringstream f(stdcells_code);
+			Frontend::frontend_call(map, &f, "<techmap.v>", verilog_frontend);
 		} else
 			for (auto &fn : map_files)
 				if (fn.substr(0, 1) == "%") {
@@ -883,11 +882,11 @@ struct TechmapPass : public Pass {
 						if (!map->has(mod->name))
 							map->add(mod->clone());
 				} else {
-					FILE *f = fopen(fn.c_str(), "rt");
-					if (f == NULL)
+					std::ifstream f;
+					f.open(fn.c_str());
+					if (f.fail())
 						log_cmd_error("Can't open map file `%s'\n", fn.c_str());
-					Frontend::frontend_call(map, f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "ilang" : verilog_frontend);
-					fclose(f);
+					Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "ilang" : verilog_frontend);
 				}
 
 		std::map<RTLIL::IdString, RTLIL::Module*> modules_new;