rlibmap.cxx

Go to the documentation of this file.
00001 // @(#)root/utils:$Id: rlibmap.cxx 36819 2010-11-21 12:15:05Z rdm $
00002 // Author: Fons Rademakers   05/12/2003
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 // This program generates a map between class name and shared library.
00013 // Its output is in TEnv format.
00014 // Usage: rlibmap [-f] [-o <mapfile>] -l <sofile> -d <depsofiles>
00015 //                 -c <linkdeffiles>
00016 // -f: output full library path name (not needed when ROOT library
00017 //     search path is used)
00018 // -o: write output to specified file, otherwise to stdout
00019 // -r: replace existing entries in the specified file
00020 // -l: library containing the classes in the specified linkdef files
00021 // -d: libraries on which the -l library depends
00022 // -c: linkdef files containing the list of classes defined in the -l library
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;       // whole file
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    // Remove all blanks from the string str. The returned string has to be
00120    // deleted by the user.
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    // allocate 20 extra characters in case of eg, vector<vector<T>>
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                // the last one will be copied after the for loop
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    // Replace ">>" by "> >" except for operator>>.
00157    // str might be changed; the old string gets deleted in here.
00158 
00159    // Even handles cases like "A<B<operator>>()>>::operator >>()".
00160 
00161    char* pos = strstr(str, ">>");
00162    char* fixed = 0;
00163    int countgtgt = 0;
00164    while (pos) {
00165       // first run: just count, so we can allocate space for fixed
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       // check that it's not op>>:
00175       if (pos - str >= 8) {
00176          char* posop = pos - 1;
00177          // remove spaces in front of ">>":
00178          while (posop >= str && *posop == ' ')
00179             --posop;
00180          if (!strncmp("operator", posop - 7, 8)) {
00181             // it is an operator!
00182             isop = true;
00183          }
00184       }
00185       if (!isop) {
00186          // not an operator; we need to add a space.
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    // Remove entries from the map file for the specified solib.
00204 
00205    fseek(fp, 0, SEEK_SET);
00206 
00207    // get file size
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    // read file and remove lines matching specified libs
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       // fgets() should return 0 in this case but doesn't
00240       if ( (siz - size_t(fptr - fbuf)) <= 0)
00241          break;
00242    }
00243 
00244    if (ftruncate(fileno(fp), 0)) {;}
00245 
00246    // write remaining lines back
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    // Write libmap. Returns -1 in case of error.
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                // handles class, class+protected and class+private, typedef
00289                if (!strncmp(type, "class", 5) || !strcmp(type, "typedef")) {
00290                   char *cls = strtok(0, "-!+;");
00291                   // just in case remove trailing space and tab
00292                   while (*cls == ' ') cls++;
00293                   int len = strlen(cls) - 1;
00294                   while (cls[len] == ' ' || cls[len] == '\t')
00295                      cls[len--] = '\0';
00296                   //no space between tmpl arguments allowed
00297                   cls = Compress(cls);
00298                   // except for A<B<C> >!
00299                   UnCompressTemplate(cls);
00300 
00301                   // don't include "vector<string>" and "std::pair<" classes
00302                   if (!strncmp(cls, "vector<string>", 14) ||
00303                       !strncmp(cls, "std::pair<", 10))
00304                      continue;
00305 
00306                   // replace "::" by "@@" since TEnv uses ":" as delimeter
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       // lock file
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       // remove entries for solib to be processed
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       // remove lock
00479       lseek(fileno(fp), 0, SEEK_SET);
00480       if (lockf(fileno(fp), F_ULOCK, (off_t)1) == -1) {
00481          //fprintf(stderr, "rlibmap: error unlocking output file\n");
00482       }
00483 #endif
00484    }
00485 
00486    if (fp != stdout)
00487       fclose(fp);
00488 
00489    return 0;
00490 }

Generated on Tue Jul 5 14:12:03 2011 for ROOT_528-00b_version by  doxygen 1.5.1