39 void stop(
char *errorMsg) {
40 printf(
"%s\n", errorMsg);
49 unsigned short sectionNum, type;
50 char storageClass, nAux;
53 class _rstream :
public istrstream {
58 _rstream(pair<const char *, streamsize> p)
59 : istrstream(p.first, p.second), buf(p.first) {}
60 ~_rstream() {
delete[] buf; }
66 class rstream :
public _rstream {
68 template <
class T>
inline rstream &doRead(T &x) {
69 read((
char *)&x,
sizeof(T));
72 static pair<const char *, streamsize> getBuf(
const char *fileName) {
73 ifstream raw(fileName, ios::binary | ios::in);
75 stop(
"rstream.getBuf: Error opening file");
76 raw.seekg(0, ios::end);
77 streampos fileSize = raw.tellg();
79 stop(
"rstream.getBuf: Error reading file");
80 char *buf =
new char[fileSize];
81 raw.seekg(0, ios::beg);
82 raw.read(buf, fileSize);
83 return pair<const char *, streamsize>(buf, fileSize);
88 rstream(
const char *buf, streamsize size)
89 : _rstream(pair<const char *, streamsize>(buf, size)) {}
92 rstream(
const char *fileName) : _rstream(getBuf(fileName)) {}
93 rstream &operator>>(
int &x) {
return doRead(x); }
94 rstream &operator>>(
unsigned &x) {
return doRead(x); }
95 rstream &operator>>(
short &x) {
return doRead(x); }
96 rstream &operator>>(
unsigned short &x) {
return doRead(x); }
97 rstream &operator>>(Symbol &e) {
106 map<string, unsigned> directory;
111 void makeDirectory(
void) {
114 string s = string(data + i);
115 directory.insert(make_pair(s, i));
120 void init(
const char *_data) {
121 unsigned _length = *(
unsigned *)_data;
123 if (_length <
sizeof(
unsigned) || _length != *(
unsigned *)_data)
124 stop(
"StringTable.init: Invalid symbol table");
125 if (_data[_length - 1]) {
127 data =
new char[length = _length + 1];
130 data =
new char[length = _length];
132 *(
unsigned *)data = length;
133 KMP_MEMCPY(data +
sizeof(
unsigned), _data +
sizeof(
unsigned),
134 length -
sizeof(
unsigned));
139 StringTable(rstream &f) {
147 if (strSize <
sizeof(
unsigned))
148 stop(
"StringTable: Invalid string table");
149 strData =
new char[strSize];
150 *(
unsigned *)strData = strSize;
152 f.read(strData +
sizeof(
unsigned), strSize -
sizeof(
unsigned));
155 stop(
"StringTable: Unexpected EOF");
159 StringTable(
const set<string> &strings) {
162 set<string>::const_iterator it;
166 for (length =
sizeof(
unsigned), it = strings.begin(); it != strings.end();
168 size_t l = (*it).size();
170 if (l > (
unsigned)0xFFFFFFFF)
171 stop(
"StringTable: String too long");
174 if (length > (
unsigned)0xFFFFFFFF)
175 stop(
"StringTable: Symbol table too long");
178 data =
new char[length];
179 *(
unsigned *)data = length;
181 for (p = data +
sizeof(
unsigned), it = strings.begin(); it != strings.end();
183 const string &str = *it;
184 size_t l = str.size();
186 directory.insert(make_pair(str, p - data));
187 KMP_MEMCPY(p, str.c_str(), l);
193 ~StringTable() {
delete[] data; }
197 __int64 encode(
const string &str) {
200 if (str.size() <= 8) {
203 KMP_STRNCPY_S((
char *)&r,
sizeof(r), str.c_str(), 8);
207 map<string, unsigned>::const_iterator it = directory.find(str);
208 if (it == directory.end())
209 stop(
"StringTable::encode: String now found in string table");
210 ((
unsigned *)&r)[0] = 0;
211 ((
unsigned *)&r)[1] = (*it).second;
217 string decode(__int64 x)
const {
218 if (*(
unsigned *)&x == 0) {
220 unsigned &p = ((
unsigned *)&x)[1];
222 stop(
"StringTable::decode: Invalid string table lookup");
223 return string(data + p);
226 char *p = (
char *)&x;
229 for (i = 0; i < 8 && p[i]; ++i)
234 void write(ostream &os) { os.write(data, length); }
240 void computeExternalSymbols(
const char *fileName, set<string> *defined,
241 set<string> *undefined) {
244 unsigned symTabStart, symNEntries;
247 f.seekg(0, ios::end);
248 fileSize = f.tellg();
251 f >> symTabStart >> symNEntries;
253 f.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
255 printf(
"computeExternalSymbols: fileName='%s', fileSize = %lu, symTabStart " 256 "= %u, symNEntries = %u\n",
257 fileName, (
unsigned long)fileSize, symTabStart, symNEntries);
258 stop(
"computeExternalSymbols: Unexpected EOF 1");
260 StringTable stringTable(f);
261 if (f.tellg() != fileSize)
262 stop(
"computeExternalSymbols: Unexpected data after string table");
265 f.seekg(symTabStart);
269 for (
int i = 0; i < symNEntries; ++i) {
274 stop(
"computeExternalSymbols: Unexpected EOF 2");
277 stop(
"computeExternalSymbols: File read error");
279 f.seekg(e.nAux * 18, ios::cur);
283 if (e.storageClass == 2)
285 defined->insert(stringTable.decode(e.name));
287 undefined->insert(stringTable.decode(e.name));
294 void hideSymbols(
char *fileName,
const set<string> &hide) {
295 static const string prefix(
"__kmp_external_");
299 unsigned symTabStart, symNEntries;
301 rstream in(fileName);
303 in.seekg(0, ios::end);
304 fileSize = in.tellg();
307 in >> symTabStart >> symNEntries;
308 in.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
310 stop(
"hideSymbols: Unexpected EOF");
311 StringTable stringTableOld(in);
313 if (in.tellg() != fileSize)
314 stop(
"hideSymbols: Unexpected data after string table");
317 for (i = 0; i < symNEntries; ++i) {
320 in.seekg(symTabStart + i * 18);
322 stop(
"hideSymbols: Unexpected EOF");
325 stop(
"hideSymbols: File read error");
328 const string &s = stringTableOld.decode(e.name);
332 (e.storageClass == 2 && hide.find(s) != hide.end()) ? prefix + s : s);
335 ofstream out(fileName, ios::trunc | ios::out | ios::binary);
337 stop(
"hideSymbols: Error opening output file");
340 StringTable stringTableNew = StringTable(strings);
344 char *buf =
new char[symTabStart];
345 in.read(buf, symTabStart);
346 out.write(buf, symTabStart);
350 for (i = 0; i < symNEntries; ++i) {
353 in.seekg(symTabStart + i * 18);
355 stop(
"hideSymbols: Unexpected EOF");
358 stop(
"hideSymbols: File read error");
359 const string &s = stringTableOld.decode(e.name);
360 out.seekp(symTabStart + i * 18);
361 e.name = stringTableNew.encode(
362 (e.storageClass == 2 && hide.find(s) != hide.end()) ? prefix + s : s);
363 out.write((
char *)&e, 18);
365 stop(
"hideSymbols: File write error");
369 for (
int j = 1; j <= nAux; ++j) {
371 out.seekp(symTabStart + (i + j) * 18);
372 out.write((
char *)&e, 18);
378 stringTableNew.write(out);
382 template <
class T>
bool isDisjoint(
const set<T> &a,
const set<T> &b) {
383 set<T>::const_iterator ita, itb;
385 for (ita = a.begin(), itb = b.begin(); ita != a.end() && itb != b.end();) {
386 const T &ta = *ita, &tb = *itb;
404 set<int> *findRequiredExternal(
int nExternal,
int nTotal, set<string> *defined,
405 set<string> *undefined) {
406 set<int> *required =
new set<int>;
411 for (i = nTotal - 1; i >= nExternal; --i)
412 fresh[cur].insert(i);
415 for (set<int>::iterator it = fresh[cur].begin(); it != fresh[cur].end();
417 set<string> &s = undefined[*it];
419 for (i = 0; i < nExternal; ++i) {
420 if (required->find(i) == required->end()) {
421 if (!isDisjoint(defined[i], s)) {
424 fresh[1 - cur].insert(i);
436 int main(
int argc,
char **argv) {
437 int nExternal, nInternal, i;
438 set<string> *defined, *undefined;
439 set<int>::iterator it;
442 stop(
"Please specify a positive integer followed by a list of object " 444 nExternal = atoi(argv[1]);
446 stop(
"Please specify a positive integer followed by a list of object " 448 if (nExternal + 2 > argc)
449 stop(
"Too few external objects");
450 nInternal = argc - nExternal - 2;
451 defined =
new set<string>[argc - 2];
452 undefined =
new set<string>[argc - 2];
455 for (i = 2; i < argc; ++i)
456 computeExternalSymbols(argv[i], defined + i - 2, undefined + i - 2);
459 set<int> *requiredExternal =
460 findRequiredExternal(nExternal, argc - 2, defined, undefined);
465 for (it = requiredExternal->begin(); it != requiredExternal->end(); ++it) {
467 set<string>::iterator it2;
471 for (it2 = defined[idx].begin(); it2 != defined[idx].end(); ++it2)
477 for (i = 0; i < nExternal; ++i)
478 if (requiredExternal->find(i) != requiredExternal->end())
479 hideSymbols(argv[2 + i], hide);
483 for (i = nExternal + 2; i < argc; ++i)
484 hideSymbols(argv[i], hide);