VirtualBox

Changeset 393 in kBuild


Ignore:
Timestamp:
Jan 13, 2006 12:42:10 AM (19 years ago)
Author:
bird
Message:
  • src/kDepIDB/kDepIDB.c:

o Initial coding. (This is a VC++ dependency extractor.)

  • src/kDepPre/kDepPre.c, src/lib/kDep.h, src/lib/kDep.c, Config.kmk:

o Created a library for the dep*() functions.
o Removed the IDB hacks from kDepPre.

Location:
trunk
Files:
7 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/ChangeLog

    r392 r393  
    22
    332006-01-12: bird
     4    - src/kDepIDB/kDepIDB.c:
     5        o Initial coding. (This is a VC++ dependency extractor.)
     6    - src/kDepPre/kDepPre.c, src/lib/kDep.h, src/lib/kDep.c, Config.kmk:
     7        o Created a library for the dep*() functions.
     8        o Removed the IDB hacks from kDepPre.
     9
     102006-01-11: bird
    411    - kBuild/tools/vcc70.kmk:
    512        o Prepared for new IDB based dependencies.s
  • trunk/Config.kmk

    r298 r393  
    4545TEMPLATE_BIN_INCS               = \
    4646        . \
     47        $(PATH_ROOT)/src/lib \
    4748        $(PATH_ROOT)/src/gmake/w32/include \
    4849        $(PATH_ROOT)/src/gmake/glob \
     
    7576
    7677
     78
     79#
     80# Template for building libraries for the tools.
     81#
     82TEMPLATE_LIB = Library for Commandline binary
     83
     84TEMPLATE_LIB_TOOL                   = $(TEMPLATE_BIN_TOOL)
     85TEMPLATE_LIB_INST                   = lib/
     86TEMPLATE_LIB_INCS                   = $(TEMPLATE_BIN_INCS)
     87TEMPLATE_LIB_INCS.$(BUILD_TYPE)     = $(TEMPLATE_BIN_INCS.$(BUILD_TYPE))
     88TEMPLATE_LIB_DEFS                   = $(TEMPLATE_BIN_DEFS)
     89TEMPLATE_LIB_DEFS.$(BUILD_TYPE)     = $(TEMPLATE_BIN_DEFS.$(BUILD_TYPE))
     90TEMPLATE_LIB_CFLAGS                 = $(TEMPLATE_BIN_CFLAGS)
     91TEMPLATE_LIB_CFLAGS.$(BUILD_TYPE)   = $(TEMPLATE_BIN_CFLAGS.$(BUILD_TYPE))
     92TEMPLATE_LIB_CXXFLAGS               = $(TEMPLATE_BIN_CXXFLAGS)
     93TEMPLATE_LIB_CXXFLAGS.$(BUILD_TYPE) = $(TEMPLATE_BIN_CXXFLAGS.$(BUILD_TYPE))
     94
     95LIB_KDEP = $(PATH_OUT)/$(TEMPLATE_LIB_INST)$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBPREF)kDep$$(TOOL_$(TEMPLATE_LIB_TOOL)_ARLIBSUFF)
     96
  • trunk/src/kDepPre/Makefile.kmk

    r304 r393  
    2828
    2929kDepPre_TEMPLATE        = BIN
     30kDepPre_LIBS            = $(LIB_KDEP)
    3031kDepPre_DEFS.linux      = HAVE_FGETC_UNLOCKED=1
    3132kDepPre_DEFS.win32      = NEED_ISBLANK=1 __WIN32__=1
  • trunk/src/kDepPre/kDepPre.c

    r384 r393  
    44 * kDepPre - Dependency Generator using Precompiler output.
    55 *
    6  * Copyright (c) 2005 knut st. osmundsen <[email protected]>
     6 * Copyright (c) 2005-2006 knut st. osmundsen <[email protected]>
    77 *
    88 *
     
    2626
    2727
     28/*******************************************************************************
     29*   Header Files                                                               *
     30*******************************************************************************/
    2831#include <stdio.h>
    29 #include <stdlib.h>
    3032#include <string.h>
    31 #include <errno.h>
    3233#include <ctype.h>
    33 #include <limits.h>
    34 #include <sys/stat.h>
    35 #ifdef __WIN32__
    36 # include <windows.h>
    37 #endif
    38 #if !defined(__WIN32__) && !defined(__OS2__)
    39 # include <dirent.h>
    40 #endif
    41 #ifndef __WIN32__
    42 # include <unistd.h>
    43 #endif
     34#include "kDep.h"
    4435
    4536#ifdef HAVE_FGETC_UNLOCKED
     
    5445
    5546
    56 
    57 
    58 /*******************************************************************************
    59 *   Structures and Typedefs                                                    *
    60 *******************************************************************************/
    61 /** A dependency. */
    62 typedef struct DEP
    63 {
    64     /** Next dependency in the list. */
    65     struct DEP *pNext;
    66     /** The filename hash. */
    67     unsigned    uHash;
    68     /** The length of the filename. */
    69     size_t      cchFilename;
    70     /** The filename. */
    71     char        szFilename[4];
    72 } DEP, *PDEP;
    73 
    74 
    75 /*******************************************************************************
    76 *   Global Variables                                                           *
    77 *******************************************************************************/
    78 /** List of dependencies. */
    79 static PDEP g_pDeps = NULL;
    80 
    81 
    82 /*******************************************************************************
    83 *   Internal Functions                                                         *
    84 *******************************************************************************/
    85 static PDEP depAdd(const char *pszFilename, size_t cchFilename);
    86 static void depOptimize(int fFixCase);
    87 static void depPrint(FILE *pOutput);
    88 static void depPrintStubs(FILE *pOutput);
    89 
    90 
    91 #ifdef __WIN32__
    92 /**
    93  * Corrects the case of a path.
    94  * Expects a fullpath!
    95  *
    96  * @param   pszPath     Pointer to the path, both input and output.
    97  *                      The buffer must be able to hold one more byte than the string length.
    98  */
    99 void fixcase(char *pszPath)
    100 {
    101 #define my_assert(expr) \
    102     do { \
    103         if (!(expr)) { \
    104             printf("my_assert: %s, file %s, line %d\npszPath=%s\npsz=%s\n", \
    105                    #expr, __FILE__, __LINE__, pszPath, psz); \
    106             __asm { __asm int 3 } \
    107             exit(1); \
    108         } \
    109     } while (0)
    110 
    111     char *psz = pszPath;
    112     if (*psz == '/' || *psz == '\\')
    113     {
    114         if (psz[1] == '/' || psz[1] == '\\')
    115         {
    116             /* UNC */
    117             my_assert(psz[1] == '/' || psz[1] == '\\');
    118             my_assert(psz[2] != '/' && psz[2] != '\\');
    119 
    120             /* skip server name */
    121             psz += 2;
    122             while (*psz != '\\' && *psz != '/')
    123             {
    124                 if (!*psz)
    125                     return;
    126                 *psz++ = toupper(*psz);
    127             }
    128 
    129             /* skip the share name */
    130             psz++;
    131             my_assert(*psz != '/' && *psz != '\\');
    132             while (*psz != '\\' && *psz != '/')
    133             {
    134                 if (!*psz)
    135                     return;
    136                 *psz++ = toupper(*psz);
    137             }
    138             my_assert(*psz == '/' || *psz == '\\');
    139             psz++;
    140         }
    141         else
    142         {
    143             /* Unix spec */
    144             psz++;
    145         }
    146     }
    147     else
    148     {
    149         /* Drive letter */
    150         my_assert(psz[1] == ':');
    151         *psz = toupper(*psz);
    152         my_assert(psz[0] >= 'A' && psz[0] <= 'Z');
    153         my_assert(psz[2] == '/' || psz[2] == '\\');
    154         psz += 3;
    155     }
    156 
    157     /*
    158      * Pointing to the first char after the unc or drive specifier.
    159      */
    160     while (*psz)
    161     {
    162         WIN32_FIND_DATA FindFileData;
    163         HANDLE hDir;
    164         char chSaved0;
    165         char chSaved1;
    166         char *pszEnd;
    167 
    168 
    169         /* find the end of the component. */
    170         pszEnd = psz;
    171         while (*pszEnd && *pszEnd != '/' && *pszEnd != '\\')
    172             pszEnd++;
    173 
    174         /* replace the end with "?\0" */
    175         chSaved0 = pszEnd[0];
    176         chSaved1 = pszEnd[1];
    177         pszEnd[0] = '?';
    178         pszEnd[1] = '\0';
    179 
    180         /* find the right filename. */
    181         hDir = FindFirstFile(pszPath, &FindFileData);
    182         pszEnd[1] = chSaved1;
    183         if (!hDir)
    184         {
    185             pszEnd[0] = chSaved0;
    186             return;
    187         }
    188         pszEnd[0] = '\0';
    189         while (stricmp(FindFileData.cFileName, psz))
    190         {
    191             if (!FindNextFile(hDir, &FindFileData))
    192             {
    193                 pszEnd[0] = chSaved0;
    194                 return;
    195             }
    196         }
    197         strcpy(psz, FindFileData.cFileName);
    198         pszEnd[0] = chSaved0;
    199 
    200         /* advance to the next component */
    201         if (!chSaved0)
    202             return;
    203         psz = pszEnd + 1;
    204         my_assert(*psz != '/' && *psz != '\\');
    205     }
    206 #undef my_assert
    207 }
    208 
    209 /**
    210  * Corrects all slashes to unix slashes.
    211  *
    212  * @returns pszFilename.
    213  * @param   pszFilename     The filename to correct.
    214  */
    215 char *fixslash(char *pszFilename)
    216 {
    217     char *psz = pszFilename;
    218     while ((psz = strchr(psz, '\\')) != NULL)
    219         *psz++ = '/';
    220     return pszFilename;
    221 }
    222 
    223 #elif defined(__OS2__)
    224 
    225 /**
    226  * Corrects the case of a path.
    227  *
    228  * @param   pszPath     Pointer to the path, both input and output.
    229  *                      The buffer must be able to hold one more byte than the string length.
    230  */
    231 void fixcase(char *pszFilename)
    232 {
    233     return;
    234 }
    235 
    236 #else
    237 
    238 /**
    239  * Corrects the case of a path.
    240  *
    241  * @param   pszPath     Pointer to the path, both input and output.
    242  */
    243 void fixcase(char *pszFilename)
    244 {
    245     char *psz;
    246 
    247     /*
    248      * Skip the root.
    249      */
    250     psz = pszFilename;
    251     while (*psz == '/')
    252         psz++;
    253 
    254     /*
    255      * Iterate all the components.
    256      */
    257     while (*psz)
    258     {
    259         char  chSlash;
    260         struct stat s;
    261         char   *pszStart = psz;
    262 
    263         /*
    264          * Find the next slash (or end of string) and terminate the string there.
    265          */
    266         while (*psz != '/' && *psz)
    267             *psz++;
    268         chSlash = *psz;
    269         *psz = '\0';
    270 
    271         /*
    272          * Does this part exist?
    273          * If not we'll enumerate the directory and search for an case-insensitive match.
    274          */
    275         if (stat(pszFilename, &s))
    276         {
    277             struct dirent  *pEntry;
    278             DIR            *pDir;
    279             if (pszStart == pszFilename)
    280                 pDir = opendir(*pszFilename ? pszFilename : ".");
    281             else
    282             {
    283                 pszStart[-1] = '\0';
    284                 pDir = opendir(pszFilename);
    285                 pszStart[-1] = '/';
    286             }
    287             if (!pDir)
    288             {
    289                 *psz = chSlash;
    290                 break; /* giving up, if we fail to open the directory. */
    291             }
    292 
    293             while ((pEntry = readdir(pDir)) != NULL)
    294             {
    295                 if (!strcasecmp(pEntry->d_name, pszStart))
    296                 {
    297                     strcpy(pszStart, pEntry->d_name);
    298                     break;
    299                 }
    300             }
    301             closedir(pDir);
    302             if (!pEntry)
    303             {
    304                 *psz = chSlash;
    305                 break;  /* giving up if not found. */
    306             }
    307         }
    308 
    309         /* restore the slash and press on. */
    310         *psz = chSlash;
    311         while (*psz == '/')
    312             psz++;
    313     }
    314 
    315     return;
    316 }
    317 
    318 
    319 #endif
    320 
    321 
    322 /**
    323  * 'Optimizes' and corrects the dependencies.
    324  */
    325 static void depOptimize(int fFixCase)
    326 {
    327     /*
    328      * Walk the list correct the names and re-insert them.
    329      */
    330     PDEP pDepOrg = g_pDeps;
    331     PDEP pDep = g_pDeps;
    332     g_pDeps = NULL;
    333     for (; pDep; pDep = pDep->pNext)
    334     {
    335 #ifdef __WIN32__
    336         char        szFilename[_MAX_PATH + 1];
    337 #else
    338         char        szFilename[PATH_MAX + 1];
    339 #endif
    340         char       *pszFilename;
    341         struct stat s;
    342 
    343         /*
    344          * Skip some fictive names like <built-in> and <command line>.
    345          */
    346         if (    pDep->szFilename[0] == '<'
    347             &&  pDep->szFilename[pDep->cchFilename - 1] == '>')
    348             continue;
    349         pszFilename = pDep->szFilename;
    350 
    351 #if !defined(__OS2__) && !defined(__WIN32__)
    352         /*
    353          * Skip any drive letters from compilers running in wine.
    354          */
    355         if (pszFilename[1] == ':')
    356             pszFilename += 2;
    357 #endif
    358 
    359         /*
    360          * The microsoft compilers are notoriously screwing up the casing.
    361          * This will screw up kmk (/ GNU Make).
    362          */
    363         if (fFixCase)
    364         {
    365 #ifdef __WIN32__
    366             if (_fullpath(szFilename, pszFilename, sizeof(szFilename)))
    367                 fixslash(szFilename);
    368             else
    369 #endif
    370                 strcpy(szFilename, pszFilename);
    371             fixcase(szFilename);
    372             pszFilename = szFilename;
    373         }
    374 
    375         /*
    376          * Check that the file exists before we start depending on it.
    377          */
    378         if (stat(pszFilename, &s))
    379         {
    380             fprintf(stderr, "kDepPre: Skipping '%s' - %s!\n", szFilename, strerror(errno));
    381             continue;
    382         }
    383 
    384         /*
    385          * Insert the corrected dependency.
    386          */
    387         depAdd(pszFilename, strlen(pszFilename));
    388     }
    389 
    390 #if 0 /* waste of time */
    391     /*
    392      * Free the old ones.
    393      */
    394     while (pDepOrg)
    395     {
    396         pDep = pDepOrg;
    397         pDepOrg = pDepOrg->pNext;
    398         free(pDep);
    399     }
    400 #endif
    401 }
    402 
    403 
    404 /**
    405  * Prints the dependency chain.
    406  *
    407  * @returns Pointer to the allocated dependency.
    408  * @param   pOutput     Output stream.
    409  */
    410 static void depPrint(FILE *pOutput)
    411 {
    412     PDEP pDep;
    413     for (pDep = g_pDeps; pDep; pDep = pDep->pNext)
    414         fprintf(pOutput, " \\\n\t%s", pDep->szFilename);
    415     fprintf(pOutput, "\n\n");
    416 }
    417 
    418 
    419 /**
    420  * Prints empty dependency stubs for all dependencies.
    421  */
    422 static void depPrintStubs(FILE *pOutput)
    423 {
    424     PDEP pDep;
    425     for (pDep = g_pDeps; pDep; pDep = pDep->pNext)
    426         fprintf(pOutput, "%s:\n\n", pDep->szFilename);
    427 }
    428 
    429 
    430 /* sdbm:
    431    This algorithm was created for sdbm (a public-domain reimplementation of
    432    ndbm) database library. it was found to do well in scrambling bits,
    433    causing better distribution of the keys and fewer splits. it also happens
    434    to be a good general hashing function with good distribution. the actual
    435    function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
    436    is the faster version used in gawk. [there is even a faster, duff-device
    437    version] the magic constant 65599 was picked out of thin air while
    438    experimenting with different constants, and turns out to be a prime.
    439    this is one of the algorithms used in berkeley db (see sleepycat) and
    440    elsewhere. */
    441 static unsigned sdbm(const char *str)
    442 {
    443     unsigned hash = 0;
    444     int c;
    445 
    446     while ((c = *(unsigned const char *)str++))
    447         hash = c + (hash << 6) + (hash << 16) - hash;
    448 
    449     return hash;
    450 }
    451 
    452 
    453 /**
    454  * Adds a dependency.
    455  *
    456  * @returns Pointer to the allocated dependency.
    457  * @param   pszFilename     The filename.
    458  * @param   cchFilename     The length of the filename.
    459  */
    460 static PDEP depAdd(const char *pszFilename, size_t cchFilename)
    461 {
    462     unsigned uHash = sdbm(pszFilename);
    463     PDEP    pDep;
    464     PDEP    pDepPrev;
    465 
    466     /*
    467      * Check if we've already got this one.
    468      */
    469     pDepPrev = NULL;
    470     for (pDep = g_pDeps; pDep; pDepPrev = pDep, pDep = pDep->pNext)
    471         if (    pDep->uHash == uHash
    472             &&  pDep->cchFilename == cchFilename
    473             &&  !memcmp(pDep->szFilename, pszFilename, cchFilename))
    474             return pDep;
    475 
    476     /*
    477      * Add it.
    478      */
    479     pDep = (PDEP)malloc(sizeof(*pDep) + cchFilename);
    480     if (!pDep)
    481     {
    482         fprintf(stderr, "\nOut of memory! (requested %#x bytes)\n\n", sizeof(*pDep) + cchFilename);
    483         exit(1);
    484     }
    485 
    486     pDep->cchFilename = cchFilename;
    487     memcpy(pDep->szFilename, pszFilename, cchFilename + 1);
    488     pDep->uHash = uHash;
    489 
    490     if (pDepPrev)
    491     {
    492         pDep->pNext = pDepPrev->pNext;
    493         pDepPrev->pNext = pDep;
    494     }
    495     else
    496     {
    497         pDep->pNext = g_pDeps;
    498         g_pDeps = pDep;
    499     }
    500     return pDep;
    501 }
    50247
    50348
     
    662207
    663208
    664 /**
    665  * Make an attempt at parsing a Visual C++ IDB file.
    666  */
    667 static int ParseVCxxIDB(FILE *pInput, const char *argv0)
    668 {
    669     char       *pbFile;
    670     long        cbFile;
    671     int         rc = 0;
    672 
    673     /*
    674      * Figure out file size.
    675      */
    676     if (    fseek(pInput, 0, SEEK_END) < 0
    677         ||  (cbFile = ftell(pInput)) < 0
    678         ||  fseek(pInput, 0, SEEK_SET))
    679     {
    680         fprintf(stderr, "%s: error: Failed to determin file size of the Visual C++ IDB file.\n", argv0);
    681         return -1;
    682     }
    683 
    684     /*
    685      * Allocate memory and read the file.
    686      */
    687     pbFile = (char *)malloc(cbFile + 1);
    688     if (!pbFile)
    689     {
    690         fprintf(stderr, "%s: error: Failed to allocate %ld bytes of memory for the Visual C++ IDB file.\n", argv0, cbFile);
    691         return -1;
    692     }
    693     if (fread(pbFile, cbFile, 1, pInput))
    694     {
    695         const char *pszPrefix = NULL;
    696         int         cchPrefix = 0;
    697         pbFile[cbFile] = '\0';
    698 
    699         /*
    700          * Check the header.
    701          */
    702         if (!strncmp(pbFile, "Microsoft C/C++ MSF 7.", sizeof("Microsoft C/C++ MSF 7.") - 1))
    703         {
    704             pszPrefix = "/mr/inversedeps/";
    705             cchPrefix = sizeof("/mr/inversedeps/") - 1;
    706         }
    707         else if (!strncmp(pbFile, "Microsoft C/C++ program database 2.", sizeof("Microsoft C/C++ program database 2.") - 1))
    708         {
    709             pszPrefix = "/ipm/header/";
    710             cchPrefix = sizeof("/ipm/header/") - 1;
    711         }
    712         if (pszPrefix)
    713         {
    714             /*
    715              * Do a brute force scan of the file until we encounter "\0/mr/inversedeps/" (which is the
    716              * vc70 and vc80 prefix) or "\0/ipm/header/" (which is the vc60 prefix).
    717              * (This is highly experimental and I've no idea about the actual format of the file.)
    718              */
    719             char *pb = pbFile;
    720             long cbLeft = cbFile;
    721             while (cbLeft > cchPrefix + 3)
    722             {
    723                 /** @todo use memchr? */
    724                 if (    *pb != *pszPrefix
    725                     ||   strncmp(pb, pszPrefix, cchPrefix))
    726                 {
    727                     pb++;
    728                     cbLeft--;
    729                 }
    730                 else
    731                 {
    732                     const char *psz = &pb[cchPrefix];
    733                     size_t      cch = strlen(psz);
    734                     depAdd(psz, cch);
    735                     //printf("dep='%s'\n", psz);
    736                     pb += cch + cchPrefix;
    737                     cbLeft -= cch + cchPrefix;
    738                 }
    739             }
    740         }
    741         else
    742         {
    743             fprintf(stderr, "%s: error: Doesn't recognize the header of the Visual C++ IDB file.\n", argv0, cbFile);
    744             rc = 1;
    745         }
    746     }
    747     else
    748     {
    749         fprintf(stderr, "%s: error: Failed to allocate %ld bytes of memory for the Visual C++ IDB file.\n", argv0, cbFile);
    750         rc = 1;
    751     }
    752 
    753     return rc;
    754 }
    755 
    756 
    757209static void usage(const char *argv0)
    758210{
    759     printf("syntax: %s [-l=c] -o <output> -t <target> [-f] [-s] < - | <filename> | -e <cmdline> | -i <vc idb-file> >\n", argv0);
     211    printf("syntax: %s [-l=c] -o <output> -t <target> [-f] [-s] < - | <filename> | -e <cmdline> >\n", argv0);
    760212}
    761213
     
    775227    /* Argument parsing. */
    776228    int         fInput = 0;             /* set when we've found input argument. */
    777     int         fIDBMode = 0;
    778229
    779230    /*
     
    886337                    pInput = stdin;
    887338                    fInput = 1;
    888                     break;
    889                 }
    890 
    891                 /*
    892                  * IDB input.
    893                  */
    894                 case 'i':
    895                 {
    896                     if (++i >= argc)
    897                     {
    898                         fprintf(stderr, "%s: syntax error: The '-i' argument is missing IDB filename.\n", argv[0]);
    899                         return 1;
    900                     }
    901                     pInput = fopen(argv[i], "rb");
    902                     if (!pInput)
    903                     {
    904                         fprintf(stderr, "%s: error: Failed to open input file '%s'.\n", argv[0], argv[i]);
    905                         return 1;
    906                     }
    907                     fInput = 1;
    908                     fIDBMode = 1;
    909339                    break;
    910340                }
     
    993423     * Do the parsing.
    994424     */
    995     if (!fIDBMode)
    996         i = ParseCPrecompiler(pInput);
    997     else
    998         i = ParseVCxxIDB(pInput, argv[0]);
     425    i = ParseCPrecompiler(pInput);
    999426
    1000427    /*
     
    1035462    return i;
    1036463}
     464
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette