VirtualBox

Changeset 2616 in kBuild for trunk/src/kObjCache/kObjCache.c


Ignore:
Timestamp:
Aug 2, 2012 1:43:58 AM (12 years ago)
Author:
bird
Message:

kObjCache: Early commit of the C preprocessor output optimizer.

File:
1 edited

Legend:

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

    r2615 r2616  
    113113#define MY_IS_BLANK(a_ch)   ((a_ch) == ' ' || (a_ch) == '\t')
    114114
     115#define KOC_BUF_MIN         KOC_BUF_ALIGNMENT
     116#define KOC_BUF_INCR        KOC_BUF_ALIGNMENT
     117#define KOC_BUF_ALIGNMENT   (4U*1024U*1024U)
     118
    115119
    116120/*******************************************************************************
     
    10891093        FatalMsg("Failed to write dependency file '%s': %s\n", pszFilename, strerror(errno));
    10901094}
     1095
     1096
     1097/**
     1098 * Preprocessor output reader state.
     1099 */
     1100typedef struct KOCCPPRD
     1101{
     1102    /** Pointer to the preprocessor output. */
     1103    char *pszBuf;
     1104    /** Allocated buffer size. */
     1105    size_t cbBufAlloc;
     1106    /** Amount preprocessor output that we've completed optimizations for. */
     1107    size_t cchOptimized;
     1108    /** The offset of the next bits to process. */
     1109    size_t offCur;
     1110    /** The offset where to put more raw preprocessor output. */
     1111    size_t offRead;
     1112    /** The line number corresponding to offOptimized. */
     1113    uint32_t uOptLineNo;
     1114    /** The current line number. */
     1115    uint32_t uCurLineNo;
     1116    /** The number of lines found to be empty starting at cchOptimized. */
     1117    uint32_t cEmptyLines;
     1118    /** Set if we're done, clear if we're expecting more preprocessor output. */
     1119    int fDone;
     1120    /** The saved character at cchOptimized. */
     1121    char chSaved;
     1122    /** Whether the optimizations are enabled. */
     1123    int fOptimize;
     1124
     1125    /** Buffer holding the current file name (unescaped). */
     1126    char *pszFileNmBuf;
     1127    /** The size of the file name buffer. */
     1128    size_t cbFileNmBuf;
     1129    /** The length of the current file string. */
     1130    size_t cchCurFileNm;
     1131
     1132    /** Line directive / new line sequence buffer. */
     1133    char *pszLineBuf;
     1134    /** The size of the buffer pointed to by pszLineBuf. */
     1135    size_t cbLineBuf;
     1136} KOCCPPRD;
     1137/** Pointer to a preprocessor reader state. */
     1138typedef KOCCPPRD *PKOCCPPRD;
     1139
     1140
     1141/**
     1142 * Allocate the initial C preprocessor output buffer.
     1143 *
     1144 * @param   pCppRd      The C preprocessor reader instance.
     1145 * @param   cbOldCpp    The size of the output the last time.  This is 0 if
     1146 *                      there was not previous run.
     1147 * @param   fOptimize   Whether optimizations are enabled.
     1148 */
     1149static void kOCCppRdInit(PKOCCPPRD pCppRd, size_t cbOldCpp, int fOptimize)
     1150{
     1151    pCppRd->cbBufAlloc = cbOldCpp ? (cbOldCpp + KOC_BUF_INCR) & ~(KOC_BUF_ALIGNMENT - 1) : KOC_BUF_MIN;
     1152    pCppRd->pszBuf = xmalloc(pCppRd->cbBufAlloc);
     1153    pCppRd->cchCurFileNm = 0;
     1154    pCppRd->cchOptimized = 0;
     1155    pCppRd->offCur = 0;
     1156    pCppRd->offRead = 0;
     1157    pCppRd->uOptLineNo = 1;
     1158    pCppRd->uCurLineNo = 1;
     1159    pCppRd->cEmptyLines = 0;
     1160    pCppRd->fDone = 0;
     1161    pCppRd->chSaved = 0;
     1162    pCppRd->fOptimize = fOptimize;
     1163
     1164    pCppRd->pszFileNmBuf = NULL;
     1165    pCppRd->cbFileNmBuf = 0;
     1166    pCppRd->cchCurFileNm = 0;
     1167
     1168    pCppRd->pszLineBuf = NULL;
     1169    pCppRd->cbLineBuf = 0;
     1170}
     1171
     1172
     1173static void kOCCppRdDelete(PKOCCPPRD pCppRd)
     1174{
     1175    free(pCppRd->pszBuf);
     1176    pCppRd->pszBuf = NULL;
     1177
     1178    free(pCppRd->pszFileNmBuf);
     1179    pCppRd->pszFileNmBuf = NULL;
     1180
     1181    free(pCppRd->pszLineBuf);
     1182    pCppRd->pszLineBuf = NULL;
     1183}
     1184
     1185
     1186/**
     1187 * Allocate more buffer space for the C preprocessor output.
     1188 *
     1189 * @param   pCppRd      The C preprocessor reader instance.
     1190 */
     1191static size_t kOCCppRdGrowBuffer(PKOCCPPRD pCppRd)
     1192{
     1193    pCppRd->cbBufAlloc += KOC_BUF_INCR;
     1194    pCppRd->pszBuf = xrealloc(pCppRd->pszBuf, pCppRd->cbBufAlloc);
     1195
     1196    return pCppRd->cbBufAlloc - pCppRd->offRead;
     1197}
     1198
     1199
     1200static char *kOCCppRdOptRemove(PKOCCPPRD pCppRd, char *pszStart, size_t cbRemove)
     1201{
     1202    size_t offStart = pszStart - pCppRd->pszBuf;
     1203    size_t cbToMove = pCppRd->offRead - offStart;
     1204
     1205    assert(pCppRd->offRead >= offStart);
     1206
     1207    memmove(pszStart, pszStart + cbRemove, cbToMove + 1);
     1208
     1209    pCppRd->offRead -= cbRemove;
     1210    assert(offStart >= pCppRd->offCur);
     1211    assert(pCppRd->offRead < 1 || pCppRd->pszBuf[pCppRd->offRead - 1] != '\0');
     1212    return pszStart;
     1213}
     1214
     1215
     1216static size_t kOCCppRdOptReplace(PKOCCPPRD pCppRd, size_t offStart, size_t cchReplaced,
     1217                                 const char *pchReplacement, size_t cchReplacement)
     1218{
     1219    size_t offDelta = cchReplacement - cchReplaced;
     1220
     1221    if (offDelta)
     1222    {
     1223        size_t cbLeft = pCppRd->offRead - offStart - cchReplaced;
     1224        assert(cbLeft <= pCppRd->offRead);
     1225
     1226        if (cchReplacement > cchReplaced)
     1227            while (pCppRd->offRead + offDelta >= pCppRd->cbBufAlloc)
     1228                kOCCppRdGrowBuffer(pCppRd);
     1229
     1230        memmove(pCppRd->pszBuf + offStart + cchReplacement,
     1231                pCppRd->pszBuf + offStart + cchReplaced,
     1232                cbLeft + 1);
     1233
     1234        pCppRd->offRead += offDelta;
     1235        if (pCppRd->offCur > offStart)
     1236        {
     1237            assert(pCppRd->offCur >= offStart + cchReplaced);
     1238            pCppRd->offCur += offDelta;
     1239        }
     1240        assert(pCppRd->offRead < 1 || pCppRd->pszBuf[pCppRd->offRead - 1] != '\0');
     1241    }
     1242
     1243    memcpy(pCppRd->pszBuf + offStart, pchReplacement, cchReplacement);
     1244
     1245    return offDelta;
     1246}
     1247
     1248
     1249static char *kOCCppRdOptGetEol(PKOCCPPRD pCppRd, char *pszCur, size_t cbLeft)
     1250{
     1251    char *pszEol = memchr(pszCur, '\n', cbLeft);
     1252    if (pszEol)
     1253    {
     1254        if (pszCur != pszEol && pszEol[-1] == '\r')
     1255            pszEol--;
     1256    }
     1257    else if (pCppRd->fDone && cbLeft)
     1258        pszEol = pszCur + cbLeft;
     1259    return pszEol;
     1260}
     1261
     1262static void kOCCppRdOptSetFile(PKOCCPPRD pCppRd, const char *pchFile, size_t cchFile)
     1263{
     1264    if (cchFile >= pCppRd->cbFileNmBuf)
     1265    {
     1266        pCppRd->cbFileNmBuf  = (cchFile + 15) & ~(size_t)15;
     1267        pCppRd->pszFileNmBuf = xrealloc(pCppRd->pszFileNmBuf, pCppRd->cbFileNmBuf);
     1268    }
     1269    memcpy(pCppRd->pszFileNmBuf, pchFile, cchFile);
     1270    pCppRd->pszFileNmBuf[cchFile] = '\0';
     1271    pCppRd->cchCurFileNm = cchFile;
     1272}
     1273
     1274
     1275static size_t kOCCppRdOptFmtLine(PKOCCPPRD pCppRd, uint32_t uLine, const char *pchFile, size_t cchFile)
     1276{
     1277    size_t cchUsed;
     1278    size_t cbNeeded;
     1279
     1280    /* Make sure we've got enough buffer space. */
     1281    cbNeeded = sizeof("#line 4888222111 \"\"\n") + cchFile;
     1282    if (cbNeeded > pCppRd->cbLineBuf)
     1283    {
     1284        pCppRd->cbLineBuf  = (cbNeeded + 32 + 15) & ~(size_t)15;
     1285        pCppRd->pszLineBuf = xrealloc(pCppRd->pszLineBuf, pCppRd->cbLineBuf);
     1286    }
     1287
     1288    /* Do the formatting. */
     1289    cchUsed = sprintf(pCppRd->pszLineBuf, "#line %lu", (unsigned long)uLine);
     1290    if (cchFile)
     1291    {
     1292        pCppRd->pszLineBuf[cchUsed++] = ' ';
     1293        pCppRd->pszLineBuf[cchUsed++] = '"';
     1294        memcpy(&pCppRd->pszLineBuf[cchUsed], pchFile, cchFile);
     1295        cchUsed += cchFile;
     1296        pCppRd->pszLineBuf[cchUsed++] = '"';
     1297    }
     1298    pCppRd->pszLineBuf[cchUsed++] = '\n';
     1299    pCppRd->pszLineBuf[cchUsed] = '\0';
     1300
     1301    return cchUsed;
     1302}
     1303
     1304
     1305static size_t kOCCppRdOptFmtNewLines(PKOCCPPRD pCppRd, uint32_t cNewLines)
     1306{
     1307    if (cNewLines + 1 > pCppRd->cbLineBuf)
     1308    {
     1309        pCppRd->cbLineBuf  = (cNewLines + 1 + 32 + 15) & ~(size_t)15;
     1310        pCppRd->pszLineBuf = xrealloc(pCppRd->pszLineBuf, pCppRd->cbLineBuf);
     1311    }
     1312
     1313    memset(pCppRd->pszLineBuf, '\n', cNewLines);
     1314    pCppRd->pszLineBuf[cNewLines] = '\0';
     1315    return cNewLines;
     1316}
     1317
     1318
     1319
     1320static char *kOCCppRdOptFlush(PKOCCPPRD pCppRd, char *pszCur, int fLineDirNext)
     1321{
     1322    size_t const cchOptimized = pCppRd->cchOptimized;
     1323    size_t const offTmp = pszCur - pCppRd->pszBuf;
     1324    assert(offTmp >= cchOptimized);
     1325    if (pCppRd->offCur > cchOptimized)
     1326    {
     1327        /*
     1328         * We've got unflushed whitelines.
     1329         */
     1330        size_t const cchInQuestion = pCppRd->offCur - cchOptimized;
     1331        uint32_t const cLinesInQuestion = pCppRd->uCurLineNo - pCppRd->uOptLineNo;
     1332        size_t cchLineDir;
     1333        size_t offDelta;
     1334
     1335        if (   cLinesInQuestion <= 7
     1336            || (cchLineDir = kOCCppRdOptFmtLine(pCppRd, pCppRd->uCurLineNo, NULL, 0)) >= cLinesInQuestion)
     1337            cchLineDir = kOCCppRdOptFmtNewLines(pCppRd, cLinesInQuestion);
     1338
     1339        offDelta = kOCCppRdOptReplace(pCppRd, cchOptimized, cchInQuestion, pCppRd->pszLineBuf, cchLineDir);
     1340        pszCur += offDelta;
     1341
     1342        pCppRd->cchOptimized = cchOptimized + cchLineDir;
     1343        pCppRd->uOptLineNo = pCppRd->uCurLineNo;
     1344
     1345        /* pCppRd->offCur is adjusted by the replace call */
     1346    }
     1347
     1348    (void)fLineDirNext; /* Use later if required. */
     1349    return pszCur;
     1350}
     1351
     1352
     1353static int kOCCppRdOptParseLine(PKOCCPPRD pCppRd, char *pszCur, char *pszEol,
     1354                                uint32_t *puNewLineNo, char **ppszNewFile, size_t *pcchNewFile)
     1355{
     1356    char    *psz = pszCur;
     1357    uint32_t uNewLineNo;
     1358    int      fIsShort;
     1359
     1360    /*
     1361     * Check if it's a #line directive of some kind and parse it.
     1362     */
     1363    if (*psz != '#')
     1364        return 0;
     1365    psz++;
     1366
     1367    fIsShort = MY_IS_BLANK(*psz);
     1368    while (MY_IS_BLANK(*psz))
     1369        psz++;
     1370
     1371    if (   psz[0] == 'l'
     1372        && psz[1] == 'i'
     1373        && psz[2] == 'n'
     1374        && psz[3] == 'e'
     1375        && MY_IS_BLANK(psz[4]) )
     1376    {
     1377        fIsShort = 0;
     1378        psz += 5;
     1379        while (MY_IS_BLANK(*psz))
     1380            psz++;
     1381    }
     1382    else if (fIsShort && isdigit(*psz))
     1383        fIsShort = 1;
     1384    else
     1385        return 0;
     1386
     1387    /* Parse the line number. */
     1388    if (!isdigit(*psz))
     1389        return 0;
     1390
     1391    uNewLineNo = *psz++ - '0';
     1392    while (isdigit(*psz))
     1393    {
     1394        uNewLineNo *= 10;
     1395        uNewLineNo += *psz++ - '0';
     1396    }
     1397    if (   psz != pszEol
     1398        && !MY_IS_BLANK(*psz))
     1399        return 0;
     1400
     1401    /*
     1402     * The file name part is optional.
     1403     */
     1404    while (MY_IS_BLANK(*psz))
     1405        psz++;
     1406
     1407    if (   psz != pszEol
     1408        && *psz == '"')
     1409    {
     1410        *ppszNewFile = ++psz;
     1411        while (   psz != pszEol
     1412               && (   *psz != '"'
     1413                   || (   psz[-1] == '\\'
     1414                       && kOCDepIsEscaped(psz, psz - *ppszNewFile)) )
     1415              )
     1416            psz++;
     1417        if (psz == pszEol)
     1418        {
     1419            /** @todo complain? */
     1420            return 0;
     1421        }
     1422        *pcchNewFile = psz - *ppszNewFile;
     1423
     1424        do
     1425            psz++;
     1426        while (psz != pszEol && MY_IS_BLANK(*psz));
     1427    }
     1428    else
     1429    {
     1430        /* No file given => Same as the current. */
     1431        *ppszNewFile = pCppRd->cchCurFileNm ? pCppRd->pszFileNmBuf : NULL;
     1432        *pcchNewFile = pCppRd->cchCurFileNm;
     1433    }
     1434    if (psz != pszEol)
     1435    {
     1436        /** @todo complain? */
     1437        return 0;
     1438    }
     1439
     1440    *puNewLineNo = uNewLineNo;
     1441    return 1;
     1442}
     1443
     1444
     1445static char *kOCCppRdOptHandleLine(PKOCCPPRD pCppRd, char *pszCur, size_t *pcbLeft, int *pfEmptyLine, char *pszEol)
     1446{
     1447    size_t const cchEol = pszEol - pszCur;
     1448    char *pszNewFile;
     1449    size_t cchNewFile;
     1450    uint32_t uNewLineNo;
     1451    assert(*pszEol == '\r' || *pszEol == '\n' || *pszEol == '\0');
     1452
     1453    if (!kOCCppRdOptParseLine(pCppRd, pszCur, pszEol, &uNewLineNo, &pszNewFile, &cchNewFile))
     1454    {
     1455        /*
     1456         * No line directive.  Flush pending optimizations and indicate that
     1457         * the line isn't empty and needs to be commited at EOL.
     1458         */
     1459        pszEol = kOCCppRdOptFlush(pCppRd, pszEol, 0);
     1460        *pfEmptyLine = 0;
     1461    }
     1462    else
     1463    {
     1464        char *pszCurFile = pCppRd->cchCurFileNm ? pCppRd->pszFileNmBuf : NULL;
     1465        if (   pszNewFile == pszCurFile
     1466            || (   cchNewFile == pCppRd->cchCurFileNm
     1467                && !memcmp(pszNewFile, pszCurFile, cchNewFile)) )
     1468        {
     1469            /*
     1470             * A #line directive specifying the same file.
     1471             */
     1472            if (uNewLineNo >= pCppRd->uCurLineNo)
     1473                *pfEmptyLine = 1;
     1474            else
     1475            {
     1476                /*
     1477                 * It went backwards, so we need to flush the old section of
     1478                 * the file and emit another directive for starting the new one.
     1479                 */
     1480                size_t const cchOrgLine = pszEol - pCppRd->pszBuf - pCppRd->offCur;
     1481                size_t cchLineDir;
     1482                pszEol = kOCCppRdOptFlush(pCppRd, pszEol, 1);
     1483
     1484                cchLineDir = kOCCppRdOptFmtLine(pCppRd, uNewLineNo, NULL, 0) - 1; /* sans \n */
     1485
     1486                pszEol += kOCCppRdOptReplace(pCppRd, pCppRd->offCur, cchOrgLine,
     1487                                             pCppRd->pszLineBuf, cchLineDir);
     1488
     1489                *pfEmptyLine = 0;
     1490            }
     1491        }
     1492        else
     1493        {
     1494            /*
     1495             * The #line directive changed the file.
     1496             */
     1497            size_t const cchOrgLine = pszEol - pCppRd->pszBuf - pCppRd->offCur;
     1498            size_t cchLineDir;
     1499            size_t offDelta;
     1500            assert(*pszEol == '\r' || *pszEol == '\n' || *pszEol == '\0');
     1501
     1502            offDelta = kOCCppRdOptFlush(pCppRd, pszEol, 1) - pszEol;
     1503            pszEol += offDelta;
     1504            pszNewFile += offDelta;
     1505            assert(*pszEol == '\r' || *pszEol == '\n' || *pszEol == '\0');
     1506
     1507            kOCCppRdOptSetFile(pCppRd, pszNewFile, cchNewFile);
     1508            cchLineDir = kOCCppRdOptFmtLine(pCppRd, uNewLineNo, pszNewFile, cchNewFile) - 1; /* sans \n */
     1509            assert(*pszEol == '\r' || *pszEol == '\n' || *pszEol == '\0');
     1510
     1511            pszEol += kOCCppRdOptReplace(pCppRd, pCppRd->offCur, cchOrgLine,
     1512                                         pCppRd->pszLineBuf, cchLineDir);
     1513            assert(*pszEol == '\r' || *pszEol == '\n' || *pszEol == '\0');
     1514
     1515            *pfEmptyLine = 0;
     1516        }
     1517
     1518        pCppRd->uCurLineNo = uNewLineNo - 1;
     1519        assert(*pszEol == '\r' || *pszEol == '\n' || *pszEol == '\0');
     1520    }
     1521
     1522    pCppRd->offCur = pszEol - pCppRd->pszBuf;
     1523    *pcbLeft -= cchEol;
     1524    return pszEol;
     1525}
     1526
     1527
     1528static void kOCCppRdOpt(PKOCCPPRD pCppRd)
     1529{
     1530    size_t cch;
     1531    char *pszEol;
     1532    char *pszCur = pCppRd->pszBuf + pCppRd->offCur;
     1533    size_t cbTodo = pCppRd->offRead - pCppRd->offCur;
     1534    int fEmptyLine = 1;
     1535
     1536    while (cbTodo > 0)
     1537    {
     1538        switch (*pszCur)
     1539        {
     1540            case ' ':
     1541            case '\t':
     1542                break;
     1543
     1544            case '\n':
     1545                pCppRd->offCur = pszCur - pCppRd->pszBuf + 1;
     1546                pCppRd->uCurLineNo++;
     1547                if (!fEmptyLine)
     1548                {
     1549                    pCppRd->cchOptimized = pCppRd->offCur;
     1550                    pCppRd->uOptLineNo = pCppRd->uCurLineNo;
     1551                }
     1552                else
     1553                    pCppRd->cEmptyLines++;
     1554                fEmptyLine = 1;
     1555                break;
     1556
     1557            case '\r': /* "\r\n" -> "\n" */
     1558                if (cbTodo == 1 && !pCppRd->fDone)
     1559                    return;
     1560                if (pszCur[1] == '\n')
     1561                {
     1562                    pszCur = kOCCppRdOptRemove(pCppRd, pszCur, 1);
     1563                    cbTodo -= 1;
     1564                    continue;
     1565                }
     1566                break;
     1567
     1568            case '#':
     1569                pszEol = kOCCppRdOptGetEol(pCppRd, pszCur + 1, cbTodo - 1);
     1570                if (!pszEol)
     1571                    return;
     1572                pszCur = kOCCppRdOptHandleLine(pCppRd, pszCur, &cbTodo, &fEmptyLine, pszEol);
     1573                continue;
     1574
     1575            default:
     1576                /*
     1577                 * Some non-white stuff encountered, flush pending white
     1578                 * line optimizations and skip to the end of the line.
     1579                 */
     1580                fEmptyLine = 0;
     1581                pszEol = kOCCppRdOptGetEol(pCppRd, pszCur + 1, cbTodo - 1);
     1582                if (!pszEol)
     1583                    return;
     1584                cch = pszEol - pszCur;
     1585
     1586                pszCur = kOCCppRdOptFlush(pCppRd, pszCur, 0);
     1587
     1588                cbTodo -= cch;
     1589                pszCur += cch;
     1590                continue;
     1591        }
     1592
     1593        cbTodo--;
     1594        pszCur++;
     1595    }
     1596}
     1597
     1598
     1599static void kOCCppRdOptFinalize(PKOCCPPRD pCppRd)
     1600{
     1601    pCppRd->fDone = 1;
     1602    assert(pCppRd->offRead < 1 || pCppRd->pszBuf[pCppRd->offRead - 1] != '\0');
     1603    pCppRd->pszBuf[pCppRd->offRead] = '\0';
     1604    kOCCppRdOpt(pCppRd);
     1605    kOCCppRdOptFlush(pCppRd, pCppRd->pszBuf + pCppRd->offCur, 0);
     1606}
     1607
     1608
     1609
     1610/**
     1611 * Read C preprocessor output from the given file descriptor, optionally
     1612 * optimzing it.
     1613 *
     1614 * @returns Number of bytes read. 0 indicates end of file.
     1615 *
     1616 * @param   pCppRd      The C preprocessor reader instance.
     1617 * @param   fdIn        The file descriptor to read the raw preprocessor output
     1618 *                      from.
     1619 * @param   ppszRet     Where to return the pointer to the output.
     1620 *
     1621 * @remarks Won't return on error, calls FatalDie on those occasions.
     1622 */
     1623static long kOCCppRdRead(PKOCCPPRD pCppRd, int fdIn, const char **ppszRet)
     1624{
     1625    size_t cbLeft;
     1626    long   cbRead;
     1627
     1628    if (pCppRd->fOptimize)
     1629    {
     1630        /*
     1631         * Optimize the C preprocessor output on the way thru.
     1632         */
     1633        size_t const cchOldOptimized = pCppRd->cchOptimized;
     1634        if (pCppRd->chSaved)
     1635            pCppRd->pszBuf[pCppRd->cchOptimized] = pCppRd->chSaved;
     1636
     1637        do
     1638        {
     1639            /* Read more raw C preprocessor output. */
     1640            cbLeft = pCppRd->cbBufAlloc - pCppRd->offRead;
     1641            if (cbLeft <= 1)
     1642                cbLeft = kOCCppRdGrowBuffer(pCppRd);
     1643            if (cbLeft > 256*1024)
     1644                cbLeft = 256*1024;  /* memmove() get's expensive if there is to much to work on - bad algorithm! */
     1645
     1646            do
     1647                cbRead = read(fdIn, pCppRd->pszBuf + pCppRd->offRead, (long)(cbLeft - 1));
     1648            while (cbRead < 0 && errno == EINTR);
     1649            if (cbRead < 0)
     1650                FatalDie("kOCCppRdRead - read(%d,,%ld) failed: %s\n",
     1651                         fdIn, (long)(cbLeft - 1), strerror(errno));
     1652            pCppRd->offRead += cbRead;
     1653
     1654            /* Optimize it. */
     1655            if (!cbRead)
     1656            {
     1657                kOCCppRdOptFinalize(pCppRd);
     1658                break;
     1659            }
     1660            kOCCppRdOpt(pCppRd);
     1661        } while (pCppRd->cchOptimized == cchOldOptimized);
     1662
     1663        *ppszRet = &pCppRd->pszBuf[cchOldOptimized];
     1664        pCppRd->chSaved = pCppRd->pszBuf[pCppRd->cchOptimized];
     1665        pCppRd->pszBuf[pCppRd->cchOptimized] = '\0';
     1666        cbRead = (long)(pCppRd->cchOptimized - cchOldOptimized);
     1667    }
     1668    else
     1669    {
     1670        /*
     1671         * Pass thru.
     1672         */
     1673        char *pszBuf;
     1674        cbLeft = pCppRd->cbBufAlloc - pCppRd->offRead;
     1675        if (cbLeft <= 1)
     1676            cbLeft = kOCCppRdGrowBuffer(pCppRd);
     1677        pszBuf = pCppRd->pszBuf + pCppRd->offRead;
     1678
     1679        do
     1680            cbRead = read(fdIn, pszBuf, (long)(cbLeft - 1));
     1681        while (cbRead < 0 && errno == EINTR);
     1682        if (cbRead < 0)
     1683            FatalDie("kOCCppRdRead - read(%d,,%ld) failed: %s\n",
     1684                     fdIn, (long)(cbLeft - 1), strerror(errno));
     1685
     1686        *ppszRet = pszBuf;
     1687        pCppRd->offRead += cbRead;
     1688        pszBuf[cbRead] = '\0';
     1689    }
     1690
     1691    return cbRead;
     1692}
     1693
     1694
     1695/**
     1696 * Grabs the output buffer from the C preprocessor reader.
     1697 *
     1698 * @param   pCppRd              The C preprocessor reader instance.
     1699 * @param   ppszRet             Where to return the pointer to the output.
     1700 * @param   pcbRet              Where to return the size of the output.
     1701 */
     1702static void kOCCppRdGrabOutput(PKOCCPPRD pCppRd, char **ppszRet, size_t *pcbRet)
     1703{
     1704    assert(pCppRd->offRead < 1 || pCppRd->pszBuf[pCppRd->offRead - 1] != '\0');
     1705    *ppszRet = pCppRd->pszBuf;
     1706    *pcbRet  = pCppRd->offRead;
     1707    pCppRd->pszBuf = NULL;
     1708    pCppRd->offRead = 0;
     1709}
     1710
     1711
    10911712
    10921713
     
    14332054    /** The dependency collector state.  */
    14342055    KOCDEP DepState;
     2056    /** Whether the optimizations are enabled. */
     2057    int fOptimizeCpp;
    14352058    /** Cache entry key that's used for some quick digest validation. */
    14362059    uint32_t uKey;
     
    20452668
    20462669/**
     2670 * Configures the preprocessor output optimizations.
     2671 *
     2672 * @param   pEntry                  The cache entry.
     2673 * @param   fOptimizeCpp            The one and only flag, so far.
     2674 */
     2675static void kOCEntrySetOptimizations(PKOCENTRY pEntry, int fOptimizeCpp)
     2676{
     2677    pEntry->fOptimizeCpp = fOptimizeCpp;
     2678}
     2679
     2680
     2681/**
    20472682 * Spawns a child in a synchronous fashion.
    20482683 * Terminating on failure.
     
    24703105{
    24713106    KOCSUMCTX Ctx;
    2472     long cbLeft;
    2473     long cbAlloc;
    2474     char *psz;
     3107    KOCCPPRD CppRd;
    24753108
    24763109    kOCSumInitWithCtx(&pEntry->New.SumHead, &Ctx);
    2477     cbAlloc = pEntry->Old.cbCpp ? ((long)pEntry->Old.cbCpp + 4*1024*1024 + 4096) & ~(4*1024*1024 - 1) : 4*1024*1024;
    2478     cbLeft = cbAlloc;
    2479     pEntry->New.pszCppMapping = psz = xmalloc(cbAlloc);
     3110    kOCCppRdInit(&CppRd, pEntry->Old.cbCpp, pEntry->fOptimizeCpp);
     3111
    24803112    for (;;)
    24813113    {
     
    24833115         * Read data from the pipe.
    24843116         */
    2485         long cbRead = read(fdIn, psz, cbLeft - 1);
     3117        const char *psz;
     3118        long cbRead = kOCCppRdRead(&CppRd, fdIn, &psz);
    24863119        if (!cbRead)
    24873120            break;
    2488         if (cbRead < 0)
    2489         {
    2490             if (errno == EINTR)
    2491                 continue;
    2492             FatalDie("PreProcess - read(%d,,%ld) failed: %s\n",
    2493                      fdIn, (long)cbLeft, strerror(errno));
    2494         }
    24953121
    24963122        /*
    24973123         * Process the data.
    24983124         */
    2499         psz[cbRead] = '\0';
    25003125        kOCSumUpdate(&pEntry->New.SumHead, &Ctx, psz, cbRead);
    25013126        if (pEntry->pszMakeDepFilename)
    25023127            kOCDepConsumer(&pEntry->DepState, psz, cbRead);
    2503 
    2504         /*
    2505          * Advance.
    2506          */
    2507         psz += cbRead;
    2508         cbLeft -= cbRead;
    2509         if (cbLeft <= 1)
    2510         {
    2511             size_t off = psz - pEntry->New.pszCppMapping;
    2512             cbLeft  += 4*1024*1024;
    2513             cbAlloc += 4*1024*1024;
    2514             pEntry->New.pszCppMapping = xrealloc(pEntry->New.pszCppMapping, cbAlloc);
    2515             psz = pEntry->New.pszCppMapping + off;
    2516         }
    25173128    }
    25183129
    25193130    close(fdIn);
    2520     pEntry->New.cbCpp = cbAlloc - cbLeft;
     3131    kOCCppRdGrabOutput(&CppRd, &pEntry->New.pszCppMapping, &pEntry->New.cbCpp);
     3132    kOCCppRdDelete(&CppRd);
    25213133    kOCSumFinalize(&pEntry->New.SumHead, &Ctx);
    25223134    kOCSumInfo(&pEntry->New.SumHead, 4, "cpp (pipe)");
     
    25663178
    25673179        /*
    2568          * Precompile it and calculate the checksum on the output.
     3180         * Preprocess it and calculate the checksum on the output.
    25693181         */
    25703182        InfoMsg(3, "precompiling -> '%s'...\n", pEntry->New.pszCppName);
     
    27473359#endif
    27483360    KOCSUMCTX Ctx;
    2749     long cbLeft;
    2750     long cbAlloc;
    2751     char *psz;
     3361    KOCCPPRD  CppRd;
    27523362
    27533363    kOCSumInitWithCtx(&pEntry->New.SumHead, &Ctx);
    2754     cbAlloc = pEntry->Old.cbCpp ? ((long)pEntry->Old.cbCpp + 4*1024*1024 + 4096) & ~(4*1024*1024 - 1) : 4*1024*1024;
    2755     cbLeft = cbAlloc;
    2756     pEntry->New.pszCppMapping = psz = xmalloc(cbAlloc);
     3364    kOCCppRdInit(&CppRd, pEntry->Old.cbCpp, pEntry->fOptimizeCpp);
    27573365    InfoMsg(3, "preprocessor|compile - starting passhtru...\n");
    27583366    for (;;)
     
    27613369         * Read data from the pipe.
    27623370         */
    2763         long cbRead = read(fdIn, psz, cbLeft - 1);
     3371        const char *psz;
     3372        long cbRead = kOCCppRdRead(&CppRd, fdIn, &psz);
    27643373        if (!cbRead)
    27653374            break;
    2766         if (cbRead < 0)
    2767         {
    2768             if (errno == EINTR)
    2769                 continue;
    2770             FatalDie("preprocess|compile - read(%d,,%ld) failed: %s\n",
    2771                      fdIn, (long)cbLeft, strerror(errno));
    2772         }
    27733375        InfoMsg(3, "preprocessor|compile - read %d\n", cbRead);
    27743376
     
    27763378         * Process the data.
    27773379         */
    2778         psz[cbRead] = '\0';
    27793380        kOCSumUpdate(&pEntry->New.SumHead, &Ctx, psz, cbRead);
    27803381        if (pEntry->pszMakeDepFilename)
     
    27973398            psz += cbWritten;
    27983399            cbRead -= cbWritten;
    2799             cbLeft -= cbWritten;
    28003400        } while (cbRead > 0);
    28013401
    2802         /*
    2803          * Expand the buffer?
    2804          */
    2805         if (cbLeft <= 1)
    2806         {
    2807             size_t off = psz - pEntry->New.pszCppMapping;
    2808             cbLeft = 4*1024*1024;
    2809             cbAlloc += cbLeft;
    2810             pEntry->New.pszCppMapping = xrealloc(pEntry->New.pszCppMapping, cbAlloc);
    2811             psz = pEntry->New.pszCppMapping + off;
    2812         }
    28133402    }
    28143403    InfoMsg(3, "preprocessor|compile - done passhtru\n");
     
    28163405    close(fdIn);
    28173406    close(fdOut);
    2818     pEntry->New.cbCpp = cbAlloc - cbLeft;
     3407    kOCCppRdGrabOutput(&CppRd, &pEntry->New.pszCppMapping, &pEntry->New.cbCpp);
     3408    kOCCppRdDelete(&CppRd);
    28193409    kOCSumFinalize(&pEntry->New.SumHead, &Ctx);
    28203410    kOCSumInfo(&pEntry->New.SumHead, 4, "cpp (tee)");
     
    42704860    int fMakeDepGenStubs = 0;
    42714861    int fMakeDepQuiet = 0;
     4862    int fOptimizePreprocessorOutput = 0;
    42724863
    42734864    const char *pszTarget = NULL;
     
    43874978        else if (!strcmp(argv[i], "--make-dep-quiet"))
    43884979            fMakeDepQuiet = 1;
     4980        else if (!strcmp(argv[i], "-O1") || !strcmp(argv[i], "--optimize-1"))
     4981            fOptimizePreprocessorOutput = 1;
    43894982        else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--passthru"))
    43904983            fRedirPreCompStdOut = fRedirCompileStdIn = 1;
     
    44385031            if (!psz || psz <= pszCacheName)
    44395032                psz = (char *)pszCacheName + cch;
    4440             memcpy(psz, ".koc", sizeof(".koc") - 1);
     5033            memcpy(psz, ".koc", sizeof(".koc"));
    44415034        }
    44425035        pszCacheFile = MakePathFromDirAndFile(pszCacheName, pszCacheDir);
     
    44615054    kOCEntrySetPipedMode(pEntry, fRedirPreCompStdOut, fRedirCompileStdIn, pszNmPipeCompile);
    44625055    kOCEntrySetDepFilename(pEntry, pszMakeDepFilename, fMakeDepFixCase, fMakeDepQuiet, fMakeDepGenStubs);
     5056    kOCEntrySetOptimizations(pEntry, fOptimizePreprocessorOutput);
    44635057
    44645058    /*
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