diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2010-11-09 14:02:41 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2010-11-09 14:02:41 +0200 |
commit | edae7d98cfac5f55782236d397c831f68ebe11a6 (patch) | |
tree | 417df3223034fb02421731412203ae361c43e15a /odb/plugin.cxx | |
parent | ce696c26d2c9dd5a5813fd865082ab19ac49bcfa (diff) |
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.
Diffstat (limited to 'odb/plugin.cxx')
-rw-r--r-- | odb/plugin.cxx | 92 |
1 files changed, 90 insertions, 2 deletions
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 <memory> // std::auto_ptr #include <string> #include <vector> +#include <cstring> // std::strcpy #include <iostream> #include <odb/pragma.hxx> @@ -24,6 +25,63 @@ using namespace semantics; int plugin_is_GPL_compatible; auto_ptr<options const> 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<cpp_file_prefix*> (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 != "<built-in>" && + f != "<command-line>" && + f != "<stdin>") + { + file = path (f); + break; + } + } + } + + // + // parser p (*options_, loc_pragmas_, decl_pragmas_); - path file (main_input_filename); auto_ptr<unit> 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<string> 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<string> argv_str; + strings argv_str; vector<char*> 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); |