60 void stop(
char* errorMsg) {
61 printf(
"%s\n", errorMsg);
70 unsigned short sectionNum, type;
71 char storageClass, nAux;
74 class _rstream :
public istrstream {
78 _rstream(pair<const char*, streamsize> p):istrstream(p.first,p.second),buf(p.first){}
88 class rstream :
public _rstream {
91 inline rstream& doRead(T &x) {
92 read((
char*)&x,
sizeof(T));
95 static pair<const char*, streamsize> getBuf(
const char *fileName) {
96 ifstream raw(fileName,ios::binary | ios::in);
98 stop(
"rstream.getBuf: Error opening file");
99 raw.seekg(0,ios::end);
100 streampos fileSize = raw.tellg();
102 stop(
"rstream.getBuf: Error reading file");
103 char *buf =
new char[fileSize];
104 raw.seekg(0,ios::beg);
105 raw.read(buf, fileSize);
106 return pair<const char*, streamsize>(buf,fileSize);
110 rstream(
const char *buf,streamsize size):_rstream(pair<const char*,streamsize>(buf, size)){}
114 rstream(
const char *fileName):_rstream(getBuf(fileName)){}
115 rstream& operator>>(
int &x) {
118 rstream& operator>>(
unsigned &x) {
121 rstream& operator>>(
short &x) {
124 rstream& operator>>(
unsigned short &x) {
127 rstream& operator>>(Symbol &e) {
136 map<string, unsigned> directory;
141 void makeDirectory(
void) {
144 string s = string(data + i);
145 directory.insert(make_pair(s, i));
150 void init(
const char *_data) {
151 unsigned _length = *(
unsigned*)_data;
153 if(_length <
sizeof(
unsigned) || _length != *(
unsigned*)_data)
154 stop(
"StringTable.init: Invalid symbol table");
155 if(_data[_length - 1]) {
157 data =
new char[length = _length + 1];
160 data =
new char[length = _length];
162 *(
unsigned*)data = length;
163 memcpy(data +
sizeof(
unsigned), _data +
sizeof(
unsigned),
164 length -
sizeof(
unsigned));
168 StringTable(rstream &f) {
177 if(strSize <
sizeof(
unsigned))
178 stop(
"StringTable: Invalid string table");
179 strData =
new char[strSize];
180 *(
unsigned*)strData = strSize;
182 f.read(strData +
sizeof(
unsigned), strSize -
sizeof(
unsigned));
185 stop(
"StringTable: Unexpected EOF");
189 StringTable(
const set<string> &strings) {
193 set<string>::const_iterator it;
197 for(length =
sizeof(
unsigned), it = strings.begin(); it != strings.end(); ++it) {
198 size_t l = (*it).size();
200 if(l > (
unsigned) 0xFFFFFFFF)
201 stop(
"StringTable: String too long");
204 if(length > (
unsigned) 0xFFFFFFFF)
205 stop(
"StringTable: Symbol table too long");
208 data =
new char[length];
209 *(
unsigned*)data = length;
211 for(p = data +
sizeof(
unsigned), it = strings.begin(); it != strings.end(); ++it) {
212 const string &str = *it;
213 size_t l = str.size();
215 directory.insert(make_pair(str, p - data));
216 memcpy(p, str.c_str(), l);
229 __int64 encode(
const string &str) {
232 if(str.size() <= 8) {
235 strncpy((
char*)&r, str.c_str(), 8);
239 map<string,unsigned>::const_iterator it = directory.find(str);
240 if(it == directory.end())
241 stop(
"StringTable::encode: String now found in string table");
242 ((
unsigned*)&r)[0] = 0;
243 ((
unsigned*)&r)[1] = (*it).second;
251 string decode(__int64 x)
const {
252 if(*(
unsigned*)&x == 0) {
254 unsigned &p = ((
unsigned*)&x)[1];
256 stop(
"StringTable::decode: Invalid string table lookup");
257 return string(data + p);
263 for(i = 0; i < 8 && p[i]; ++i);
267 void write(ostream &os) {
268 os.write(data, length);
275 void computeExternalSymbols(
const char *fileName, set<string> *defined, set<string> *undefined){
278 unsigned symTabStart, symNEntries;
282 fileSize = f.tellg();
285 f >> symTabStart >> symNEntries;
287 f.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
289 printf(
"computeExternalSymbols: fileName='%s', fileSize = %lu, symTabStart = %u, symNEntries = %u\n",
290 fileName, (
unsigned long) fileSize, symTabStart, symNEntries);
291 stop(
"computeExternalSymbols: Unexpected EOF 1");
293 StringTable stringTable(f);
294 if(f.tellg() != fileSize)
295 stop(
"computeExternalSymbols: Unexpected data after string table");
298 f.seekg(symTabStart);
300 defined->clear(); undefined->clear();
301 for(
int i = 0; i < symNEntries; ++i) {
306 stop(
"computeExternalSymbols: Unexpected EOF 2");
309 stop(
"computeExternalSymbols: File read error");
311 f.seekg(e.nAux * 18, ios::cur);
315 if(e.storageClass == 2)
317 defined->insert(stringTable.decode(e.name));
319 undefined->insert(stringTable.decode(e.name));
327 void hideSymbols(
char *fileName,
const set<string> &hide) {
328 static const string prefix(
"__kmp_external_");
332 unsigned symTabStart, symNEntries;
334 rstream in(fileName);
336 in.seekg(0,ios::end);
337 fileSize = in.tellg();
340 in >> symTabStart >> symNEntries;
341 in.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
343 stop(
"hideSymbols: Unexpected EOF");
344 StringTable stringTableOld(in);
346 if(in.tellg() != fileSize)
347 stop(
"hideSymbols: Unexpected data after string table");
350 for(i = 0; i < symNEntries; ++i) {
353 in.seekg(symTabStart + i * 18);
355 stop(
"hideSymbols: Unexpected EOF");
358 stop(
"hideSymbols: File read error");
361 const string &s = stringTableOld.decode(e.name);
364 strings.insert( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
368 ofstream out(fileName, ios::trunc | ios::out | ios::binary);
370 stop(
"hideSymbols: Error opening output file");
373 StringTable stringTableNew = StringTable(strings);
377 char *buf =
new char[symTabStart];
378 in.read(buf, symTabStart);
379 out.write(buf, symTabStart);
383 for(i = 0; i < symNEntries; ++i) {
386 in.seekg(symTabStart + i*18);
388 stop(
"hideSymbols: Unexpected EOF");
391 stop(
"hideSymbols: File read error");
392 const string &s = stringTableOld.decode(e.name);
393 out.seekp(symTabStart + i*18);
394 e.name = stringTableNew.encode( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
396 out.write((
char*)&e, 18);
398 stop(
"hideSymbols: File write error");
402 for(
int j = 1; j <= nAux; ++j) {
404 out.seekp(symTabStart + (i + j) * 18);
405 out.write((
char*)&e, 18);
411 stringTableNew.write(out);
416 bool isDisjoint(
const set<T> &a,
const set<T> &b) {
417 set<T>::const_iterator ita, itb;
419 for(ita = a.begin(), itb = b.begin(); ita != a.end() && itb != b.end();) {
420 const T &ta = *ita, &tb = *itb;
438 set<int> *findRequiredExternal(
int nExternal,
int nTotal, set<string> *defined, set<string> *undefined) {
439 set<int> *required =
new set<int>;
444 for(i = nTotal - 1; i >= nExternal; --i)
445 fresh[cur].insert(i);
448 for(set<int>::iterator it = fresh[cur].begin(); it != fresh[cur].end(); ++it) {
449 set<string> &s = undefined[*it];
451 for(i = 0; i < nExternal; ++i) {
452 if(required->find(i) == required->end()) {
453 if(!isDisjoint(defined[i], s)) {
456 fresh[1 - cur].insert(i);
468 int main(
int argc,
char **argv) {
469 int nExternal, nInternal, i;
470 set<string> *defined, *undefined;
471 set<int>::iterator it;
474 stop(
"Please specify a positive integer followed by a list of object filenames");
475 nExternal = atoi(argv[1]);
477 stop(
"Please specify a positive integer followed by a list of object filenames");
478 if(nExternal + 2 > argc)
479 stop(
"Too few external objects");
480 nInternal = argc - nExternal - 2;
481 defined =
new set<string>[argc - 2];
482 undefined =
new set<string>[argc - 2];
485 for(i = 2; i < argc; ++i)
486 computeExternalSymbols(argv[i], defined + i - 2, undefined + i - 2);
489 set<int> *requiredExternal = findRequiredExternal(nExternal, argc - 2, defined, undefined);
495 for(it = requiredExternal->begin(); it != requiredExternal->end(); ++it) {
497 set<string>::iterator it2;
502 for(it2 = defined[idx].begin(); it2 != defined[idx].end(); ++it2)
509 for(i = 0; i < nExternal; ++i)
510 if(requiredExternal->find(i) != requiredExternal->end())
511 hideSymbols(argv[2 + i], hide);
515 for(i = nExternal + 2; i < argc; ++i)
516 hideSymbols(argv[i], hide);