From d55bee477e61ad59642203bc0f6fe0a3e0eb9355 Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Tue, 25 Apr 2017 01:16:09 +0200 Subject: [PATCH] MakeImport/MakePEF: communicate exact member name to MakePEF even if file system does not support MacRoman-encoded filenames. --- PEFTools/MakeImport.cc | 18 ++++++++++++++++++ PEFTools/MakePEF.cc | 32 +++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/PEFTools/MakeImport.cc b/PEFTools/MakeImport.cc index 001556f341..80ef1be6fa 100755 --- a/PEFTools/MakeImport.cc +++ b/PEFTools/MakeImport.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -268,11 +269,28 @@ void MakeImportLibraryMulti(fs::path path, fs::path libname) for(auto &member : members) { std::ostringstream memberNameStream; + + // classic MacOS shared library names are in MacRoman and + // may contain wierd characters; the shared library name is used + // as the file name for the archive member, so there can be problems. + // + // We encode the file name to hex (and add a human readable name). + // MakePEF contains corresponding decoder logic. + + memberNameStream << "imp__"; + for(char c : member.name) { if(isalnum(c)) memberNameStream << c; } + memberNameStream << "_"; + for(char c : member.name) + { + int cc = (unsigned char) c; + memberNameStream << std::setw(2) << std::setfill('0') << std::hex + << cc; + } memberNameStream << "_" << memberIndex++; string memberName = memberNameStream.str(); diff --git a/PEFTools/MakePEF.cc b/PEFTools/MakePEF.cc index 24bba8697f..dbd80f25dd 100755 --- a/PEFTools/MakePEF.cc +++ b/PEFTools/MakePEF.cc @@ -9,7 +9,7 @@ #include #include - +#include #include "PEF.h" @@ -306,6 +306,36 @@ void mkpef(const std::string& inFn, const std::string& outFn) } } + if(name.length() > 5) + { + // the shared library name has been encoded as hex by MakeImport + // in order to avoid potential file name issues + // classic MacOS shared library names are in MacRoman and + // may contain wierd characters; the shared library name is used + // as the file name for the archive member, so there can be problems. + if(name.substr(0,5) == "imp__") + { + std::string realName; + + int i; + int n = name.size(); + for(i = 5; i < n && name[i] != '_'; i++) + ; + ++i; + for(; i + 1 < n && name[i] != '_'; i+=2) + { + char c1 = tolower(name[i]); + char c2 = tolower(name[i+1]); + assert(isdigit(c1) || (c1 >= 'a' && c1 <= 'f')); + assert(isdigit(c2) || (c2 >= 'a' && c2 <= 'f')); + int c = (c1 >= 'a' ? c1 - 'a' + 10 : c1 - '0') * 16 + + (c2 >= 'a' ? c2 - 'a' + 10 : c2 - '0'); + realName += (char)c; + } + name = realName; + } + } + if(verboseFlag) { std::cerr << "PEF name \"" << name << '"';