From edae7d98cfac5f55782236d397c831f68ebe11a6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 9 Nov 2010 14:02:41 +0200 Subject: Implement new compilation architecture Instead of compiling the header directly, g++ is now invoked to compile stdin. At the same time the odb driver pipes the original header to g++. This new approach allows us to add some source code before and/or after the original header. --- odb/plugin.cxx | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 2 deletions(-) (limited to 'odb/plugin.cxx') diff --git a/odb/plugin.cxx b/odb/plugin.cxx index 1947c6e..d5134d9 100644 --- a/odb/plugin.cxx +++ b/odb/plugin.cxx @@ -8,6 +8,7 @@ #include // std::auto_ptr #include #include +#include // std::strcpy #include #include @@ -24,6 +25,63 @@ using namespace semantics; int plugin_is_GPL_compatible; auto_ptr options_; +// A prefix of the _cpp_file struct. This struct is not part of the +// public interface so we have to resort to this technique (based on +// libcpp/files.c). +// +struct cpp_file_prefix +{ + char const* name; + char const* path; + char const* pchname; + char const* dir_name; +}; + +extern "C" void +start_unit_callback (void*, void*) +{ + // Set the directory of the main file (stdin) to that of the orginal + // file. + // + cpp_buffer* b (cpp_get_buffer (parse_in)); + _cpp_file* f (cpp_get_file (b)); + char const* p (cpp_get_path (f)); + cpp_file_prefix* fp (reinterpret_cast (f)); + + // Perform sanity checks. + // + if (p != 0 && *p == '\0' // The path should be empty (stdin). + && cpp_get_prev (b) == 0 // This is the only buffer (main file). + && fp->path == p // Our prefix corresponds to the actual type. + && fp->dir_name == 0) // The directory part hasn't been initialized. + { + path p (options_->svc_file ()); + path d (p.directory ()); + char* s; + + if (d.empty ()) + { + s = XNEWVEC (char, 1); + *s = '\0'; + } + else + { + size_t n (d.string ().size ()); + s = XNEWVEC (char, n + 2); + strcpy (s, d.string ().c_str ()); + s[n] = path::traits::directory_separator; + s[n + 1] = '\0'; + } + + fp->dir_name = s; + } + else + { + cerr << "ice: unable to initialize main file directory" << endl; + exit (1); + } +} + extern "C" void gate_callback (void*, void*) { @@ -37,8 +95,31 @@ gate_callback (void*, void*) try { + // Find the actual main file name that was specified with the + // #line directive. + // + path file; + for (size_t i (0); i < line_table->used; ++i) + { + line_map const* m (line_table->maps + i); + + if (MAIN_FILE_P (m) && m->reason == LC_RENAME) + { + string f (m->to_file); + + if (f != "" && + f != "" && + f != "") + { + file = path (f); + break; + } + } + } + + // + // parser p (*options_, loc_pragmas_, decl_pragmas_); - path file (main_input_filename); auto_ptr u (p.parse (global_namespace, file)); // @@ -73,6 +154,8 @@ gate_callback (void*, void*) static char const* const odb_version = ODB_COMPILER_VERSION_STR; +typedef vector strings; + extern "C" int plugin_init (plugin_name_args* plugin_info, plugin_gcc_version*) { @@ -84,7 +167,7 @@ plugin_init (plugin_name_args* plugin_info, plugin_gcc_version*) // Parse options. // { - vector argv_str; + strings argv_str; vector argv; argv_str.push_back (plugin_info->base_name); @@ -129,6 +212,11 @@ plugin_init (plugin_name_args* plugin_info, plugin_gcc_version*) 0); register_callback (plugin_info->base_name, + PLUGIN_START_UNIT, + start_unit_callback, + 0); + + register_callback (plugin_info->base_name, PLUGIN_OVERRIDE_GATE, &gate_callback, 0); -- cgit v1.1