37 void stop(
char *errorMsg) {
38 printf(
"%s\n", errorMsg);
47 unsigned short sectionNum, type;
48 char storageClass, nAux;
51 class _rstream :
public istrstream {
56 _rstream(pair<const char *, streamsize> p)
57 : istrstream(p.first, p.second), buf(p.first) {}
58 ~_rstream() {
delete[] buf; }
64 class rstream :
public _rstream {
66 template <
class T>
inline rstream &doRead(T &x) {
67 read((
char *)&x,
sizeof(T));
70 static pair<const char *, streamsize> getBuf(
const char *fileName) {
71 ifstream raw(fileName, ios::binary | ios::in);
73 stop(
"rstream.getBuf: Error opening file");
74 raw.seekg(0, ios::end);
75 streampos fileSize = raw.tellg();
77 stop(
"rstream.getBuf: Error reading file");
78 char *buf =
new char[fileSize];
79 raw.seekg(0, ios::beg);
80 raw.read(buf, fileSize);
81 return pair<const char *, streamsize>(buf, fileSize);
86 rstream(
const char *buf, streamsize size)
87 : _rstream(pair<const char *, streamsize>(buf, size)) {}
90 rstream(
const char *fileName) : _rstream(getBuf(fileName)) {}
91 rstream &operator>>(
int &x) {
return doRead(x); }
92 rstream &operator>>(
unsigned &x) {
return doRead(x); }
93 rstream &operator>>(
short &x) {
return doRead(x); }
94 rstream &operator>>(
unsigned short &x) {
return doRead(x); }
95 rstream &operator>>(Symbol &e) {
104 map<string, unsigned> directory;
109 void makeDirectory(
void) {
112 string s = string(data + i);
113 directory.insert(make_pair(s, i));
118 void init(
const char *_data) {
119 unsigned _length = *(
unsigned *)_data;
121 if (_length <
sizeof(
unsigned) || _length != *(
unsigned *)_data)
122 stop(
"StringTable.init: Invalid symbol table");
123 if (_data[_length - 1]) {
125 data =
new char[length = _length + 1];
128 data =
new char[length = _length];
130 *(
unsigned *)data = length;
131 KMP_MEMCPY(data +
sizeof(
unsigned), _data +
sizeof(
unsigned),
132 length -
sizeof(
unsigned));
137 StringTable(rstream &f) {
145 if (strSize <
sizeof(
unsigned))
146 stop(
"StringTable: Invalid string table");
147 strData =
new char[strSize];
148 *(
unsigned *)strData = strSize;
150 f.read(strData +
sizeof(
unsigned), strSize -
sizeof(
unsigned));
153 stop(
"StringTable: Unexpected EOF");
157 StringTable(
const set<string> &strings) {
160 set<string>::const_iterator it;
164 for (length =
sizeof(
unsigned), it = strings.begin(); it != strings.end();
166 size_t l = (*it).size();
168 if (l > (
unsigned)0xFFFFFFFF)
169 stop(
"StringTable: String too long");
172 if (length > (
unsigned)0xFFFFFFFF)
173 stop(
"StringTable: Symbol table too long");
176 data =
new char[length];
177 *(
unsigned *)data = length;
179 for (p = data +
sizeof(
unsigned), it = strings.begin(); it != strings.end();
181 const string &str = *it;
182 size_t l = str.size();
184 directory.insert(make_pair(str, p - data));
185 KMP_MEMCPY(p, str.c_str(), l);
191 ~StringTable() {
delete[] data; }
195 __int64 encode(
const string &str) {
198 if (str.size() <= 8) {
201 KMP_STRNCPY_S((
char *)&r,
sizeof(r), str.c_str(), 8);
205 map<string, unsigned>::const_iterator it = directory.find(str);
206 if (it == directory.end())
207 stop(
"StringTable::encode: String now found in string table");
208 ((
unsigned *)&r)[0] = 0;
209 ((
unsigned *)&r)[1] = (*it).second;
215 string decode(__int64 x)
const {
216 if (*(
unsigned *)&x == 0) {
218 unsigned &p = ((
unsigned *)&x)[1];
220 stop(
"StringTable::decode: Invalid string table lookup");
221 return string(data + p);
224 char *p = (
char *)&x;
227 for (i = 0; i < 8 && p[i]; ++i)
232 void write(ostream &os) { os.write(data, length); }
238 void computeExternalSymbols(
const char *fileName, set<string> *defined,
239 set<string> *undefined) {
242 unsigned symTabStart, symNEntries;
245 f.seekg(0, ios::end);
246 fileSize = f.tellg();
249 f >> symTabStart >> symNEntries;
251 f.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
253 printf(
"computeExternalSymbols: fileName='%s', fileSize = %lu, symTabStart " 254 "= %u, symNEntries = %u\n",
255 fileName, (
unsigned long)fileSize, symTabStart, symNEntries);
256 stop(
"computeExternalSymbols: Unexpected EOF 1");
258 StringTable stringTable(f);
259 if (f.tellg() != fileSize)
260 stop(
"computeExternalSymbols: Unexpected data after string table");
263 f.seekg(symTabStart);
267 for (
int i = 0; i < symNEntries; ++i) {
272 stop(
"computeExternalSymbols: Unexpected EOF 2");
275 stop(
"computeExternalSymbols: File read error");
277 f.seekg(e.nAux * 18, ios::cur);
281 if (e.storageClass == 2)
283 defined->insert(stringTable.decode(e.name));
285 undefined->insert(stringTable.decode(e.name));
292 void hideSymbols(
char *fileName,
const set<string> &hide) {
293 static const string prefix(
"__kmp_external_");
297 unsigned symTabStart, symNEntries;
299 rstream in(fileName);
301 in.seekg(0, ios::end);
302 fileSize = in.tellg();
305 in >> symTabStart >> symNEntries;
306 in.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
308 stop(
"hideSymbols: Unexpected EOF");
309 StringTable stringTableOld(in);
311 if (in.tellg() != fileSize)
312 stop(
"hideSymbols: Unexpected data after string table");
315 for (i = 0; i < symNEntries; ++i) {
318 in.seekg(symTabStart + i * 18);
320 stop(
"hideSymbols: Unexpected EOF");
323 stop(
"hideSymbols: File read error");
326 const string &s = stringTableOld.decode(e.name);
330 (e.storageClass == 2 && hide.find(s) != hide.end()) ? prefix + s : s);
333 ofstream out(fileName, ios::trunc | ios::out | ios::binary);
335 stop(
"hideSymbols: Error opening output file");
338 StringTable stringTableNew = StringTable(strings);
342 char *buf =
new char[symTabStart];
343 in.read(buf, symTabStart);
344 out.write(buf, symTabStart);
348 for (i = 0; i < symNEntries; ++i) {
351 in.seekg(symTabStart + i * 18);
353 stop(
"hideSymbols: Unexpected EOF");
356 stop(
"hideSymbols: File read error");
357 const string &s = stringTableOld.decode(e.name);
358 out.seekp(symTabStart + i * 18);
359 e.name = stringTableNew.encode(
360 (e.storageClass == 2 && hide.find(s) != hide.end()) ? prefix + s : s);
361 out.write((
char *)&e, 18);
363 stop(
"hideSymbols: File write error");
367 for (
int j = 1; j <= nAux; ++j) {
369 out.seekp(symTabStart + (i + j) * 18);
370 out.write((
char *)&e, 18);
376 stringTableNew.write(out);
380 template <
class T>
bool isDisjoint(
const set<T> &a,
const set<T> &b) {
381 set<T>::const_iterator ita, itb;
383 for (ita = a.begin(), itb = b.begin(); ita != a.end() && itb != b.end();) {
384 const T &ta = *ita, &tb = *itb;
402 set<int> *findRequiredExternal(
int nExternal,
int nTotal, set<string> *defined,
403 set<string> *undefined) {
404 set<int> *required =
new set<int>;
409 for (i = nTotal - 1; i >= nExternal; --i)
410 fresh[cur].insert(i);
413 for (set<int>::iterator it = fresh[cur].begin(); it != fresh[cur].end();
415 set<string> &s = undefined[*it];
417 for (i = 0; i < nExternal; ++i) {
418 if (required->find(i) == required->end()) {
419 if (!isDisjoint(defined[i], s)) {
422 fresh[1 - cur].insert(i);
434 int main(
int argc,
char **argv) {
435 int nExternal, nInternal, i;
436 set<string> *defined, *undefined;
437 set<int>::iterator it;
440 stop(
"Please specify a positive integer followed by a list of object " 442 nExternal = atoi(argv[1]);
444 stop(
"Please specify a positive integer followed by a list of object " 446 if (nExternal + 2 > argc)
447 stop(
"Too few external objects");
448 nInternal = argc - nExternal - 2;
449 defined =
new set<string>[argc - 2];
450 undefined =
new set<string>[argc - 2];
453 for (i = 2; i < argc; ++i)
454 computeExternalSymbols(argv[i], defined + i - 2, undefined + i - 2);
457 set<int> *requiredExternal =
458 findRequiredExternal(nExternal, argc - 2, defined, undefined);
463 for (it = requiredExternal->begin(); it != requiredExternal->end(); ++it) {
465 set<string>::iterator it2;
469 for (it2 = defined[idx].begin(); it2 != defined[idx].end(); ++it2)
475 for (i = 0; i < nExternal; ++i)
476 if (requiredExternal->find(i) != requiredExternal->end())
477 hideSymbols(argv[2 + i], hide);
481 for (i = nExternal + 2; i < argc; ++i)
482 hideSymbols(argv[i], hide);