Go to the documentation of this file.00001 #include <typelib/registry.hh>
00002
00003 #include <CPPLexer.hpp>
00004 #include "typesolver.hh"
00005 #include "import.hh"
00006
00007 #include <fstream>
00008 #include <iostream>
00009 #include <utilmm/stringtools.hh>
00010
00011 #include <utilmm/configfile/configset.hh>
00012 #include <utilmm/system/process.hh>
00013 #include <utilmm/system/system.hh>
00014
00015 #include <boost/filesystem.hpp>
00016
00017 #include "standard_types.hh"
00018
00019 using namespace std;
00020 using namespace antlr;
00021 using namespace Typelib;
00022
00023 using boost::filesystem::path;
00024
00025 namespace
00026 {
00027 using namespace std;
00028 using namespace utilmm;
00029 using namespace boost::filesystem;
00030
00031 path runcpp(path const& file, config_set const& config)
00032 {
00033 utilmm::process cpp;
00034
00035 try {
00036 tempfile tmpfile("typelib_cimport");
00037 path tmp_path = tmpfile.path();
00038 FILE* handle = tmpfile.handle();
00039
00040 bool debug = config.get<bool>("debug");
00041
00042 if (debug)
00043 {
00044 std::clog << "cpp output goes to " << tmp_path.native_file_string() << std::endl;
00045 tmpfile.detach();
00046 }
00047
00048 cpp.push("cpp");
00049 cpp.push(file.native_file_string());
00050
00051
00052 typedef list<string> strlist;
00053 list<string> defines = config.get< list<string> >("define");
00054 list<string> includes = config.get< list<string> >("include");
00055 list<string> rawflags = config.get< list<string> >("rawflags");
00056 {
00057 list<string> rawflag = config.get< list<string> >("rawflag");
00058 rawflags.splice(rawflags.end(), rawflag);
00059 }
00060
00061 for (strlist::const_iterator it = defines.begin(); it != defines.end(); ++it)
00062 cpp.push("-D" + *it);
00063 for (strlist::const_iterator it = includes.begin(); it != includes.end(); ++it)
00064 cpp.push("-I" + *it);
00065 for (strlist::const_iterator it = rawflags.begin(); it != rawflags.end(); ++it)
00066 cpp.push(*it);
00067
00068 if (debug)
00069 {
00070 std::clog << "will run the following command: \n"
00071 << " " << utilmm::join(cpp.cmdline(), " ") << std::endl;
00072 }
00073
00074
00075 cpp.redirect_to(process::Stdout, handle, false);
00076 cpp.start();
00077 cpp.wait();
00078 if (cpp.exit_normal() && !cpp.exit_status())
00079 {
00080 if (!debug)
00081 tmpfile.detach();
00082 return tmp_path;
00083 }
00084
00085 return path();
00086 }
00087 catch(utilmm::unix_error) { return path(); }
00088 }
00089 }
00090
00091 void CImport::load
00092 ( std::istream& stream
00093 , utilmm::config_set const& config
00094 , Registry& registry )
00095 {
00096 try {
00097 CPPLexer cpp_lexer(stream);
00098
00099 Typelib::CXX::addStandardTypes(registry);
00100
00101 TypeSolver reader(cpp_lexer, registry, config.get<bool>("cxx", true));
00102 reader.setupOpaqueHandling(config.get<bool>("opaques_forced_alignment", true),
00103 config.get<bool>("opaques_ignore", false));
00104
00105 list<config_set const*> opaque_defs = config.children("opaques");
00106 for (list<config_set const*>::const_iterator it = opaque_defs.begin(); it != opaque_defs.end(); ++it)
00107 {
00108 reader.defineOpaqueAlignment((*it)->get<string>("name"),
00109 (*it)->get<size_t>("alignment"));
00110 }
00111
00112 reader.init();
00113 reader.translation_unit();
00114 }
00115 catch (ANTLRException const& e)
00116 { throw ImportError("", "syntax error: " + e.toString()); }
00117 }
00118
00119
00120 void CImport::load
00121 ( std::string const& file
00122 , utilmm::config_set const& config
00123 , Registry& registry)
00124 {
00125 path temp;
00126 try
00127 {
00128 temp = runcpp(utilmm::clean_path(file), config);
00129 if (temp.empty())
00130 throw ImportError("", "error running the preprocessor");
00131
00132
00133 ifstream s(temp.native_file_string().c_str());
00134 if (!s)
00135 throw ImportError("", "cannot open for reading");
00136
00137 load(s, config, registry);
00138 remove(temp);
00139 }
00140 catch(...)
00141 {
00142 if (! temp.empty())
00143 remove(temp);
00144 throw;
00145 }
00146 }
00147