58 void stop(
char* errorMsg) {
59 printf(
"%s\n", errorMsg);
68 unsigned short sectionNum, type;
69 char storageClass, nAux;
72 class _rstream :
public istrstream {
76 _rstream(pair<const char*, streamsize> p):istrstream(p.first,p.second),buf(p.first){}
86 class rstream :
public _rstream {
89 inline rstream& doRead(T &x) {
90 read((
char*)&x,
sizeof(T));
93 static pair<const char*, streamsize> getBuf(
const char *fileName) {
94 ifstream raw(fileName,ios::binary | ios::in);
96 stop(
"rstream.getBuf: Error opening file");
97 raw.seekg(0,ios::end);
98 streampos fileSize = raw.tellg();
100 stop(
"rstream.getBuf: Error reading file");
101 char *buf =
new char[fileSize];
102 raw.seekg(0,ios::beg);
103 raw.read(buf, fileSize);
104 return pair<const char*, streamsize>(buf,fileSize);
108 rstream(
const char *buf,streamsize size):_rstream(pair<const char*,streamsize>(buf, size)){}
112 rstream(
const char *fileName):_rstream(getBuf(fileName)){}
113 rstream& operator>>(
int &x) {
116 rstream& operator>>(
unsigned &x) {
119 rstream& operator>>(
short &x) {
122 rstream& operator>>(
unsigned short &x) {
125 rstream& operator>>(Symbol &e) {
134 map<string, unsigned> directory;
139 void makeDirectory(
void) {
142 string s = string(data + i);
143 directory.insert(make_pair(s, i));
148 void init(
const char *_data) {
149 unsigned _length = *(
unsigned*)_data;
151 if(_length <
sizeof(
unsigned) || _length != *(
unsigned*)_data)
152 stop(
"StringTable.init: Invalid symbol table");
153 if(_data[_length - 1]) {
155 data =
new char[length = _length + 1];
158 data =
new char[length = _length];
160 *(
unsigned*)data = length;
161 KMP_MEMCPY(data +
sizeof(
unsigned), _data +
sizeof(
unsigned),
162 length -
sizeof(
unsigned));
166 StringTable(rstream &f) {
175 if(strSize <
sizeof(
unsigned))
176 stop(
"StringTable: Invalid string table");
177 strData =
new char[strSize];
178 *(
unsigned*)strData = strSize;
180 f.read(strData +
sizeof(
unsigned), strSize -
sizeof(
unsigned));
183 stop(
"StringTable: Unexpected EOF");
187 StringTable(
const set<string> &strings) {
191 set<string>::const_iterator it;
195 for(length =
sizeof(
unsigned), it = strings.begin(); it != strings.end(); ++it) {
196 size_t l = (*it).size();
198 if(l > (
unsigned) 0xFFFFFFFF)
199 stop(
"StringTable: String too long");
202 if(length > (
unsigned) 0xFFFFFFFF)
203 stop(
"StringTable: Symbol table too long");
206 data =
new char[length];
207 *(
unsigned*)data = length;
209 for(p = data +
sizeof(
unsigned), it = strings.begin(); it != strings.end(); ++it) {
210 const string &str = *it;
211 size_t l = str.size();
213 directory.insert(make_pair(str, p - data));
214 KMP_MEMCPY(p, str.c_str(), l);
227 __int64 encode(
const string &str) {
230 if(str.size() <= 8) {
233 KMP_STRNCPY_S((
char*)&r,
sizeof(r), str.c_str(), 8);
237 map<string,unsigned>::const_iterator it = directory.find(str);
238 if(it == directory.end())
239 stop(
"StringTable::encode: String now found in string table");
240 ((
unsigned*)&r)[0] = 0;
241 ((
unsigned*)&r)[1] = (*it).second;
249 string decode(__int64 x)
const {
250 if(*(
unsigned*)&x == 0) {
252 unsigned &p = ((
unsigned*)&x)[1];
254 stop(
"StringTable::decode: Invalid string table lookup");
255 return string(data + p);
261 for(i = 0; i < 8 && p[i]; ++i);
265 void write(ostream &os) {
266 os.write(data, length);
273 void computeExternalSymbols(
const char *fileName, set<string> *defined, set<string> *undefined){
276 unsigned symTabStart, symNEntries;
280 fileSize = f.tellg();
283 f >> symTabStart >> symNEntries;
285 f.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
287 printf(
"computeExternalSymbols: fileName='%s', fileSize = %lu, symTabStart = %u, symNEntries = %u\n",
288 fileName, (
unsigned long) fileSize, symTabStart, symNEntries);
289 stop(
"computeExternalSymbols: Unexpected EOF 1");
291 StringTable stringTable(f);
292 if(f.tellg() != fileSize)
293 stop(
"computeExternalSymbols: Unexpected data after string table");
296 f.seekg(symTabStart);
298 defined->clear(); undefined->clear();
299 for(
int i = 0; i < symNEntries; ++i) {
304 stop(
"computeExternalSymbols: Unexpected EOF 2");
307 stop(
"computeExternalSymbols: File read error");
309 f.seekg(e.nAux * 18, ios::cur);
313 if(e.storageClass == 2)
315 defined->insert(stringTable.decode(e.name));
317 undefined->insert(stringTable.decode(e.name));
325 void hideSymbols(
char *fileName,
const set<string> &hide) {
326 static const string prefix(
"__kmp_external_");
330 unsigned symTabStart, symNEntries;
332 rstream in(fileName);
334 in.seekg(0,ios::end);
335 fileSize = in.tellg();
338 in >> symTabStart >> symNEntries;
339 in.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
341 stop(
"hideSymbols: Unexpected EOF");
342 StringTable stringTableOld(in);
344 if(in.tellg() != fileSize)
345 stop(
"hideSymbols: Unexpected data after string table");
348 for(i = 0; i < symNEntries; ++i) {
351 in.seekg(symTabStart + i * 18);
353 stop(
"hideSymbols: Unexpected EOF");
356 stop(
"hideSymbols: File read error");
359 const string &s = stringTableOld.decode(e.name);
362 strings.insert( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
366 ofstream out(fileName, ios::trunc | ios::out | ios::binary);
368 stop(
"hideSymbols: Error opening output file");
371 StringTable stringTableNew = StringTable(strings);
375 char *buf =
new char[symTabStart];
376 in.read(buf, symTabStart);
377 out.write(buf, symTabStart);
381 for(i = 0; i < symNEntries; ++i) {
384 in.seekg(symTabStart + i*18);
386 stop(
"hideSymbols: Unexpected EOF");
389 stop(
"hideSymbols: File read error");
390 const string &s = stringTableOld.decode(e.name);
391 out.seekp(symTabStart + i*18);
392 e.name = stringTableNew.encode( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
394 out.write((
char*)&e, 18);
396 stop(
"hideSymbols: File write error");
400 for(
int j = 1; j <= nAux; ++j) {
402 out.seekp(symTabStart + (i + j) * 18);
403 out.write((
char*)&e, 18);
409 stringTableNew.write(out);
414 bool isDisjoint(
const set<T> &a,
const set<T> &b) {
415 set<T>::const_iterator ita, itb;
417 for(ita = a.begin(), itb = b.begin(); ita != a.end() && itb != b.end();) {
418 const T &ta = *ita, &tb = *itb;
436 set<int> *findRequiredExternal(
int nExternal,
int nTotal, set<string> *defined, set<string> *undefined) {
437 set<int> *required =
new set<int>;
442 for(i = nTotal - 1; i >= nExternal; --i)
443 fresh[cur].insert(i);
446 for(set<int>::iterator it = fresh[cur].begin(); it != fresh[cur].end(); ++it) {
447 set<string> &s = undefined[*it];
449 for(i = 0; i < nExternal; ++i) {
450 if(required->find(i) == required->end()) {
451 if(!isDisjoint(defined[i], s)) {
454 fresh[1 - cur].insert(i);
466 int main(
int argc,
char **argv) {
467 int nExternal, nInternal, i;
468 set<string> *defined, *undefined;
469 set<int>::iterator it;
472 stop(
"Please specify a positive integer followed by a list of object filenames");
473 nExternal = atoi(argv[1]);
475 stop(
"Please specify a positive integer followed by a list of object filenames");
476 if(nExternal + 2 > argc)
477 stop(
"Too few external objects");
478 nInternal = argc - nExternal - 2;
479 defined =
new set<string>[argc - 2];
480 undefined =
new set<string>[argc - 2];
483 for(i = 2; i < argc; ++i)
484 computeExternalSymbols(argv[i], defined + i - 2, undefined + i - 2);
487 set<int> *requiredExternal = findRequiredExternal(nExternal, argc - 2, defined, undefined);
493 for(it = requiredExternal->begin(); it != requiredExternal->end(); ++it) {
495 set<string>::iterator it2;
500 for(it2 = defined[idx].begin(); it2 != defined[idx].end(); ++it2)
507 for(i = 0; i < nExternal; ++i)
508 if(requiredExternal->find(i) != requiredExternal->end())
509 hideSymbols(argv[2 + i], hide);
513 for(i = nExternal + 2; i < argc; ++i)
514 hideSymbols(argv[i], hide);