// // $Id: $ // // lib2def extracts the template symbols from a list of .lib files and puts them // into a single .def file, which is printed to standard output. This tool is // used to workaround a problem with Borland C++ importing template // instantiations from DLLs. It requires the Borland tool TDUMP to be located on // the path. // // Usage: lib2def [-Ldir...] libfile... // #include #include #include #include #include #include #include #include #include #include void print_usage () { std::cerr << "Usage: lib2def [-Ldir...] libfile...\n"; } int find_lib (const std::string& lib_name, const std::vector& lib_search_paths, std::string& lib_path) { for (size_t i = 0; i < lib_search_paths.size (); ++i) { struct stat stat_buf; std::string test_path = lib_search_paths[i] + lib_name; if (stat (test_path.c_str (), &stat_buf) == 0) { lib_path = test_path; return 0; } } return -1; } bool is_template_symbol (const std::string& symbol) { char unmangled_symbol[8192]; _umKind unmangled_kind = _rtl_unmangle(const_cast(symbol.c_str()), unmangled_symbol, sizeof(unmangled_symbol), 0, 0, 1); if (unmangled_kind & UM_ERRMASK) return true; // Can't unmangle symbol so force import bool have_less_than = false; bool have_greater_than = false; for (char* p = unmangled_symbol; *p; ++p) { switch (*p) { case '<': have_less_than = true; break; case '>': have_greater_than = true; break; default: break; } } return (have_less_than && have_greater_than); } int process_tdump_line (const std::string& line) { if (line.size () == 0 || line.compare (0, 5, "Turbo") == 0 || line.find ("Display of") != std::string::npos) return 0; std::istringstream is (line); std::string impdef; is >> impdef; if (impdef != "Impdef:") return -1; std::string name_or_ord; is >> name_or_ord; if (name_or_ord != "(Name)" && name_or_ord != "(Ord)") return -1; is >> std::ws; std::string module; std::getline (is, module, is.widen ('.')); std::string ordinal; std::getline (is, ordinal, is.widen ('=')); std::string symbol; std::getline (is, symbol); if (!is) return -1; if (symbol == "___CPPdebugHook") return 0; if (!is_template_symbol (symbol)) return 0; std::cout << " " << module << "." << symbol << "\n"; return 0; } int process_lib (const std::string& lib_path) { std::string temp_file_name = std::tmpnam (0); std::string cmd_line = "tdump -li -m " + lib_path + " > " + temp_file_name; if (std::system (cmd_line.c_str ()) != 0) return -1; int status = 0; std::ifstream is (temp_file_name.c_str ()); std::string line; while (std::getline (is, line)) if ((status = process_tdump_line (line)) == -1) break; is.close (); std::remove (temp_file_name.c_str ()); return status; } int main (int argc, char* argv[]) { std::vector lib_search_paths; lib_search_paths.push_back (""); bool printed_imports = false; int argi = 1; while (argi < argc) { if (argv[argi][0] == '-' || argv[argi][0] == '/') { if (argv[argi][1] == 'L') { if (argv[argi][2]) { lib_search_paths.push_back (&argv[argi][2]); lib_search_paths.back () += "/"; } else { ++argi; lib_search_paths.push_back (argv[argi]); lib_search_paths.back () += "/"; } } else { // Other options are simply ignored, to allow all // linker flags to be passed to this program. } } else { std::string lib_path; if (find_lib (argv[argi], lib_search_paths, lib_path) == -1) { std::cerr << "Warning: cannot locate " << argv[argi] << "\n"; ++argi; continue; } if (!printed_imports) { std::cout << "IMPORTS\n"; printed_imports = true; } if (process_lib (lib_path) == -1) { std::cerr << "Warning: cannot process " << argv[argi] << "\n"; } } ++argi; } if (!printed_imports) { std::cout << "IMPORTS\n"; } return 0; }