MergeSym.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:10k
- /*
- * MergeSym.cxx
- *
- * Symbol merging utility for Windows DLL's.
- *
- * Portable Windows Library
- *
- * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Portable Windows Library.
- *
- * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
- *
- * Contributor(s): ______________________________________.
- *
- * $Log: MergeSym.cxx,v $
- * Revision 1.7 2000/04/29 05:48:22 robertj
- * Added error and progress reporting in searching path for external DEF files.
- *
- * Revision 1.6 2000/04/29 05:01:49 robertj
- * Added multiple external DEF file capability (-x flag).
- * Added directory search path argument for external DEF files.
- * Fixed bug for symbols in external DEF file actively removed from merged DEF file.
- * Added copyright notice.
- *
- */
- #include <ptlib.h>
- #include <ptlib/pipechan.h>
- PDECLARE_CLASS(Symbol, PCaselessString)
- public:
- Symbol(const PString & sym, const PString & cpp, PINDEX ord = 0, BOOL ext = FALSE)
- : PCaselessString(sym), unmangled(cpp) { ordinal = ord; external = ext; }
- void SetOrdinal(PINDEX ord) { ordinal = ord; }
- BOOL IsExternal() const { return external; }
- void PrintOn(ostream & s) const
- { s << " " << theArray << " @" << ordinal << " NONAME ;" << unmangled << 'n'; }
- private:
- PString unmangled;
- PINDEX ordinal;
- BOOL external;
- };
- PSORTED_LIST(SortedSymbolList, Symbol);
- PDECLARE_CLASS(MergeSym, PProcess)
- public:
- MergeSym();
- void Main();
- };
- PCREATE_PROCESS(MergeSym);
- MergeSym::MergeSym()
- : PProcess("Equivalence", "MergeSym", 1, 1, ReleaseCode, 1)
- {
- }
- void MergeSym::Main()
- {
- cout << GetName() << " version " << GetVersion(TRUE)
- << " on " << GetOSClass() << ' ' << GetOSName()
- << " by " << GetManufacturer() << endl;
- PArgList & args = GetArguments();
- args.Parse("vx:I:");
- PFilePath lib_filename, def_filename;
- switch (args.GetCount()) {
- case 2 :
- def_filename = args[1];
- lib_filename = args[0];
- break;
- case 1 :
- lib_filename = def_filename = args[0];
- def_filename.SetType(".def");
- break;
- default :
- PError << "usage: MergeSym [ -v ] [ -x deffile[.def] ] [-I deffilepath ] libfile[.lib] [ deffile[.def] ]";
- SetTerminationValue(1);
- return;
- }
- if (lib_filename.GetType().IsEmpty())
- lib_filename.SetType(".lib");
- if (!PFile::Exists(lib_filename)) {
- PError << "MergeSym: library file " << lib_filename << " does not exist.n";
- SetTerminationValue(1);
- return;
- }
- if (def_filename.GetType().IsEmpty())
- def_filename.SetType(".def");
- SortedSymbolList def_symbols;
- if (args.HasOption('x')) {
- PStringArray include_path;
- if (args.HasOption('I'))
- include_path = args.GetOptionString('I').Tokenise(';', FALSE);
- include_path.InsertAt(0, new PString());
- PStringArray file_list = args.GetOptionString('x').Lines();
- for (PINDEX ext_index = 0; ext_index < file_list.GetSize(); ext_index++) {
- PString base_ext_filename = file_list[ext_index];
- PFilePath ext_filename = base_ext_filename;
- if (ext_filename.GetType().IsEmpty())
- ext_filename.SetType(".def");
- PINDEX previous_def_symbols_size = def_symbols.GetSize();
- for (PINDEX inc_index = 0; inc_index < include_path.GetSize(); inc_index++) {
- PString trial_filename;
- if (include_path[inc_index].IsEmpty())
- trial_filename = ext_filename;
- else
- trial_filename = PDirectory(include_path[inc_index]) + ext_filename.GetFileName();
- if (args.HasOption('v'))
- cout << "nTrying " << trial_filename << " ..." << flush;
- PTextFile ext;
- if (ext.Open(trial_filename, PFile::ReadOnly)) {
- if (args.HasOption('v'))
- cout << "nReading external symbols from " << ext.GetFilePath() << " ..." << flush;
- BOOL prefix = TRUE;
- while (!ext.eof()) {
- PCaselessString line;
- ext >> line;
- if (prefix)
- prefix = line.Find("EXPORTS") == P_MAX_INDEX;
- else {
- PINDEX start = 0;
- while (isspace(line[start]))
- start++;
- PINDEX end = start;
- while (line[end] != ' ' && !isspace(line[end]))
- end++;
- def_symbols.Append(new Symbol(line(start, end-1), "", 0, TRUE));
- if (args.HasOption('v') && def_symbols.GetSize()%100 == 0)
- cout << '.' << flush;
- }
- }
- break;
- }
- }
- if (inc_index >= include_path.GetSize())
- PError << "MergeSym: external symbol file "" << base_ext_filename << "" not found.n";
- if (args.HasOption('v'))
- cout << 'n' << (def_symbols.GetSize() - previous_def_symbols_size)
- << " symbols read." << endl;
- }
- }
- PStringList def_file_lines;
- PINDEX max_ordinal = 0;
- PINDEX removed = 0;
- PTextFile def;
- if (def.Open(def_filename, PFile::ReadOnly)) {
- if (args.HasOption('v'))
- cout << "Reading existing ordinals..." << flush;
- BOOL prefix = TRUE;
- while (!def.eof()) {
- PCaselessString line;
- def >> line;
- if (prefix) {
- def_file_lines.AppendString(line);
- if (line.Find("EXPORTS") != P_MAX_INDEX)
- prefix = FALSE;
- }
- else {
- PINDEX start = 0;
- while (isspace(line[start]))
- start++;
- PINDEX end = start;
- while (line[end] != ' ' && !isspace(line[end]))
- end++;
- PINDEX ordpos = line.Find('@', end);
- if (ordpos != P_MAX_INDEX) {
- PINDEX ordinal = line.Mid(ordpos+1).AsInteger();
- if (ordinal > max_ordinal)
- max_ordinal = ordinal;
- PINDEX unmanglepos = line.Find(';', ordpos);
- if (unmanglepos != P_MAX_INDEX)
- unmanglepos++;
- Symbol sym(line(start, end-1), line.Mid(unmanglepos), ordinal);
- if (def_symbols.GetValuesIndex(sym) == P_MAX_INDEX)
- def_symbols.Append(new Symbol(sym));
- removed++;
- if (args.HasOption('v') && def_symbols.GetSize()%100 == 0)
- cout << '.' << flush;
- }
- }
- }
- def.Close();
- if (args.HasOption('v'))
- cout << 'n' << removed << " symbols read." << endl;
- }
- else {
- def_file_lines.AppendString("LIBRARY " + def_filename.GetTitle());
- def_file_lines.AppendString("EXPORTS");
- }
- if (args.HasOption('v'))
- cout << "Reading library symbols..." << flush;
- PINDEX linecount = 0;
- SortedSymbolList lib_symbols;
- PPipeChannel pipe("dumpbin /symbols '" + lib_filename + "'", PPipeChannel::ReadOnly);
- while (!pipe.eof()) {
- char line[500];
- pipe.getline(line, sizeof(line));
- char * namepos = strchr(line, '|');
- if (namepos != NULL) {
- *namepos = ' ';
- while (*++namepos == ' ');
- if (strstr(line, " UNDEF ") == NULL &&
- strstr(line, " External ") != NULL &&
- strstr(namepos, "deleting destructor") == NULL) {
- int namelen = strcspn(namepos, "rnt ");
- PString name(namepos, namelen);
- if (strncmp(name, "??_C@_", 6) != 0 &&
- lib_symbols.GetValuesIndex(name) == P_MAX_INDEX) {
- const char * unmangled = strchr(namepos+namelen, '(');
- if (unmangled == NULL)
- unmangled = name;
- else {
- unmangled++;
- char * endunmangle = strrchr(unmangled, ')');
- if (endunmangle != NULL)
- *endunmangle = ' ';
- }
- lib_symbols.Append(new Symbol(name, unmangled));
- }
- }
- }
- if (args.HasOption('v') && linecount%500 == 0)
- cout << '.' << flush;
- linecount++;
- }
- if (args.HasOption('v'))
- cout << 'n' << lib_symbols.GetSize() << " symbols read.n"
- "Sorting symbols... " << flush;
- PINDEX i;
- for (i = 0; i < def_symbols.GetSize(); i++) {
- if (lib_symbols.GetValuesIndex(def_symbols[i]) != P_MAX_INDEX &&
- !def_symbols[i].IsExternal())
- removed--;
- }
- PINDEX added = 0;
- for (i = 0; i < lib_symbols.GetSize(); i++) {
- if (def_symbols.GetValuesIndex(lib_symbols[i]) == P_MAX_INDEX) {
- lib_symbols[i].SetOrdinal(++max_ordinal);
- added++;
- }
- }
- if (added == 0 && removed == 0)
- cout << "nNo changes to symbols.n";
- else {
- if (args.HasOption('v'))
- cout << "Writing .DEF file..." << flush;
- // If file is read/only, set it to read/write
- PFileInfo info;
- if (PFile::GetInfo(def_filename, info)) {
- if ((info.permissions&PFileInfo::UserWrite) == 0) {
- PFile::SetPermissions(def_filename, info.permissions|PFileInfo::UserWrite);
- cout << "Setting "" << def_filename << "" to read/write mode." << flush;
- }
- }
- if (def.Open(def_filename, PFile::WriteOnly)) {
- for (i = 0; i < def_file_lines.GetSize(); i++)
- def << def_file_lines[i] << 'n';
- for (i = 0; i < def_symbols.GetSize(); i++) {
- if (lib_symbols.GetValuesIndex(def_symbols[i]) != P_MAX_INDEX &&
- !def_symbols[i].IsExternal()) {
- def << def_symbols[i];
- }
- if (args.HasOption('v') && i%100 == 0)
- cout << '.' << flush;
- }
- for (i = 0; i < lib_symbols.GetSize(); i++) {
- if (def_symbols.GetValuesIndex(lib_symbols[i]) == P_MAX_INDEX)
- def << lib_symbols[i];
- if (args.HasOption('v') && i%100 == 0)
- cout << '.' << flush;
- }
- cout << "nSymbols merged: " << added << " added, " << removed << " removed.n";
- }
- else {
- PError << "Could not create file " << def_filename << ':' << def.GetErrorText() << endl;
- SetTerminationValue(1);
- }
- }
- }
- // End MergeSym.cxx