diff options
Diffstat (limited to 'odb/plugin.cxx')
-rw-r--r-- | odb/plugin.cxx | 458 |
1 files changed, 0 insertions, 458 deletions
diff --git a/odb/plugin.cxx b/odb/plugin.cxx deleted file mode 100644 index aff90ee..0000000 --- a/odb/plugin.cxx +++ /dev/null @@ -1,458 +0,0 @@ -// file : odb/plugin.cxx -// license : GNU GPL v3; see accompanying LICENSE file - -#include <odb/gcc.hxx> // Keep it first. - -#include <unistd.h> // stat() -#include <sys/types.h> // stat -#include <sys/stat.h> // stat - -#include <memory> // std::unique_ptr -#include <string> -#include <vector> -#include <cstring> // std::strcpy, std::strstr -#include <cassert> -#include <iostream> - -#include <cutl/re.hxx> -#include <cutl/fs/path.hxx> - -#include <odb/pragma.hxx> -#include <odb/parser.hxx> -#include <odb/options.hxx> -#include <odb/option-functions.hxx> -#include <odb/features.hxx> -#include <odb/profile.hxx> -#include <odb/version.hxx> -#include <odb/validator.hxx> -#include <odb/processor.hxx> -#include <odb/generator.hxx> -#include <odb/semantics/unit.hxx> - -using namespace std; -using namespace semantics; - -using cutl::fs::path; -using cutl::fs::invalid_path; - -typedef vector<path> paths; - -#if defined(_WIN32) && !defined(ODB_STATIC_PLUGIN) -__declspec(dllexport) -#endif -int plugin_is_GPL_compatible; - -unique_ptr<options const> options_; -paths profile_paths_; -path file_; // File being compiled. -paths inputs_; // List of input files in at-once mode or just file_. - -bool (*cpp_diagnostic_prev) ( - cpp_reader*, -#if BUILDING_GCC_MAJOR >= 9 - cpp_diagnostic_level, - cpp_warning_reason, -#else - int, - int, -#endif -#if BUILDING_GCC_MAJOR >= 6 - rich_location*, -#else - location_t, - unsigned int, -#endif - const char*, - va_list*); - -static bool -cpp_diagnostic_filter (cpp_reader* r, -#if BUILDING_GCC_MAJOR >= 9 - cpp_diagnostic_level level, - cpp_warning_reason reason, -#else - int level, - int reason, -#endif -#if BUILDING_GCC_MAJOR >= 6 - rich_location* l, -#else - location_t l, - unsigned int column_override, -#endif - const char* msg, - va_list* ap) -{ - // #pragma once in the main file. Note that the message that we get is - // potentially translated so we search for the substring (there is - // currently only one warning in libcpp that mentions #pragma once). - // Unfortunately, some translations translate the 'once' word (e.g, - // #pragma uno; I wonder if one can actually specify it like that in - // the source code). Oh, well, there is only so much we can do. - // - if (strstr (msg, "#pragma once") != 0) - return true; - - return cpp_diagnostic_prev ( - r, - level, - reason, -#if BUILDING_GCC_MAJOR >= 6 - l, -#else - l, - column_override, -#endif - msg, - ap); -} - -// 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; - _cpp_file* next_file; - const uchar* buffer; - const uchar* buffer_start; - const cpp_hashnode *cmacro; - cpp_dir *dir; - struct stat st; -}; - -extern "C" void -start_unit_callback (void*, void*) -{ - // Set the preprocessor error callback to filter out useless diagnostics. - // - cpp_callbacks* cb (cpp_get_callbacks (parse_in)); - -#if BUILDING_GCC_MAJOR >= 9 - cpp_diagnostic_prev = cb->diagnostic; - cb->diagnostic = &cpp_diagnostic_filter; -#else - cpp_diagnostic_prev = cb->error; - cb->error = &cpp_diagnostic_filter; -#endif - - if (cpp_diagnostic_prev == 0) - { - cerr << "ice: expected cpp diagnostic callback to be set" << endl; - exit (1); - } - - // Set the directory of the main file (stdin) to that of the orginal - // file so that relative inclusion works. Also adjust the path and - // re-stat the file so that #pragma once works. - // - cpp_buffer* b (cpp_get_buffer (parse_in)); - _cpp_file* f (cpp_get_file (b)); - cpp_dir* d (cpp_get_dir (f)); - char const* p (cpp_get_path (f)); - - cpp_file_prefix* fp (reinterpret_cast<cpp_file_prefix*> (f)); - - // Perform some 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 == d // Our prefix corresponds to the actual type. - && fp->dir_name == 0) // The directory part hasn't been initialized. - { - // The dir_name is initialized by libcpp lazily so we can preemptively - // set it to what we need. - // - path d (file_.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; - - // Unless we are in the at-once mode (where input files are actually - // #include'ed into the synthesized stdin), pretend that we are the - // actual input file. This is necessary for the #pragma once to work. - // - // All this relies on the way things are implemented in libcpp. In - // particular, the #pragma once code first checks if the mtime and - // size of files match (that's why we need stat() below). If they - // do, then it goes ahead and compares their contents. To re-load - // the contents of the file libcpp uses the path (that's why we - // need to adjust that as well). - // - if (inputs_.size () == 1) - { - string const& f (file_.string ()); - - XDELETEVEC (fp->path); - size_t n (f.size ()); - char* p (XNEWVEC (char, n + 1)); - strcpy (p, f.c_str ()); - p[n] = '\0'; - fp->path = p; - - // This call shouldn't fail since we've just opened it in the driver. - stat (fp->path, &fp->st); - } - } - else - { - cerr << "ice: unable to initialize main file directory" << endl; - exit (1); - } -} - -extern "C" void -gate_callback (void*, void*) -{ - // If there were errors during compilation, let GCC handle the - // exit. - // - if (errorcount || sorrycount) - return; - - int r (0); - - try - { - // Post process pragmas. - // - post_process_pragmas (); - - // Parse the GCC tree to semantic graph. - // - parser p (*options_, loc_pragmas_, ns_loc_pragmas_, decl_pragmas_); - unique_ptr<unit> u (p.parse (global_namespace, file_)); - - features f; - - // Process, pass 1. - // - process (*options_, f, *u, file_, 1); - - // Validate, pass 1. - // - validate (*options_, f, *u, file_, 1); - - // Process, pass 2. - // - process (*options_, f, *u, file_, 2); - - // Validate, pass 2. - // - validate (*options_, f, *u, file_, 2); - - // Generate. - // - generate (*options_, f, *u, file_, inputs_); - } - catch (cutl::re::format const& e) - { - cerr << "error: invalid regex: '" << e.regex () << "': " << - e.description () << endl; - r = 1; - } - catch (pragmas_failed const&) - { - // Diagnostics has aready been issued. - // - r = 1; - } - catch (parser::failed const&) - { - // Diagnostics has aready been issued. - // - r = 1; - } - catch (validator_failed const&) - { - // Diagnostics has aready been issued. - // - r = 1; - } - catch (processor_failed const&) - { - // Diagnostics has aready been issued. - // - r = 1; - } - catch (generator_failed const&) - { - // Diagnostics has aready been issued. - // - r = 1; - } - - exit (r); -} - -static char const* const odb_version = ODB_COMPILER_VERSION_STR; - -typedef vector<string> strings; - -extern "C" -#if defined(_WIN32) && !defined(ODB_STATIC_PLUGIN) -__declspec(dllexport) -#endif -int -plugin_init (plugin_name_args* plugin_info, plugin_gcc_version*) -{ - int r (0); - plugin_info->version = odb_version; - - try - { - // Parse options. - // - { - strings argv_str; - argv_str.push_back (plugin_info->base_name); - - for (int i (0); i < plugin_info->argc; ++i) - { - plugin_argument& a (plugin_info->argv[i]); - - // A value cannot contain '=' so it is passed as the backspace - // character. - // - string v (a.value != 0 ? a.value : ""); - for (size_t i (0); i < v.size (); ++i) - if (v[i] == '\b') - v[i] = '='; - - // Handle service options. - // - if (strcmp (a.key, "svc-path") == 0) - { - profile_paths_.push_back (path (v)); - continue; - } - - if (strcmp (a.key, "svc-file") == 0) - { - // First is the main file. Subsequent are inputs in the at-once - // mode. - // - if (file_.empty ()) - file_ = path (v); - else - inputs_.push_back (path (v)); - - continue; - } - - string opt (strlen (a.key) > 1 ? "--" : "-"); - opt += a.key; - - argv_str.push_back (opt); - - if (a.value != 0) - argv_str.push_back (v); - } - - vector<char*> argv; - for (strings::iterator i (argv_str.begin ()); i != argv_str.end (); ++i) - argv.push_back (const_cast<char*> (i->c_str ())); - - int argc (static_cast<int> (argv.size ())); - - if (inputs_.empty ()) - inputs_.push_back (file_); - - // Two-phase options parsing, similar to the driver. - // - cli::argv_file_scanner::option_info oi[3]; - oi[0].option = "--options-file"; - oi[0].search_func = 0; - oi[1].option = "-p"; - oi[2].option = "--profile"; - - database db; - { - oi[1].search_func = &profile_search_ignore; - oi[2].search_func = &profile_search_ignore; - - cli::argv_file_scanner scan (argc, &argv[0], oi, 3); - options ops (scan); - assert (ops.database_specified ()); - db = ops.database ()[0]; - } - - profile_data pd (profile_paths_, db, "odb plugin"); - oi[1].search_func = &profile_search; - oi[2].search_func = &profile_search; - oi[1].arg = &pd; - oi[2].arg = &pd; - - cli::argv_file_scanner scan (argc, &argv[0], oi, 3); - unique_ptr<options> ops ( - new options (scan, cli::unknown_mode::fail, cli::unknown_mode::fail)); - - // Process options. - // - process_options (*ops); - - options_ = move (ops); - pragma_db_ = db; - pragma_multi_ = options_->multi_database (); - } - - if (options_->trace ()) - cerr << "starting plugin " << plugin_info->base_name << endl; - - // Disable assembly output. GCC doesn't define HOST_BIT_BUCKET - // correctly for MinGW (it still used /dev/null which fails to - // open). - // -#ifdef _WIN32 - asm_file_name = "nul"; -#else - asm_file_name = HOST_BIT_BUCKET; -#endif - - // Register callbacks. - // - register_callback (plugin_info->base_name, - PLUGIN_PRAGMAS, - register_odb_pragmas, - 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); - } - catch (cli::exception const& ex) - { - cerr << ex << endl; - r = 1; - } - - if (r != 0) - exit (r); - - return r; -} |