VirtualBox

Changeset 3315 in kBuild for trunk/src


Ignore:
Timestamp:
Mar 31, 2020 1:12:19 AM (5 years ago)
Author:
bird
Message:

lib/kDep+users: Escape spaces and such in dependency files (experimental).

Location:
trunk/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kDepPre/kDepPre.c

    r3167 r3315  
    469469    {
    470470        depOptimize(&This, fFixCase, 0 /* fQuiet */, NULL /*pszIgnoredExt*/);
    471         fprintf(pOutput, "%s:", pszTarget);
    472         depPrint(&This, pOutput);
     471        depPrintTargetWithDeps(&This, pOutput, pszTarget, 1 /*fEscapeTarget*/);
    473472        if (fStubs)
    474473            depPrintStubs(&This, pOutput);
  • trunk/src/kObjCache/kObjCache.c

    r3239 r3315  
    11341134        *psz++ = '/';
    11351135
    1136     fprintf(pFile, "%s:", pszObjFileAbs);
     1136    depPrintTargetWithDeps(&pDepState->Core, pFile, pszObjFileAbs, 1 /*fEscapeTarget*/);
    11371137    free(pszObjFileAbs);
    1138     depPrint(&pDepState->Core, pFile);
    11391138    if (fGenStubs)
    11401139        depPrintStubs(&pDepState->Core, pFile);
  • trunk/src/kmk/kmkbuiltin/kDepIDB.c

    r3192 r3315  
    830830    {
    831831        depOptimize(&This.Core, fFixCase, fQuiet, NULL /*pszIgnoredExt*/);
    832         fprintf(pOutput, "%s:", pszTarget);
    833         depPrint(&This.Core, pOutput);
     832        depPrintTargetWithDeps(&This.Core, pOutput, pszTarget, 1 /*fEscapeTarget*/);
    834833        if (fStubs)
    835834            depPrintStubs(&This.Core, pOutput);
  • trunk/src/kmk/kmkbuiltin/kDepObj.c

    r3238 r3315  
    11881188    {
    11891189        depOptimize(&This.Core, fFixCase, fQuiet, pszIgnoreExt);
    1190         fprintf(pOutput, "%s:", pszTarget);
    1191         depPrint(&This.Core, pOutput);
     1190        depPrintTargetWithDeps(&This.Core, pOutput, pszTarget, 1 /*fEscapeTarget*/);
    11921191        if (fStubs)
    11931192            depPrintStubs(&This.Core, pOutput);
  • trunk/src/lib/kDep.c

    r3174 r3315  
    326326
    327327/**
     328 * Write a filename that contains characters that needs escaping.
     329 *
     330 * @param   pOutput The output stream.
     331 * @param   pszFile The filename.
     332 * @param   cchFile The length of the filename.
     333 * @param   fDep    Whether this is for a dependency file or a target file.
     334 */
     335int depNeedsEscaping(const char *pszFile, size_t cchFile, int fDependency)
     336{
     337    return memchr(pszFile, ' ',  cchFile) != NULL
     338        || memchr(pszFile, '\t', cchFile) != NULL
     339        || memchr(pszFile, '#',  cchFile) != NULL
     340        || memchr(pszFile, '=',  cchFile) != NULL
     341        || memchr(pszFile, ';',  cchFile) != NULL
     342        || memchr(pszFile, '$',  cchFile) != NULL
     343        || memchr(pszFile, fDependency ? '|' : '%',  cchFile) != NULL;
     344}
     345
     346
     347/**
     348 * Write a filename that contains characters that needs escaping.
     349 *
     350 * @param   pOutput The output stream.
     351 * @param   pszFile The filename.
     352 * @param   cchFile The length of the filename.
     353 * @param   fDep    Whether this is for a dependency file or a target file.
     354 */
     355void depEscapedWrite(FILE *pOutput, const char *pszFile, size_t cchFile, int fDepenency)
     356{
     357    size_t cchWritten = 0;
     358    size_t off        = 0;
     359    while (off < cchFile)
     360    {
     361        char const ch = pszFile[off];
     362        switch (ch)
     363        {
     364            default:
     365                off++;
     366                break;
     367
     368            /*
     369             * Escaped by slash, but any preceeding slashes must be escaped too.
     370             * A couple of characters are only escaped on one side of the ':'.
     371             */
     372            case '%': /* target side only */
     373            case '|': /* dependency side only */
     374                if (ch != (fDepenency ? '|' : '%'))
     375                {
     376                    off++;
     377                    break;
     378                }
     379                /* fall thru */
     380            case ' ':
     381            case '\t':
     382            case '#':
     383            case '=': /** @todo buggy GNU make handling */
     384            case ';': /** @todo buggy GNU make handling */
     385                if (cchWritten < off)
     386                    fwrite(&pszFile[cchWritten], off - cchWritten, 1, pOutput);
     387                if (off == 0 || pszFile[off - 1] != '\\')
     388                {
     389                    fputc('\\', pOutput);
     390                    cchWritten = off; /* We write the escaped character with the next bunch. */
     391                }
     392                else
     393                {
     394                    size_t cchSlashes = 1;
     395                    while (cchSlashes < off && pszFile[off - cchSlashes - 1] == '\\')
     396                        cchSlashes++;
     397                    fwrite(&pszFile[off - cchSlashes], cchSlashes, 1, pOutput);
     398                    cchWritten = off - 1; /* Write a preceeding slash and the escaped character with the next bunch. */
     399                }
     400                off += 1;
     401                break;
     402
     403            /*
     404             * Escaped by doubling it.
     405             * Implemented by including in the pending writeout job as well as in the next one.
     406             */
     407            case '$':
     408                fwrite(&pszFile[cchWritten], off - cchWritten + 1, 1, pOutput);
     409                cchWritten = off++; /* write it again the next time */
     410                break;
     411        }
     412    }
     413
     414    /* Remainder: */
     415    if (cchWritten < cchFile)
     416        fwrite(&pszFile[cchWritten], cchFile - cchWritten, 1, pOutput);
     417}
     418
     419
     420/**
     421 * Escapes all trailing trailing slashes in a filename that ends with such.
     422 */
     423static void depPrintTrailngSlashEscape(FILE *pOutput, const char *pszFilename, size_t cchFilename)
     424{
     425    size_t cchSlashes = 1;
     426    while (cchSlashes < cchFilename && pszFilename[cchFilename - cchSlashes - 1] == '\\')
     427        cchSlashes++;
     428    fwrite(&pszFilename[cchFilename - cchSlashes], cchSlashes, 1, pOutput);
     429}
     430
     431
     432/**
    328433 * Prints the dependency chain.
    329434 *
     
    331436 * @param   pOutput     Output stream.
    332437 */
    333 void depPrint(PDEPGLOBALS pThis, FILE *pOutput)
    334 {
     438void depPrintChain(PDEPGLOBALS pThis, FILE *pOutput)
     439{
     440    static char const g_szEntryText[]     = " \\\n\t";
     441    static char const g_szTailText[]      = "\n\n";
     442    static char const g_szTailSlashText[] = " \\\n\n";
     443    PDEP              pDep;
     444    for (pDep = pThis->pDeps; pDep; pDep = pDep->pNext)
     445    {
     446        fwrite(g_szEntryText, sizeof(g_szEntryText) - 1, 1, pOutput);
     447        if (!pDep->fNeedsEscaping)
     448            fwrite(pDep->szFilename, pDep->cchFilename, 1, pOutput);
     449        else
     450            depEscapedWrite(pOutput, pDep->szFilename, pDep->cchFilename, 1 /*fDependency*/);
     451        if (pDep->fTrailingSlash)
     452        {   /* Escape only if more dependencies.  If last, we must add a line continuation or it won't work. */
     453            if (pDep->pNext)
     454                depPrintTrailngSlashEscape(pOutput, pDep->szFilename, pDep->cchFilename);
     455            else
     456            {
     457                fwrite(g_szTailSlashText, sizeof(g_szTailSlashText), 1, pOutput);
     458                return;
     459            }
     460        }
     461    }
     462
     463    fwrite(g_szTailText, sizeof(g_szTailText) - 1, 1, pOutput);
     464}
     465
     466
     467/**
     468 * Prints the dependency chain with a preceeding target.
     469 *
     470 * @param   pThis           The 'dep' instance.
     471 * @param   pOutput         Output stream.
     472 * @param   pszTarget       The target filename.
     473 * @param   fEscapeTarget   Whether to consider escaping the target.
     474 */
     475void depPrintTargetWithDeps(PDEPGLOBALS pThis, FILE *pOutput, const char *pszTarget, int fEscapeTarget)
     476{
     477    static char const g_szSeparator[] = ":";
     478    size_t const cchTarget = strlen(pszTarget);
     479    if (!fEscapeTarget || !depNeedsEscaping(pszTarget, cchTarget, 0 /*fDependency*/))
     480        fwrite(pszTarget, cchTarget, 1, pOutput);
     481    else
     482        depEscapedWrite(pOutput, pszTarget, cchTarget, 0 /*fDependency*/);
     483
     484    if (cchTarget == 0 || pszTarget[cchTarget - 1] != '\\')
     485    { /* likely */ }
     486    else
     487        depPrintTrailngSlashEscape(pOutput, pszTarget, cchTarget);
     488    fwrite(g_szSeparator, sizeof(g_szSeparator) - 1, 1, pOutput);
     489
     490    depPrintChain(pThis, pOutput);
     491}
     492
     493
     494/**
     495 * Prints empty dependency stubs for all dependencies.
     496 *
     497 * @param   pThis       The 'dep' instance.
     498 * @param   pOutput     Output stream.
     499 */
     500void depPrintStubs(PDEPGLOBALS pThis, FILE *pOutput)
     501{
     502    static char g_szTailText[] = ":\n\n";
    335503    PDEP pDep;
    336504    for (pDep = pThis->pDeps; pDep; pDep = pDep->pNext)
    337         fprintf(pOutput, " \\\n\t%s", pDep->szFilename);
    338     fprintf(pOutput, "\n\n");
    339 }
    340 
    341 
    342 /**
    343  * Prints empty dependency stubs for all dependencies.
    344  *
    345  * @param   pThis       The 'dep' instance.
    346  * @param   pOutput     Output stream.
    347  */
    348 void depPrintStubs(PDEPGLOBALS pThis, FILE *pOutput)
    349 {
    350     PDEP pDep;
    351     for (pDep = pThis->pDeps; pDep; pDep = pDep->pNext)
    352         fprintf(pOutput, "%s:\n\n", pDep->szFilename);
     505    {
     506        if (!pDep->fNeedsEscaping && memchr(pDep->szFilename, '%', pDep->cchFilename) == 0)
     507            fwrite(pDep->szFilename, pDep->cchFilename, 1, pOutput);
     508        else
     509            depEscapedWrite(pOutput, pDep->szFilename, pDep->cchFilename, 0 /*fDependency*/);
     510
     511        if (pDep->cchFilename == 0 || !pDep->fTrailingSlash)
     512        { /* likely */ }
     513        else
     514            depPrintTrailngSlashEscape(pOutput, pDep->szFilename, pDep->cchFilename);
     515        fwrite(g_szTailText, sizeof(g_szTailText) - 1, 1, pOutput);
     516    }
    353517}
    354518
     
    415579    memcpy(pDep->szFilename, pszFilename, cchFilename);
    416580    pDep->szFilename[cchFilename] = '\0';
     581    pDep->fNeedsEscaping = depNeedsEscaping(pszFilename, cchFilename, 1 /*fDependency*/);
     582    pDep->fTrailingSlash = cchFilename > 0 && pszFilename[cchFilename - 1] == '\\';
    417583    pDep->uHash = uHash;
    418584
  • trunk/src/lib/kDep.h

    r3167 r3315  
    4040    /** The filename hash. */
    4141    unsigned    uHash;
     42    /** Set if needs escaping. */
     43    char        fNeedsEscaping;
     44    /** Set if filename ends with a slash and may require special processing. */
     45    char        fTrailingSlash;
    4246    /** The length of the filename. */
    4347    size_t      cchFilename;
     
    5862extern PDEP depAdd(PDEPGLOBALS pThis, const char *pszFilename, size_t cchFilename);
    5963extern void depOptimize(PDEPGLOBALS pThis, int fFixCase, int fQuiet, const char *pszIgnoredExt);
    60 extern void depPrint(PDEPGLOBALS pThis, FILE *pOutput);
     64extern int  depNeedsEscaping(const char *pszFile, size_t cchFile, int fDependency);
     65extern void depEscapedWrite(FILE *pOutput, const char *pszFile, size_t cchFile, int fDepenency);
     66extern void depPrintChain(PDEPGLOBALS pThis, FILE *pOutput);
     67extern void depPrintTargetWithDeps(PDEPGLOBALS pThis, FILE *pOutput, const char *pszTarget, int fEscapeTarget);
    6168extern void depPrintStubs(PDEPGLOBALS pThis, FILE *pOutput);
    6269
Note: See TracChangeset for help on using the changeset viewer.

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