39 void stop(
char* errorMsg) {
40 printf(
"%s\n", errorMsg);
49 unsigned short sectionNum, type;
50 char storageClass, nAux;
53 class _rstream :
public istrstream {
57 _rstream(pair<const char*, streamsize> p):istrstream(p.first,p.second),buf(p.first){}
67 class rstream :
public _rstream {
70 inline rstream& doRead(T &x) {
71 read((
char*)&x,
sizeof(T));
74 static pair<const char*, streamsize> getBuf(
const char *fileName) {
75 ifstream raw(fileName,ios::binary | ios::in);
77 stop(
"rstream.getBuf: Error opening file");
78 raw.seekg(0,ios::end);
79 streampos fileSize = raw.tellg();
81 stop(
"rstream.getBuf: Error reading file");
82 char *buf =
new char[fileSize];
83 raw.seekg(0,ios::beg);
84 raw.read(buf, fileSize);
85 return pair<const char*, streamsize>(buf,fileSize);
89 rstream(
const char *buf,streamsize size):_rstream(pair<const char*,streamsize>(buf, size)){}
93 rstream(
const char *fileName):_rstream(getBuf(fileName)){}
94 rstream& operator>>(
int &x) {
97 rstream& operator>>(
unsigned &x) {
100 rstream& operator>>(
short &x) {
103 rstream& operator>>(
unsigned short &x) {
106 rstream& operator>>(Symbol &e) {
115 map<string, unsigned> directory;
120 void makeDirectory(
void) {
123 string s = string(data + i);
124 directory.insert(make_pair(s, i));
129 void init(
const char *_data) {
130 unsigned _length = *(
unsigned*)_data;
132 if(_length <
sizeof(
unsigned) || _length != *(
unsigned*)_data)
133 stop(
"StringTable.init: Invalid symbol table");
134 if(_data[_length - 1]) {
136 data =
new char[length = _length + 1];
139 data =
new char[length = _length];
141 *(
unsigned*)data = length;
142 KMP_MEMCPY(data +
sizeof(
unsigned), _data +
sizeof(
unsigned),
143 length -
sizeof(
unsigned));
147 StringTable(rstream &f) {
156 if(strSize <
sizeof(
unsigned))
157 stop(
"StringTable: Invalid string table");
158 strData =
new char[strSize];
159 *(
unsigned*)strData = strSize;
161 f.read(strData +
sizeof(
unsigned), strSize -
sizeof(
unsigned));
164 stop(
"StringTable: Unexpected EOF");
168 StringTable(
const set<string> &strings) {
172 set<string>::const_iterator it;
176 for(length =
sizeof(
unsigned), it = strings.begin(); it != strings.end(); ++it) {
177 size_t l = (*it).size();
179 if(l > (
unsigned) 0xFFFFFFFF)
180 stop(
"StringTable: String too long");
183 if(length > (
unsigned) 0xFFFFFFFF)
184 stop(
"StringTable: Symbol table too long");
187 data =
new char[length];
188 *(
unsigned*)data = length;
190 for(p = data +
sizeof(
unsigned), it = strings.begin(); it != strings.end(); ++it) {
191 const string &str = *it;
192 size_t l = str.size();
194 directory.insert(make_pair(str, p - data));
195 KMP_MEMCPY(p, str.c_str(), l);
208 __int64 encode(
const string &str) {
211 if(str.size() <= 8) {
214 KMP_STRNCPY_S((
char*)&r,
sizeof(r), str.c_str(), 8);
218 map<string,unsigned>::const_iterator it = directory.find(str);
219 if(it == directory.end())
220 stop(
"StringTable::encode: String now found in string table");
221 ((
unsigned*)&r)[0] = 0;
222 ((
unsigned*)&r)[1] = (*it).second;
230 string decode(__int64 x)
const {
231 if(*(
unsigned*)&x == 0) {
233 unsigned &p = ((
unsigned*)&x)[1];
235 stop(
"StringTable::decode: Invalid string table lookup");
236 return string(data + p);
242 for(i = 0; i < 8 && p[i]; ++i);
246 void write(ostream &os) {
247 os.write(data, length);
254 void computeExternalSymbols(
const char *fileName, set<string> *defined, set<string> *undefined){
257 unsigned symTabStart, symNEntries;
261 fileSize = f.tellg();
264 f >> symTabStart >> symNEntries;
266 f.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
268 printf(
"computeExternalSymbols: fileName='%s', fileSize = %lu, symTabStart = %u, symNEntries = %u\n",
269 fileName, (
unsigned long) fileSize, symTabStart, symNEntries);
270 stop(
"computeExternalSymbols: Unexpected EOF 1");
272 StringTable stringTable(f);
273 if(f.tellg() != fileSize)
274 stop(
"computeExternalSymbols: Unexpected data after string table");
277 f.seekg(symTabStart);
279 defined->clear(); undefined->clear();
280 for(
int i = 0; i < symNEntries; ++i) {
285 stop(
"computeExternalSymbols: Unexpected EOF 2");
288 stop(
"computeExternalSymbols: File read error");
290 f.seekg(e.nAux * 18, ios::cur);
294 if(e.storageClass == 2)
296 defined->insert(stringTable.decode(e.name));
298 undefined->insert(stringTable.decode(e.name));
306 void hideSymbols(
char *fileName,
const set<string> &hide) {
307 static const string prefix(
"__kmp_external_");
311 unsigned symTabStart, symNEntries;
313 rstream in(fileName);
315 in.seekg(0,ios::end);
316 fileSize = in.tellg();
319 in >> symTabStart >> symNEntries;
320 in.seekg(strTabStart = symTabStart + 18 * (
size_t)symNEntries);
322 stop(
"hideSymbols: Unexpected EOF");
323 StringTable stringTableOld(in);
325 if(in.tellg() != fileSize)
326 stop(
"hideSymbols: Unexpected data after string table");
329 for(i = 0; i < symNEntries; ++i) {
332 in.seekg(symTabStart + i * 18);
334 stop(
"hideSymbols: Unexpected EOF");
337 stop(
"hideSymbols: File read error");
340 const string &s = stringTableOld.decode(e.name);
343 strings.insert( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
347 ofstream out(fileName, ios::trunc | ios::out | ios::binary);
349 stop(
"hideSymbols: Error opening output file");
352 StringTable stringTableNew = StringTable(strings);
356 char *buf =
new char[symTabStart];
357 in.read(buf, symTabStart);
358 out.write(buf, symTabStart);
362 for(i = 0; i < symNEntries; ++i) {
365 in.seekg(symTabStart + i*18);
367 stop(
"hideSymbols: Unexpected EOF");
370 stop(
"hideSymbols: File read error");
371 const string &s = stringTableOld.decode(e.name);
372 out.seekp(symTabStart + i*18);
373 e.name = stringTableNew.encode( (e.storageClass == 2 && hide.find(s) != hide.end()) ?
375 out.write((
char*)&e, 18);
377 stop(
"hideSymbols: File write error");
381 for(
int j = 1; j <= nAux; ++j) {
383 out.seekp(symTabStart + (i + j) * 18);
384 out.write((
char*)&e, 18);
390 stringTableNew.write(out);
395 bool isDisjoint(
const set<T> &a,
const set<T> &b) {
396 set<T>::const_iterator ita, itb;
398 for(ita = a.begin(), itb = b.begin(); ita != a.end() && itb != b.end();) {
399 const T &ta = *ita, &tb = *itb;
417 set<int> *findRequiredExternal(
int nExternal,
int nTotal, set<string> *defined, set<string> *undefined) {
418 set<int> *required =
new set<int>;
423 for(i = nTotal - 1; i >= nExternal; --i)
424 fresh[cur].insert(i);
427 for(set<int>::iterator it = fresh[cur].begin(); it != fresh[cur].end(); ++it) {
428 set<string> &s = undefined[*it];
430 for(i = 0; i < nExternal; ++i) {
431 if(required->find(i) == required->end()) {
432 if(!isDisjoint(defined[i], s)) {
435 fresh[1 - cur].insert(i);
447 int main(
int argc,
char **argv) {
448 int nExternal, nInternal, i;
449 set<string> *defined, *undefined;
450 set<int>::iterator it;
453 stop(
"Please specify a positive integer followed by a list of object filenames");
454 nExternal = atoi(argv[1]);
456 stop(
"Please specify a positive integer followed by a list of object filenames");
457 if(nExternal + 2 > argc)
458 stop(
"Too few external objects");
459 nInternal = argc - nExternal - 2;
460 defined =
new set<string>[argc - 2];
461 undefined =
new set<string>[argc - 2];
464 for(i = 2; i < argc; ++i)
465 computeExternalSymbols(argv[i], defined + i - 2, undefined + i - 2);
468 set<int> *requiredExternal = findRequiredExternal(nExternal, argc - 2, defined, undefined);
474 for(it = requiredExternal->begin(); it != requiredExternal->end(); ++it) {
476 set<string>::iterator it2;
481 for(it2 = defined[idx].begin(); it2 != defined[idx].end(); ++it2)
488 for(i = 0; i < nExternal; ++i)
489 if(requiredExternal->find(i) != requiredExternal->end())
490 hideSymbols(argv[2 + i], hide);
494 for(i = nExternal + 2; i < argc; ++i)
495 hideSymbols(argv[i], hide);