00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <fcntl.h>
00029 #include <cctype>
00030 #include <string>
00031 #include <string.h>
00032 #include <vector>
00033 #ifndef WIN32
00034 # include <unistd.h>
00035 #else
00036 # define ssize_t int
00037 # include <io.h>
00038 # include <sys/types.h>
00039 # include "cygpath.h"
00040 #endif
00041
00042 #ifdef __APPLE__
00043 #include <AvailabilityMacros.h>
00044 #endif
00045 #if (defined(__FreeBSD__) && (__FreeBSD__ < 4)) || defined(__OpenBSD__) || \
00046 (defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_10_3) || \
00047 (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3)))
00048 #include <sys/file.h>
00049 #define lockf(fd, op, sz) flock((fd), (op))
00050 #ifndef F_LOCK
00051 #define F_LOCK (LOCK_EX | LOCK_NB)
00052 #endif
00053 #ifndef F_ULOCK
00054 #define F_ULOCK LOCK_UN
00055 #endif
00056 #endif
00057
00058 #if defined(__CYGWIN__) && defined(__GNUC__)
00059 #define F_LOCK F_WRLCK
00060 #define F_ULOCK F_UNLCK
00061 static int fcntl_lockf(int fd, int op, off_t off)
00062 {
00063 flock fl;
00064 fl.l_whence = SEEK_SET;
00065 fl.l_start = off;
00066 fl.l_len = 0;
00067 fl.l_pid = getpid();
00068 fl.l_type = op;
00069 return fcntl(fd, F_SETLK, &fl);
00070 }
00071 #define lockf fcntl_lockf
00072 #endif
00073
00074 const char *usage = "Usage: %s [-f] [<-r|-o> <mapfile>] -l <sofile> -d <depsofiles> -c <linkdeffiles>\n";
00075
00076 namespace std {}
00077 using namespace std;
00078
00079
00080 #ifdef WIN32
00081 #include <windows.h>
00082 #include <errno.h>
00083
00084 #define ftruncate(fd, size) win32_ftruncate(fd, size)
00085
00086
00087 int win32_ftruncate(int fd, ssize_t size)
00088 {
00089 HANDLE hfile;
00090 int curpos;
00091
00092 if (fd < 0) return -1;
00093
00094 hfile = (HANDLE) _get_osfhandle(fd);
00095 curpos = ::SetFilePointer(hfile, 0, 0, FILE_CURRENT);
00096 if (curpos == 0xFFFFFFFF ||
00097 ::SetFilePointer(hfile, size, 0, FILE_BEGIN) == 0xFFFFFFFF ||
00098 !::SetEndOfFile(hfile)) {
00099 int error = ::GetLastError();
00100
00101 switch (error) {
00102 case ERROR_INVALID_HANDLE:
00103 errno = EBADF;
00104 break;
00105 default:
00106 errno = EIO;
00107 break;
00108 }
00109 return -1;
00110 }
00111 return 0;
00112 }
00113
00114 #endif // WIN32
00115
00116
00117 char *Compress(const char *str)
00118 {
00119
00120
00121
00122 static const char* composedTypes[] = {"const ", "signed ","unsigned "};
00123 static unsigned int composedTypesLen[] = {6, 7, 9};
00124
00125 if (!str) return 0;
00126
00127 const char *p = str;
00128
00129 char *s, *s1 = new char[strlen(str)+20];
00130 s = s1;
00131
00132 while (*p) {
00133 if (*p != ' ') {
00134 for (unsigned int i = 0; i < sizeof(composedTypes) / sizeof(char*); ++i) {
00135 if (!strncmp(p, composedTypes[i], composedTypesLen[i])
00136 && (p == str || !isalnum(p[-1]))) {
00137
00138 memcpy(s, composedTypes[i], composedTypesLen[i] - 1);
00139 p += composedTypesLen[i] - 1;
00140 s += composedTypesLen[i] - 1;
00141 continue;
00142 }
00143 }
00144 *s++ = *p;
00145 }
00146 p++;
00147 }
00148 *s = '\0';
00149
00150 return s1;
00151 }
00152
00153
00154 void UnCompressTemplate(char*& str)
00155 {
00156
00157
00158
00159
00160
00161 char* pos = strstr(str, ">>");
00162 char* fixed = 0;
00163 int countgtgt = 0;
00164 while (pos) {
00165
00166 ++countgtgt;
00167 pos = strstr(pos+1, ">>");
00168 }
00169 if (!countgtgt)
00170 return;
00171 pos = strstr(str, ">>");
00172 while (pos && pos > str) {
00173 bool isop = false;
00174
00175 if (pos - str >= 8) {
00176 char* posop = pos - 1;
00177
00178 while (posop >= str && *posop == ' ')
00179 --posop;
00180 if (!strncmp("operator", posop - 7, 8)) {
00181
00182 isop = true;
00183 }
00184 }
00185 if (!isop) {
00186
00187 if (!fixed) {
00188 fixed = new char[strlen(str) + countgtgt + 1];
00189 strcpy(fixed, str);
00190 }
00191 fixed[pos - str + 1] = ' ';
00192 strcpy(fixed + (pos - str) + 2, pos + 1);
00193 }
00194 pos = strstr(pos + 1, ">>");
00195 }
00196 delete [] str;
00197 str = fixed;
00198 }
00199
00200
00201 int RemoveLib(const string &solib, bool fullpath, FILE *fp)
00202 {
00203
00204
00205 fseek(fp, 0, SEEK_SET);
00206
00207
00208 struct stat sbuf;
00209 fstat(fileno(fp), &sbuf);
00210 size_t siz = sbuf.st_size;
00211
00212 if (!siz) return 0;
00213
00214 const char *libbase = solib.c_str();
00215 if (!fullpath) {
00216 if ((libbase = strrchr(libbase, '/')))
00217 libbase++;
00218 }
00219
00220
00221 char *fbuf = new char[siz+1];
00222 char *fptr = fbuf;
00223
00224 while (fgets(fptr, 1+siz - size_t(fptr-fbuf), fp)) {
00225
00226 char *line = new char[strlen(fptr)+1];
00227 strcpy(line, fptr);
00228 strtok(line, " ");
00229 char *lib = strtok(0, " \n");
00230 if (lib && strcmp(lib, libbase)) {
00231 fptr += strlen(fptr);
00232 if (*(fptr-1) != '\n') {
00233 *fptr = '\n';
00234 fptr++;
00235 }
00236 }
00237 delete [] line;
00238
00239
00240 if ( (siz - size_t(fptr - fbuf)) <= 0)
00241 break;
00242 }
00243
00244 if (ftruncate(fileno(fp), 0)) {;}
00245
00246
00247 if (fptr != fbuf) {
00248 fseek(fp, 0, SEEK_SET);
00249 fwrite(fbuf, 1, size_t(fptr-fbuf), fp);
00250 }
00251
00252 delete [] fbuf;
00253
00254 fseek(fp, 0, SEEK_END);
00255
00256 return 0;
00257 }
00258
00259
00260 int LibMap(const string &solib, const vector<string> &solibdeps,
00261 const vector<string> &linkdefs, bool fullpath, FILE *fp)
00262 {
00263
00264
00265 vector<string> classes;
00266
00267 vector<string>::const_iterator lk;
00268 for (lk = linkdefs.begin(); lk != linkdefs.end(); lk++) {
00269 const char *linkdef = lk->c_str();
00270 FILE *lfp;
00271 char pragma[1024];
00272 if ((lfp = fopen(linkdef, "r"))) {
00273 while (fgets(pragma, 1024, lfp)) {
00274 if (strcmp(strtok(pragma, " "), "#pragma")) continue;
00275 const char* linkOrCreate = strtok(0, " ");
00276 bool pragmaLink = (!strcmp(linkOrCreate, "link") &&
00277 !strcmp(strtok(0, " "), "C++"));
00278 bool pragmaCreate = (!strcmp(linkOrCreate, "create") &&
00279 !strcmp(strtok(0," "), "TClass"));
00280
00281 if (pragmaLink || pragmaCreate) {
00282 const char *type = pragmaLink ? strtok(0, " ") : "class";
00283 if (!strncmp(type, "option=", 7) || !strncmp(type, "options=", 8)) {
00284 if (strstr(type, "nomap"))
00285 continue;
00286 type = strtok(0, " ");
00287 }
00288
00289 if (!strncmp(type, "class", 5) || !strcmp(type, "typedef")) {
00290 char *cls = strtok(0, "-!+;");
00291
00292 while (*cls == ' ') cls++;
00293 int len = strlen(cls) - 1;
00294 while (cls[len] == ' ' || cls[len] == '\t')
00295 cls[len--] = '\0';
00296
00297 cls = Compress(cls);
00298
00299 UnCompressTemplate(cls);
00300
00301
00302 if (!strncmp(cls, "vector<string>", 14) ||
00303 !strncmp(cls, "std::pair<", 10))
00304 continue;
00305
00306
00307 char *s = cls;
00308 while (*s) {
00309 if (*s == ':')
00310 *s = '@';
00311 else if (*s == ' ')
00312 *s = '-';
00313 s++;
00314 }
00315 classes.push_back(cls);
00316 }
00317 }
00318 }
00319 fclose(lfp);
00320 } else {
00321 fprintf(stderr, "cannot open linkdef file %s\n", linkdef);
00322 }
00323 }
00324
00325 const char *libbase = solib.c_str();
00326 if (!fullpath) {
00327 if ((libbase = strrchr(libbase, '/')))
00328 libbase++;
00329 else
00330 libbase = solib.c_str();
00331 }
00332
00333 vector<string>::const_iterator it;
00334 for (it = classes.begin(); it != classes.end(); it++) {
00335 fprintf(fp, "Library.%-35s %s", ((*it)+":").c_str(), libbase);
00336
00337 if (solibdeps.size() > 0) {
00338 vector<string>::const_iterator depit;
00339 for (depit = solibdeps.begin(); depit != solibdeps.end(); depit++) {
00340 #ifdef WIN32
00341 string::size_type i = depit->find(".lib");
00342 if (i != string::npos)
00343 continue;
00344 #endif
00345
00346 const char *deplib = depit->c_str();
00347 if (!fullpath) {
00348 if ((deplib = strrchr(deplib, '/')))
00349 deplib++;
00350 else
00351 deplib = depit->c_str();
00352 }
00353 fprintf(fp, " %s", deplib);
00354 }
00355 }
00356 fprintf(fp, "\n");
00357 }
00358
00359 return 0;
00360 }
00361
00362
00363 int main(int argc, char **argv)
00364 {
00365 string solib;
00366 vector<string> solibdeps;
00367 vector<string> linkdefs;
00368 bool fullpath = false;
00369 bool replace = false;
00370 FILE *fp = stdout;
00371
00372 if (argc > 1) {
00373 int ic = 1;
00374 if (!strcmp(argv[ic], "-?") || !strcmp(argv[ic], "-h")) {
00375 fprintf(stderr, usage, argv[0]);
00376 return 1;
00377 }
00378 if (!strcmp(argv[ic], "-f")) {
00379 fullpath = true;
00380 ic++;
00381 }
00382 if (!strcmp(argv[ic], "-o")) {
00383 ic++;
00384 std::string outfile(argv[ic]);
00385 #ifdef WIN32
00386 FromCygToNativePath(outfile);
00387 fp = fopen(outfile.c_str(), "w");
00388 #else
00389 fp = fopen(argv[ic], "w");
00390 #endif
00391 if (!fp) {
00392 fprintf(stderr, "cannot open output file %s\n", outfile.c_str());
00393 return 1;
00394 }
00395 ic++;
00396 }
00397 if (!strcmp(argv[ic], "-r")) {
00398 replace = true;
00399 ic++;
00400 std::string outfile(argv[ic]);
00401 #ifdef WIN32
00402 FromCygToNativePath(outfile);
00403 fp = fopen(outfile.c_str(), "a+");
00404 #else
00405 fp = fopen(outfile.c_str(), "a+");
00406 #endif
00407 if (!fp) {
00408 fprintf(stderr, "cannot open output file %s\n", outfile.c_str());
00409 return 1;
00410 }
00411 ic++;
00412 }
00413 if (!strcmp(argv[ic], "-l")) {
00414 ic++;
00415 solib = argv[ic];
00416 #ifdef WIN32
00417 FromCygToNativePath(solib);
00418 #endif
00419 #ifdef __APPLE__
00420 string::size_type i = solib.find(".dylib");
00421 if (i != string::npos)
00422 solib.replace(i, 6, ".so");
00423 #endif
00424 ic++;
00425 }
00426 if (!strcmp(argv[ic], "-d")) {
00427 ic++;
00428 for (int i = ic; i < argc && argv[i][0] != '-'; i++) {
00429 string dl = argv[i];
00430 #ifdef WIN32
00431 FromCygToNativePath(dl);
00432 #endif
00433 #ifdef __APPLE__
00434 string::size_type j = dl.find(".dylib");
00435 if (j != string::npos)
00436 dl.replace(j, 6, ".so");
00437 #endif
00438 solibdeps.push_back(dl);
00439 ic++;
00440 }
00441 }
00442 if (!strcmp(argv[ic], "-c")) {
00443 ic++;
00444 for (int i = ic; i < argc; i++) {
00445 #ifdef WIN32
00446 std::string linkdef(argv[i]);
00447 FromCygToNativePath(linkdef);
00448 linkdefs.push_back(linkdef);
00449 #else
00450 linkdefs.push_back(argv[i]);
00451 #endif
00452 ic++;
00453 }
00454 }
00455 } else {
00456 fprintf(stderr, usage, argv[0]);
00457 return 1;
00458 }
00459
00460 if (replace) {
00461 #if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \
00462 !defined(__OpenBSD__)
00463
00464 if (lockf(fileno(fp), F_LOCK, (off_t)1) == -1) {
00465 fprintf(stderr, "rlibmap: locking failed, don't use gmake -j\n");
00466 }
00467 #endif
00468
00469
00470 RemoveLib(solib, fullpath, fp);
00471 }
00472
00473 LibMap(solib, solibdeps, linkdefs, fullpath, fp);
00474
00475 if (replace) {
00476 #if !defined(WIN32) && !defined(__CYGWIN__) && !defined(__FreeBSD__) && \
00477 !defined(__OpenBSD__)
00478
00479 lseek(fileno(fp), 0, SEEK_SET);
00480 if (lockf(fileno(fp), F_ULOCK, (off_t)1) == -1) {
00481
00482 }
00483 #endif
00484 }
00485
00486 if (fp != stdout)
00487 fclose(fp);
00488
00489 return 0;
00490 }