MergeSym.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:10k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * MergeSym.cxx
  3.  *
  4.  * Symbol merging utility for Windows DLL's.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Contributor(s): ______________________________________.
  25.  *
  26.  * $Log: MergeSym.cxx,v $
  27.  * Revision 1.7  2000/04/29 05:48:22  robertj
  28.  * Added error and progress reporting in searching path for external DEF files.
  29.  *
  30.  * Revision 1.6  2000/04/29 05:01:49  robertj
  31.  * Added multiple external DEF file capability (-x flag).
  32.  * Added directory search path argument for external DEF files.
  33.  * Fixed bug for symbols in external DEF file actively removed from merged DEF file.
  34.  * Added copyright notice.
  35.  *
  36.  */
  37. #include <ptlib.h>
  38. #include <ptlib/pipechan.h>
  39. PDECLARE_CLASS(Symbol, PCaselessString)
  40.   public:
  41.     Symbol(const PString & sym, const PString & cpp, PINDEX ord = 0, BOOL ext = FALSE)
  42.       : PCaselessString(sym), unmangled(cpp) { ordinal = ord; external = ext; }
  43.     void SetOrdinal(PINDEX ord) { ordinal = ord; }
  44.     BOOL IsExternal() const { return external; }
  45.     void PrintOn(ostream & s) const
  46.       { s << "    " << theArray << " @" << ordinal << " NONAME ;" << unmangled << 'n'; }
  47.   private:
  48.     PString unmangled;
  49.     PINDEX ordinal;
  50.     BOOL external;
  51. };
  52. PSORTED_LIST(SortedSymbolList, Symbol);
  53. PDECLARE_CLASS(MergeSym, PProcess)
  54.   public:
  55.     MergeSym();
  56.     void Main();
  57. };
  58. PCREATE_PROCESS(MergeSym);
  59. MergeSym::MergeSym()
  60.   : PProcess("Equivalence", "MergeSym", 1, 1, ReleaseCode, 1)
  61. {
  62. }
  63. void MergeSym::Main()
  64. {
  65.   cout << GetName() << " version " << GetVersion(TRUE)
  66.        << " on " << GetOSClass() << ' ' << GetOSName()
  67.        << " by " << GetManufacturer() << endl;
  68.   PArgList & args = GetArguments();
  69.   args.Parse("vx:I:");
  70.   PFilePath lib_filename, def_filename;
  71.   switch (args.GetCount()) {
  72.     case 2 :
  73.       def_filename = args[1];
  74.       lib_filename = args[0];
  75.       break;
  76.     case 1 :
  77.       lib_filename = def_filename = args[0];
  78.       def_filename.SetType(".def");
  79.       break;
  80.     default :
  81.       PError << "usage: MergeSym [ -v ] [ -x deffile[.def] ] [-I deffilepath ] libfile[.lib] [ deffile[.def] ]";
  82.       SetTerminationValue(1);
  83.       return;
  84.   }
  85.   if (lib_filename.GetType().IsEmpty())
  86.     lib_filename.SetType(".lib");
  87.   if (!PFile::Exists(lib_filename)) {
  88.     PError << "MergeSym: library file " << lib_filename << " does not exist.n";
  89.     SetTerminationValue(1);
  90.     return;
  91.   }
  92.   if (def_filename.GetType().IsEmpty())
  93.     def_filename.SetType(".def");
  94.   SortedSymbolList def_symbols;
  95.   if (args.HasOption('x')) {
  96.     PStringArray include_path;
  97.     if (args.HasOption('I'))
  98.       include_path = args.GetOptionString('I').Tokenise(';', FALSE);
  99.     include_path.InsertAt(0, new PString());
  100.     PStringArray file_list = args.GetOptionString('x').Lines();
  101.     for (PINDEX ext_index = 0; ext_index < file_list.GetSize(); ext_index++) {
  102.       PString base_ext_filename = file_list[ext_index];
  103.       PFilePath ext_filename = base_ext_filename;
  104.       if (ext_filename.GetType().IsEmpty())
  105.         ext_filename.SetType(".def");
  106.       PINDEX previous_def_symbols_size = def_symbols.GetSize();
  107.       for (PINDEX inc_index = 0; inc_index < include_path.GetSize(); inc_index++) {
  108.         PString trial_filename;
  109.         if (include_path[inc_index].IsEmpty())
  110.           trial_filename = ext_filename;
  111.         else
  112.           trial_filename = PDirectory(include_path[inc_index]) + ext_filename.GetFileName();
  113.         if (args.HasOption('v'))
  114.           cout << "nTrying " << trial_filename << " ..." << flush;
  115.         PTextFile ext;
  116.         if (ext.Open(trial_filename, PFile::ReadOnly)) {
  117.           if (args.HasOption('v'))
  118.             cout << "nReading external symbols from " << ext.GetFilePath() << " ..." << flush;
  119.           BOOL prefix = TRUE;
  120.           while (!ext.eof()) {
  121.             PCaselessString line;
  122.             ext >> line;
  123.             if (prefix)
  124.               prefix = line.Find("EXPORTS") == P_MAX_INDEX;
  125.             else {
  126.               PINDEX start = 0;
  127.               while (isspace(line[start]))
  128.                 start++;
  129.               PINDEX end = start;
  130.               while (line[end] != '' && !isspace(line[end]))
  131.                 end++;
  132.               def_symbols.Append(new Symbol(line(start, end-1), "", 0, TRUE));
  133.               if (args.HasOption('v') && def_symbols.GetSize()%100 == 0)
  134.                 cout << '.' << flush;
  135.             }
  136.           }
  137.           break;
  138.         }
  139.       }
  140.       if (inc_index >= include_path.GetSize())
  141.         PError << "MergeSym: external symbol file "" << base_ext_filename << "" not found.n";
  142.       if (args.HasOption('v'))
  143.         cout << 'n' << (def_symbols.GetSize() - previous_def_symbols_size)
  144.              << " symbols read." << endl;
  145.     }
  146.   }
  147.   PStringList def_file_lines;
  148.   PINDEX max_ordinal = 0;
  149.   PINDEX removed = 0;
  150.   PTextFile def;
  151.   if (def.Open(def_filename, PFile::ReadOnly)) {
  152.     if (args.HasOption('v'))
  153.       cout << "Reading existing ordinals..." << flush;
  154.     BOOL prefix = TRUE;
  155.     while (!def.eof()) {
  156.       PCaselessString line;
  157.       def >> line;
  158.       if (prefix) {
  159.         def_file_lines.AppendString(line);
  160.         if (line.Find("EXPORTS") != P_MAX_INDEX)
  161.           prefix = FALSE;
  162.       }
  163.       else {
  164.         PINDEX start = 0;
  165.         while (isspace(line[start]))
  166.           start++;
  167.         PINDEX end = start;
  168.         while (line[end] != '' && !isspace(line[end]))
  169.           end++;
  170.         PINDEX ordpos = line.Find('@', end);
  171.         if (ordpos != P_MAX_INDEX) {
  172.           PINDEX ordinal = line.Mid(ordpos+1).AsInteger();
  173.           if (ordinal > max_ordinal)
  174.             max_ordinal = ordinal;
  175.           PINDEX unmanglepos = line.Find(';', ordpos);
  176.           if (unmanglepos != P_MAX_INDEX)
  177.             unmanglepos++;
  178.           Symbol sym(line(start, end-1), line.Mid(unmanglepos), ordinal);
  179.           if (def_symbols.GetValuesIndex(sym) == P_MAX_INDEX)
  180.             def_symbols.Append(new Symbol(sym));
  181.           removed++;
  182.           if (args.HasOption('v') && def_symbols.GetSize()%100 == 0)
  183.             cout << '.' << flush;
  184.         }
  185.       }
  186.     }
  187.     def.Close();
  188.     if (args.HasOption('v'))
  189.       cout << 'n' << removed << " symbols read." << endl;
  190.   }
  191.   else {
  192.     def_file_lines.AppendString("LIBRARY " + def_filename.GetTitle());
  193.     def_file_lines.AppendString("EXPORTS");
  194.   }
  195.   if (args.HasOption('v'))
  196.     cout << "Reading library symbols..." << flush;
  197.   PINDEX linecount = 0;
  198.   SortedSymbolList lib_symbols;
  199.   PPipeChannel pipe("dumpbin /symbols '" + lib_filename + "'", PPipeChannel::ReadOnly);
  200.   while (!pipe.eof()) {
  201.     char line[500];
  202.     pipe.getline(line, sizeof(line));
  203.     char * namepos = strchr(line, '|');
  204.     if (namepos != NULL) {
  205.       *namepos = '';
  206.       while (*++namepos == ' ');
  207.       if (strstr(line, " UNDEF ") == NULL &&
  208.           strstr(line, " External ") != NULL &&
  209.           strstr(namepos, "deleting destructor") == NULL) {
  210.         int namelen = strcspn(namepos, "rnt ");
  211.         PString name(namepos, namelen);
  212.         if (strncmp(name, "??_C@_", 6) != 0 &&
  213.             lib_symbols.GetValuesIndex(name) == P_MAX_INDEX) {
  214.           const char * unmangled = strchr(namepos+namelen, '(');
  215.           if (unmangled == NULL)
  216.             unmangled = name;
  217.           else {
  218.             unmangled++;
  219.             char * endunmangle = strrchr(unmangled, ')');
  220.             if (endunmangle != NULL)
  221.               *endunmangle = '';
  222.           }
  223.           lib_symbols.Append(new Symbol(name, unmangled));
  224.         }
  225.       }
  226.     }
  227.     if (args.HasOption('v') && linecount%500 == 0)
  228.       cout << '.' << flush;
  229.     linecount++;
  230.   }
  231.   if (args.HasOption('v'))
  232.     cout << 'n' << lib_symbols.GetSize() << " symbols read.n"
  233.             "Sorting symbols... " << flush;
  234.   PINDEX i;
  235.   for (i = 0; i < def_symbols.GetSize(); i++) {
  236.     if (lib_symbols.GetValuesIndex(def_symbols[i]) != P_MAX_INDEX &&
  237.         !def_symbols[i].IsExternal())
  238.       removed--;
  239.   }
  240.   PINDEX added = 0;
  241.   for (i = 0; i < lib_symbols.GetSize(); i++) {
  242.     if (def_symbols.GetValuesIndex(lib_symbols[i]) == P_MAX_INDEX) {
  243.       lib_symbols[i].SetOrdinal(++max_ordinal);
  244.       added++;
  245.     }
  246.   }
  247.   if (added == 0 && removed == 0)
  248.     cout << "nNo changes to symbols.n";
  249.   else {
  250.     if (args.HasOption('v'))
  251.       cout << "Writing .DEF file..." << flush;
  252.     // If file is read/only, set it to read/write
  253.     PFileInfo info;
  254.     if (PFile::GetInfo(def_filename, info)) {
  255.       if ((info.permissions&PFileInfo::UserWrite) == 0) {
  256.         PFile::SetPermissions(def_filename, info.permissions|PFileInfo::UserWrite);
  257.         cout << "Setting "" << def_filename << "" to read/write mode." << flush;
  258.       }
  259.     }
  260.     if (def.Open(def_filename, PFile::WriteOnly)) {
  261.       for (i = 0; i < def_file_lines.GetSize(); i++)
  262.         def << def_file_lines[i] << 'n';
  263.       for (i = 0; i < def_symbols.GetSize(); i++) {
  264.         if (lib_symbols.GetValuesIndex(def_symbols[i]) != P_MAX_INDEX &&
  265.             !def_symbols[i].IsExternal()) {
  266.           def << def_symbols[i];
  267.         }
  268.         if (args.HasOption('v') && i%100 == 0)
  269.           cout << '.' << flush;
  270.       }
  271.       for (i = 0; i < lib_symbols.GetSize(); i++) {
  272.         if (def_symbols.GetValuesIndex(lib_symbols[i]) == P_MAX_INDEX)
  273.           def << lib_symbols[i];
  274.         if (args.HasOption('v') && i%100 == 0)
  275.           cout << '.' << flush;
  276.       }
  277.       cout << "nSymbols merged: " << added << " added, " << removed << " removed.n";
  278.     }
  279.     else {
  280.       PError << "Could not create file " << def_filename << ':' << def.GetErrorText() << endl;
  281.       SetTerminationValue(1);
  282.     }
  283.   }
  284. }
  285. // End MergeSym.cxx