VirtualBox

Changeset 41246 in vbox


Ignore:
Timestamp:
May 10, 2012 8:05:32 PM (13 years ago)
Author:
vboxsync
Message:

Macro expansion fundamentals.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bldprogs/VBoxCPP.cpp

    r41226 r41246  
    7070*******************************************************************************/
    7171/**
     72 * Variable string buffer (very simple version of SCMSTREAM).
     73 */
     74typedef struct VBCPPSTRBUF
     75{
     76    /** The preprocessor instance (for error reporting). */
     77    struct VBCPP   *pThis;
     78    /** The length of the string in the buffer. */
     79    size_t          cchBuf;
     80    /** The string storage. */
     81    char           *pszBuf;
     82    /** Allocated buffer space. */
     83    size_t          cbBufAllocated;
     84} VBCPPSTRBUF;
     85/** Pointer to a variable string buffer. */
     86typedef VBCPPSTRBUF *PVBCPPSTRBUF;
     87
     88
     89/**
    7290 * The preprocessor mode.
    7391 */
     
    89107    /** The string space core. */
    90108    RTSTRSPACECORE      Core;
     109    /** For linking macros that have the fExpanding flag set. */
     110    struct VBCPPDEF    *pUpExpanding;
    91111    /** Whether it's a function. */
    92112    bool                fFunction;
     
    95115    /** Set if originating on the command line. */
    96116    bool                fCmdLine;
    97     /** The number of known arguments.*/
     117    /** Set if this macro is currently being expanded and should not be
     118     * recursively applied. */
     119    bool                fExpanding;
     120    /** The number of known arguments. */
    98121    uint32_t            cArgs;
    99122    /** Pointer to a list of argument names. */
     
    108131/** Pointer to a define. */
    109132typedef VBCPPDEF *PVBCPPDEF;
     133
     134
     135/**
     136 * Macro expansion data.
     137 */
     138typedef struct VBCPPMACROEXP
     139{
     140    /** The expansion buffer. */
     141    char           *pszBuf;
     142    /** The length of the string in the expansion buffer. */
     143    size_t          cchBuf;
     144    /** The current allocated buffer size. */
     145    size_t          cbBufAllocated;
     146    /** List of expanding macros (Stack). */
     147    PVBCPPDEF       pMacroStack;
     148    /** The input stream (in case we want to look for parameter lists). */
     149    PSCMSTREAM      pStrmInput;
     150    /** Array of argument values.  Used when expanding function style macros.  */
     151    char          **papszArgs;
     152    /** The number of argument values current in papszArgs. */
     153    size_t          cArgs;
     154    /** The number of argument values papszArgs can currently hold  */
     155    size_t          cArgsAlloced;
     156} VBCPPMACROEXP;
     157/** Pointer to macro expansion data. */
     158typedef VBCPPMACROEXP *PVBCPPMACROEXP;
    110159
    111160
     
    294343*******************************************************************************/
    295344static PVBCPPDEF    vbcppMacroLookup(PVBCPP pThis, const char *pszDefine, size_t cchDefine);
    296 static RTEXITCODE   vbcppMacroExpandFunctionLike(PVBCPP pThis, PVBCPPDEF pMacro, PSCMSTREAM pStrmInput, char **ppszExpansion);
    297 static RTEXITCODE   vbcppMacroExpandObjectLike(PVBCPP pThis, PVBCPPDEF pMacro, PSCMSTREAM pStrmInput, char **ppszExpansion);
     345static RTEXITCODE   vbcppMacroExpandIt(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offMacro, PVBCPPDEF pMacro, size_t offParameters);
     346static RTEXITCODE   vbcppMacroExpandReScan(PVBCPP pThis, PVBCPPMACROEXP pExp);
     347static void         vbcppMacroExpandCleanup(PVBCPPMACROEXP pExp);
    298348
    299349
     
    381431
    382432
     433
     434
     435/*
     436 *
     437 *
     438 * Variable String Buffers.
     439 * Variable String Buffers.
     440 * Variable String Buffers.
     441 * Variable String Buffers.
     442 * Variable String Buffers.
     443 *
     444 *
     445 */
     446
     447
     448static void vbcppStrBufInit(PVBCPPSTRBUF pStrBuf, PVBCPP pThis)
     449{
     450    pStrBuf->pThis              = pThis;
     451    pStrBuf->cchBuf             = 0;
     452    pStrBuf->cbBufAllocated     = 0;
     453    pStrBuf->pszBuf             = NULL;
     454}
     455
     456
     457static void vbcppStrBufDelete(PVBCPPSTRBUF pStrBuf)
     458{
     459    RTMemFree(pStrBuf->pszBuf);
     460    pStrBuf->pszBuf = NULL;
     461}
     462
     463
     464static RTEXITCODE vbcppStrBufGrow(PVBCPPSTRBUF pStrBuf, size_t cbMin)
     465{
     466    if (pStrBuf->cbBufAllocated >= cbMin)
     467        return RTEXITCODE_SUCCESS;
     468
     469    size_t cbNew = pStrBuf->cbBufAllocated * 2;
     470    if (cbNew < cbMin)
     471        cbNew = RT_ALIGN_Z(cbMin, _1K);
     472    void *pv = RTMemRealloc(pStrBuf->pszBuf, cbNew);
     473    if (!pv)
     474        return vbcppError(pStrBuf->pThis, "out of memory (%zu bytes)", cbNew);
     475
     476    pStrBuf->pszBuf         = (char *)pv;
     477    pStrBuf->cbBufAllocated = cbNew;
     478    return RTEXITCODE_SUCCESS;
     479}
     480
     481
     482static RTEXITCODE vbcppStrBufAppendN(PVBCPPSTRBUF pStrBuf, const char *pchSrc, size_t cchSrc)
     483{
     484    size_t cchBuf = pStrBuf->cchBuf;
     485    if (cchBuf + cchSrc + 1 > pStrBuf->cbBufAllocated)
     486    {
     487        RTEXITCODE rcExit = vbcppStrBufGrow(pStrBuf, cchBuf + cchSrc + 1);
     488        if (rcExit != RTEXITCODE_SUCCESS)
     489            return rcExit;
     490    }
     491
     492    memcpy(&pStrBuf->pszBuf[cchBuf], pchSrc, cchSrc);
     493    cchBuf += cchSrc;
     494    pStrBuf->pszBuf[cchBuf] = '\0';
     495    pStrBuf->cchBuf = cchBuf;
     496
     497    return RTEXITCODE_SUCCESS;
     498}
     499
     500
     501static RTEXITCODE vbcppStrBufAppendCh(PVBCPPSTRBUF pStrBuf, char ch)
     502{
     503    size_t cchBuf = pStrBuf->cchBuf;
     504    if (cchBuf + 2 > pStrBuf->cbBufAllocated)
     505    {
     506        RTEXITCODE rcExit = vbcppStrBufGrow(pStrBuf, cchBuf + 2);
     507        if (rcExit != RTEXITCODE_SUCCESS)
     508            return rcExit;
     509    }
     510
     511    pStrBuf->pszBuf[cchBuf++] = ch;
     512    pStrBuf->pszBuf[cchBuf] = '\0';
     513    pStrBuf->cchBuf = cchBuf;
     514
     515    return RTEXITCODE_SUCCESS;
     516}
     517
     518
     519static RTEXITCODE vbcppStrBufAppend(PVBCPPSTRBUF pStrBuf, const char *psz)
     520{
     521    return vbcppStrBufAppendN(pStrBuf, psz, strlen(psz));
     522}
     523
     524
     525static char vbcppStrBufLastCh(PVBCPPSTRBUF pStrBuf)
     526{
     527    if (!pStrBuf->cchBuf)
     528        return '\0';
     529    return pStrBuf->pszBuf[pStrBuf->cchBuf - 1];
     530}
     531
     532
     533
     534
     535
     536
     537
    383538/*
    384539 *
     
    460615
    461616
     617
     618/**
     619 * Checks if the given character is valid C punctuation.
     620 *
     621 * @returns true / false.
     622 * @param   ch                  The character to inspect.
     623 */
     624DECLINLINE(bool) vbcppIsCPunctuationLeadChar(char ch)
     625{
     626    switch (ch)
     627    {
     628        case '!':
     629        case '#':
     630        case '%':
     631        case '&':
     632        case '(':
     633        case ')':
     634        case '*':
     635        case '+':
     636        case ',':
     637        case '-':
     638        case '.':
     639        case '/':
     640        case ':':
     641        case ';':
     642        case '<':
     643        case '=':
     644        case '>':
     645        case '?':
     646        case '[':
     647        case ']':
     648        case '^':
     649        case '{':
     650        case '|':
     651        case '}':
     652        case '~':
     653            return true;
     654        default:
     655            return false;
     656    }
     657}
     658
     659
     660/**
     661 * Checks if the given string start with valid C punctuation.
     662 *
     663 * @returns 0 if not, otherwise the length of the punctuation.
     664 * @param   pch                 The which start we should evaluate.
     665 * @param   cchMax              The maximum string length.
     666 */
     667static size_t vbcppIsCPunctuationLeadChar(const char *psz, size_t cchMax)
     668{
     669    if (!cchMax)
     670        return 0;
     671
     672    switch (psz[0])
     673    {
     674        case '!':
     675        case '*':
     676        case '/':
     677        case '=':
     678        case '^':
     679            if (cchMax >= 2 && psz[1] == '=')
     680                return 2;
     681            return 1;
     682
     683        case '#':
     684            if (cchMax >= 2 && psz[1] == '#')
     685                return 2;
     686            return 1;
     687
     688        case '%':
     689            if (cchMax >= 2 && (psz[1] == '=' || psz[1] == '>'))
     690                return 2;
     691            if (cchMax >= 2 && psz[1] == ':')
     692            {
     693                if (cchMax >= 4 && psz[2] == '%' && psz[3] == ':')
     694                    return 4;
     695                return 2;
     696            }
     697            return 1;
     698
     699        case '&':
     700            if (cchMax >= 2 && (psz[1] == '=' || psz[1] == '&'))
     701                return 2;
     702            return 1;
     703
     704        case '(':
     705        case ')':
     706        case ',':
     707        case '?':
     708        case '[':
     709        case ']':
     710        case '{':
     711        case '}':
     712            return 1;
     713
     714        case '+':
     715            if (cchMax >= 2 && (psz[1] == '=' || psz[1] == '+'))
     716                return 2;
     717            return 1;
     718
     719        case '-':
     720            if (cchMax >= 2 && (psz[1] == '=' || psz[1] == '-' || psz[1] == '>'))
     721                return 2;
     722            return 1;
     723
     724        case ':':
     725            if (cchMax >= 2 && psz[1] == '>')
     726                return 2;
     727            return 1;
     728
     729        case ';':
     730            return 1;
     731
     732        case '<':
     733            if (cchMax >= 2 && psz[1] == '<')
     734            {
     735                if (cchMax >= 3 && psz[2] == '=')
     736                    return 3;
     737                return 2;
     738            }
     739            if (cchMax >= 2 && (psz[1] == '=' || psz[1] == ':' || psz[1] == '%'))
     740                return 2;
     741            return 1;
     742
     743        case '.':
     744            if (cchMax >= 3 && psz[1] == '.' && psz[2] == '.')
     745                return 3;
     746            return 1;
     747
     748        case '>':
     749            if (cchMax >= 2 && psz[1] == '>')
     750            {
     751                if (cchMax >= 3 && psz[2] == '=')
     752                    return 3;
     753                return 2;
     754            }
     755            if (cchMax >= 2 && psz[1] == '=')
     756                return 2;
     757            return 1;
     758
     759        case '|':
     760            if (cchMax >= 2 && (psz[1] == '=' || psz[1] == '|'))
     761                return 2;
     762            return 1;
     763
     764        case '~':
     765            return 1;
     766
     767        default:
     768            return 0;
     769    }
     770}
    462771
    463772
     
    682991 * Skips white spaces.
    683992 *
    684  * @returns The current location upon return..
     993 * @returns The current location upon return.
    685994 * @param   pStrmInput          The input stream.
    686995 */
     
    9261235
    9271236/**
    928  * Processes a single quoted litteral.
     1237 * Processes a single quoted constant.
    9291238 *
    9301239 * Must not replace any C-words in strings.
     
    10011310static RTEXITCODE vbcppProcessIdentifier(PVBCPP pThis, PSCMSTREAM pStrmInput, char ch)
    10021311{
    1003     int         rc     = VINF_SUCCESS;
    1004     RTEXITCODE  rcExit = RTEXITCODE_SUCCESS;
     1312    RTEXITCODE  rcExit;
    10051313    size_t      cchDefine;
    10061314    const char *pchDefine = ScmStreamCGetWordM1(pStrmInput, &cchDefine);
     
    10151323            || vbcppInputLookForLeftParenthesis(pThis, pStrmInput)) )
    10161324    {
    1017         char *pszExpansion = NULL;
    1018         if (!pMacro->fFunction)
    1019             rcExit = vbcppMacroExpandObjectLike(pThis, pMacro, pStrmInput, &pszExpansion);
     1325        /*
     1326         * Expand it.
     1327         */
     1328        VBCPPMACROEXP ExpCtx;
     1329        ExpCtx.pMacroStack    = NULL;
     1330        ExpCtx.pStrmInput     = pStrmInput;
     1331        ExpCtx.papszArgs      = NULL;
     1332        ExpCtx.cArgs          = 0;
     1333        ExpCtx.cArgsAlloced   = 0;
     1334        ExpCtx.cchBuf         = cchDefine;
     1335        ExpCtx.cbBufAllocated = RT_ALIGN_Z(cchDefine + 1, 16);
     1336        ExpCtx.pszBuf         = (char *)RTMemAlloc(ExpCtx.cbBufAllocated);
     1337        if (ExpCtx.pszBuf)
     1338        {
     1339            memcpy(ExpCtx.pszBuf, pchDefine, cchDefine);
     1340            ExpCtx.pszBuf[cchDefine] = '\0';
     1341
     1342            rcExit = vbcppMacroExpandIt(pThis, &ExpCtx, 0 /* offset */, pMacro, cchDefine);
     1343            if (rcExit == RTEXITCODE_SUCCESS)
     1344                rcExit = vbcppMacroExpandReScan(pThis, &ExpCtx);
     1345            if (rcExit == RTEXITCODE_SUCCESS)
     1346            {
     1347                /*
     1348                 * Insert it into the output stream.  Make sure there is a
     1349                 * whitespace following it.
     1350                 */
     1351                int rc = ScmStreamWrite(&pThis->StrmOutput, ExpCtx.pszBuf, ExpCtx.cchBuf);
     1352                if (RT_SUCCESS(rc))
     1353                {
     1354                    unsigned chAfter = ScmStreamPeekCh(pStrmInput);
     1355                    if (chAfter != ~(unsigned)0 && !RT_C_IS_SPACE(chAfter))
     1356                        rcExit = vbcppOutputCh(pThis, ' ');
     1357                }
     1358                else
     1359                    rcExit = vbcppError(pThis, "Output error: %Rrc", rc);
     1360            }
     1361            vbcppMacroExpandCleanup(&ExpCtx);
     1362        }
    10201363        else
    1021             rcExit = vbcppMacroExpandFunctionLike(pThis, pMacro, pStrmInput, &pszExpansion);
    1022         if (rcExit == RTEXITCODE_SUCCESS)
    1023         {
    1024             rc = ScmStreamWrite(&pThis->StrmOutput, pszExpansion, strlen(pszExpansion));
    1025             if (RT_FAILURE(rc))
    1026                 rcExit = vbcppError(pThis, "Output error: %Rrc", rc);
    1027             RTMemFree(pszExpansion);
    1028         }
     1364            rcExit = vbcppError(pThis, "out of memory");
    10291365    }
    10301366    else
     
    10341370         * output the text unchanged.
    10351371         */
    1036         rc = ScmStreamWrite(&pThis->StrmOutput, pchDefine, cchDefine);
    1037         if (RT_FAILURE(rc))
     1372        int rc = ScmStreamWrite(&pThis->StrmOutput, pchDefine, cchDefine);
     1373        if (RT_SUCCESS(rc))
     1374            rcExit = RTEXITCODE_SUCCESS;
     1375        else
    10381376            rcExit = vbcppError(pThis, "Output error: %Rrc", rc);
    10391377    }
     
    10961434
    10971435
    1098 
    1099 static RTEXITCODE vbcppMacroExpandObjectLike(PVBCPP pThis, PVBCPPDEF pMacro, PSCMSTREAM pStrmInput, char **ppszExpansion)
    1100 {
    1101     *ppszExpansion = RTStrDup(pMacro->szValue);
    1102     if (!*ppszExpansion)
    1103         return vbcppError(pThis, "out of memory");
     1436static uint32_t vbcppMacroLookupArg(PVBCPPDEF pMacro, const char *pchName, size_t cchName)
     1437{
     1438    Assert(cchName > 0);
     1439
     1440    char const ch = *pchName;
     1441    for (uint32_t i = 0; i < pMacro->cArgs; i++)
     1442        if (   pMacro->papszArgs[i][0] == ch
     1443            && !strncmp(pMacro->papszArgs[i], pchName, cchName)
     1444            && pMacro->papszArgs[i][cchName] == '\0')
     1445            return i;
     1446
     1447    if (   pMacro->fVarArg
     1448        && cchName == sizeof("__VA_ARGS__") - 1
     1449        && !strncmp(pchName, "__VA_ARGS__", sizeof("__VA_ARGS__") - 1) )
     1450        return pMacro->cArgs;
     1451
     1452    return UINT32_MAX;
     1453}
     1454
     1455
     1456
     1457
     1458static RTEXITCODE vbcppMacroExpandReplace(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t off, size_t cchToReplace,
     1459                                          const char *pchReplacement, size_t cchReplacement)
     1460{
     1461    /*
     1462     * Figure how much space we actually need.
     1463     * (Hope this whitespace stuff is correct...)
     1464     */
     1465    bool const fLeadingSpace            = off > 0
     1466                                       && !RT_C_IS_SPACE(pExp->pszBuf[off - 1]);
     1467    bool const fTrailingSpace           = off + cchToReplace < pExp->cchBuf
     1468                                       && !RT_C_IS_SPACE(pExp->pszBuf[off + cchToReplace]);
     1469    size_t const cchActualReplacement   = fLeadingSpace + cchReplacement + fTrailingSpace;
     1470
     1471    /*
     1472     * Adjust the buffer size and contents.
     1473     */
     1474    if (cchActualReplacement > cchToReplace)
     1475    {
     1476        size_t const offMore = cchActualReplacement - cchToReplace;
     1477
     1478        /* Ensure enough buffer space. */
     1479        size_t cbMinBuf = offMore + pExp->cchBuf + 1;
     1480        if (cbMinBuf > pExp->cbBufAllocated)
     1481        {
     1482            if (cbMinBuf > ~(size_t)0 / 4)
     1483                return vbcppError(pThis, "Expansion is too big - %u bytes or more", offMore + pExp->cchBuf);
     1484            size_t cbNew = pExp->cbBufAllocated * 2;
     1485            while (cbNew < cbMinBuf)
     1486                cbNew *= 2;
     1487            void *pvNew = RTMemRealloc(pExp->pszBuf, cbNew);
     1488            if (!pvNew)
     1489                return vbcppError(pThis, "Out of memory (%u bytes)", cbNew);
     1490            pExp->pszBuf         = (char *)pvNew;
     1491            pExp->cbBufAllocated = cbNew;
     1492        }
     1493
     1494        /* Push the chars following the replacement area down to make room. */
     1495        memmove(&pExp->pszBuf[off + cchToReplace + offMore],
     1496                &pExp->pszBuf[off + cchToReplace],
     1497                pExp->cchBuf - off - cchToReplace + 1);
     1498        pExp->cchBuf += offMore;
     1499
     1500    }
     1501    else if (cchActualReplacement < cchToReplace)
     1502    {
     1503        size_t const offLess = cchToReplace - cchActualReplacement;
     1504
     1505        /* Pull the chars following the replacement area up. */
     1506        memmove(&pExp->pszBuf[off + cchToReplace - offLess],
     1507                &pExp->pszBuf[off + cchToReplace],
     1508                pExp->cchBuf - off - cchToReplace + 1);
     1509        pExp->cchBuf -= offLess;
     1510    }
     1511
     1512    /*
     1513     * Insert the replacement string.
     1514     */
     1515    char *pszCur = &pExp->pszBuf[off];
     1516    if (fLeadingSpace)
     1517        *pszCur++ = ' ';
     1518    memcpy(pszCur, pchReplacement, cchReplacement);
     1519    if (fTrailingSpace)
     1520        *pszCur++ = ' ';
     1521
     1522    Assert(strlen(pExp->pszBuf) == pExp->cchBuf);
     1523    Assert(pExp->cchBuf < pExp->cbBufAllocated);
     1524
    11041525    return RTEXITCODE_SUCCESS;
    11051526}
    11061527
    11071528
    1108 static RTEXITCODE vbcppMacroExpandFunctionLike(PVBCPP pThis, PVBCPPDEF pMacro, PSCMSTREAM pStrmInput, char **ppszExpansion)
    1109 {
    1110     *ppszExpansion = NULL;
    1111     return vbcppError(pThis, "Expansion of function like macros is not yet supported");
     1529static unsigned vbcppMacroExpandPeekCh(PVBCPPMACROEXP pExp, size_t *poff)
     1530{
     1531    size_t off = *poff;
     1532    if (off >= pExp->cchBuf)
     1533        return ScmStreamPeekCh(pExp->pStrmInput);
     1534    return pExp->pszBuf[off];
     1535}
     1536
     1537
     1538static unsigned vbcppMacroExpandGetCh(PVBCPPMACROEXP pExp, size_t *poff)
     1539{
     1540    size_t off = *poff;
     1541    if (off >= pExp->cchBuf)
     1542        return ScmStreamGetCh(pExp->pStrmInput);
     1543    *poff = off + 1;
     1544    return pExp->pszBuf[off];
     1545}
     1546
     1547
     1548static RTEXITCODE vbcppMacroExpandSkipEolEx(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t *poff, unsigned chFirst)
     1549{
     1550    if (chFirst == '\r')
     1551    {
     1552        unsigned ch2 = vbcppMacroExpandPeekCh(pExp, poff);
     1553        if (ch2 == '\n')
     1554        {
     1555            ch2 = ScmStreamGetCh(pExp->pStrmInput);
     1556            AssertReturn(ch2 == '\n', vbcppError(pThis, "internal error"));
     1557        }
     1558    }
     1559    return RTEXITCODE_SUCCESS;
     1560}
     1561
     1562
     1563static RTEXITCODE vbcppMacroExpandSkipEol(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t *poff)
     1564{
     1565    unsigned ch = vbcppMacroExpandGetCh(pExp, poff);
     1566    AssertReturn(ch == '\r' || ch == '\n', vbcppError(pThis, "internal error"));
     1567    return vbcppMacroExpandSkipEolEx(pThis, pExp, poff, ch);
     1568}
     1569
     1570
     1571static RTEXITCODE vbcppMacroExpandSkipCommentLine(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t *poff)
     1572{
     1573    unsigned ch = vbcppMacroExpandGetCh(pExp, poff);
     1574    AssertReturn(ch == '/', vbcppError(pThis, "Internal error - expected '/' got '%c'", ch));
     1575
     1576    unsigned chPrev = 0;
     1577    while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0)
     1578    {
     1579        if (ch == '\r' || ch == '\n')
     1580        {
     1581            RTEXITCODE rcExit = vbcppMacroExpandSkipEolEx(pThis, pExp, poff, ch);
     1582            if (rcExit != RTEXITCODE_SUCCESS)
     1583                return rcExit;
     1584            if (chPrev != '\\')
     1585                break;
     1586        }
     1587
     1588        chPrev = ch;
     1589    }
     1590    return RTEXITCODE_SUCCESS;
     1591}
     1592
     1593
     1594static RTEXITCODE vbcppMacroExpandSkipComment(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t *poff)
     1595{
     1596    unsigned ch = vbcppMacroExpandGetCh(pExp, poff);
     1597    AssertReturn(ch == '*', vbcppError(pThis, "Internal error - expected '*' got '%c'", ch));
     1598
     1599    unsigned chPrev2 = 0;
     1600    unsigned chPrev  = 0;
     1601    while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0)
     1602    {
     1603        if (ch == '/' && chPrev == '*')
     1604            break;
     1605
     1606        if (ch == '\r' || ch == '\n')
     1607        {
     1608            RTEXITCODE rcExit = vbcppMacroExpandSkipEolEx(pThis, pExp, poff, ch);
     1609            if (rcExit != RTEXITCODE_SUCCESS)
     1610                return rcExit;
     1611            if (chPrev == '\\')
     1612            {
     1613                chPrev = chPrev2;       /* for line splicing */
     1614                continue;
     1615            }
     1616        }
     1617
     1618        chPrev2 = chPrev;
     1619        chPrev  = ch;
     1620    }
     1621    return RTEXITCODE_SUCCESS;
     1622}
     1623
     1624
     1625static RTEXITCODE vbcppMacroExpandGrowArgArray(PVBCPP pThis, PVBCPPMACROEXP pExp, uint32_t cMinArgs)
     1626{
     1627    if (cMinArgs > pExp->cArgsAlloced)
     1628    {
     1629        void *pv = RTMemRealloc(pExp->papszArgs, cMinArgs * sizeof(char *));
     1630        if (!pv)
     1631            return vbcppError(pThis, "out of memory");
     1632        pExp->papszArgs = (char **)pv;
     1633        pExp->cArgsAlloced = cMinArgs;
     1634    }
     1635    return RTEXITCODE_SUCCESS;
     1636}
     1637
     1638
     1639static RTEXITCODE vbcppMacroExpandAddEmptyParameter(PVBCPP pThis, PVBCPPMACROEXP pExp)
     1640{
     1641    RTEXITCODE rcExit = vbcppMacroExpandGrowArgArray(pThis, pExp, pExp->cArgs + 1);
     1642    if (rcExit == RTEXITCODE_SUCCESS)
     1643    {
     1644        char *pszArg = (char *)RTMemAllocZ(1);
     1645        if (pszArg)
     1646            pExp->papszArgs[pExp->cArgs++] = pszArg;
     1647        else
     1648            rcExit = vbcppError(pThis, "out of memory");
     1649    }
     1650    return rcExit;
     1651}
     1652
     1653
     1654static RTEXITCODE vbcppMacroExpandGatherParameters(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t *poff, uint32_t cArgsHint)
     1655{
     1656    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     1657
     1658    /*
     1659     * Free previous argument values.
     1660     */
     1661    while (pExp->cArgs > 0)
     1662    {
     1663        RTMemFree(pExp->papszArgs[--pExp->cArgs]);
     1664        pExp->papszArgs[pExp->cArgs] = NULL;
     1665    }
     1666
     1667    /*
     1668     * The current character should be an opening parenthsis.
     1669     */
     1670    unsigned    ch = vbcppMacroExpandGetCh(pExp, poff);
     1671    if (ch != '(')
     1672        return vbcppError(pThis, "Internal error - expected '(', found '%c' (#x)", ch, ch);
     1673
     1674    /*
     1675     * Parse the argument list.
     1676     */
     1677    char        chQuote      = 0;
     1678    size_t      cbArgAlloc   = 0;
     1679    size_t      cchArg       = 0;
     1680    char       *pszArg       = NULL;
     1681    size_t      cParentheses = 1;
     1682    unsigned    chPrev       = 0;
     1683    while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0)
     1684    {
     1685        if (ch == ')' && !chQuote)
     1686        {
     1687            Assert(cParentheses >= 1);
     1688            cParentheses--;
     1689
     1690            /* The end? */
     1691            if (!cParentheses)
     1692            {
     1693                if (cchArg)
     1694                    while (cchArg > 0 && RT_C_IS_SPACE(pszArg[cchArg - 1]))
     1695                        pszArg[--cchArg] = '\0';
     1696                else if (pExp->cArgs || cArgsHint > 0)
     1697                    rcExit = vbcppMacroExpandAddEmptyParameter(pThis, pExp);
     1698                break;
     1699            }
     1700        }
     1701        else if (ch == '('  && !chQuote)
     1702            cParentheses++;
     1703        else if (ch == ',' && cParentheses == 1 && !chQuote)
     1704        {
     1705            /* End of one argument, start of the next. */
     1706            if (cchArg)
     1707                while (cchArg > 0 && RT_C_IS_SPACE(pszArg[cchArg - 1]))
     1708                    pszArg[--cchArg] = '\0';
     1709            else
     1710            {
     1711                rcExit = vbcppMacroExpandAddEmptyParameter(pThis, pExp);
     1712                if (rcExit != RTEXITCODE_SUCCESS)
     1713                    break;
     1714            }
     1715
     1716            cbArgAlloc = 0;
     1717            cchArg     = 0;
     1718            pszArg     = NULL;
     1719            continue;
     1720        }
     1721        else if (ch == '/' && !chQuote)
     1722        {
     1723            /* Comment? */
     1724            unsigned ch2 = vbcppMacroExpandPeekCh(pExp, poff);
     1725            /** @todo This ain't right wrt line splicing. */
     1726            if (ch2 == '/' || ch == '*')
     1727            {
     1728                if (ch2 == '/')
     1729                    rcExit = vbcppMacroExpandSkipCommentLine(pThis, pExp, poff);
     1730                else
     1731                    rcExit = vbcppMacroExpandSkipComment(pThis, pExp, poff);
     1732                if (rcExit != RTEXITCODE_SUCCESS)
     1733                    break;
     1734                continue;
     1735            }
     1736        }
     1737        else if (ch == '"')
     1738        {
     1739            if (!chQuote)
     1740                chQuote = '"';
     1741            else if (chPrev != '\\')
     1742                chQuote = 0;
     1743        }
     1744        else if (ch == '\'')
     1745        {
     1746            if (!chQuote)
     1747                chQuote = '\'';
     1748            else if (chPrev != '\\')
     1749                chQuote = 0;
     1750        }
     1751        else if (ch == '\\')
     1752        {
     1753            /* Splice lines? */
     1754            unsigned ch2 = vbcppMacroExpandPeekCh(pExp, poff);
     1755            if (ch2 == '\r' || ch2 == '\n')
     1756            {
     1757                rcExit = vbcppMacroExpandSkipEol(pThis, pExp, poff);
     1758                if (rcExit != RTEXITCODE_SUCCESS)
     1759                    break;
     1760                continue;
     1761            }
     1762        }
     1763        else if (cchArg == 0 && RT_C_IS_SPACE(ch))
     1764            continue; /* ignore spaces leading up to an argument value */
     1765
     1766        /* Append the character to the argument value, adding the argument
     1767           to the output array if it's first character in it. */
     1768        if (cchArg + 1 >= cbArgAlloc)
     1769        {
     1770            /* Add argument to the vector. */
     1771            if (!cchArg)
     1772            {
     1773                rcExit = vbcppMacroExpandGrowArgArray(pThis, pExp, RT_MAX(pExp->cArgs + 1, cArgsHint));
     1774                if (rcExit != RTEXITCODE_SUCCESS)
     1775                    break;
     1776                pExp->papszArgs[pExp->cArgs++] = pszArg;
     1777            }
     1778
     1779            /* Resize the argument value buffer. */
     1780            cbArgAlloc = cbArgAlloc ? cbArgAlloc * 2 : 16;
     1781            pszArg = (char *)RTMemRealloc(pszArg, cbArgAlloc);
     1782            if (!pszArg)
     1783            {
     1784                rcExit = vbcppError(pThis, "out of memory");
     1785                break;
     1786            }
     1787            pExp->papszArgs[pExp->cArgs - 1] = pszArg;
     1788        }
     1789
     1790        pszArg[cchArg++] = ch;
     1791        pszArg[cchArg]   = '\0';
     1792    }
     1793
     1794    /*
     1795     * Check that we're leaving on good terms.
     1796     */
     1797    if (rcExit == RTEXITCODE_SUCCESS)
     1798    {
     1799        if (cParentheses)
     1800            rcExit = vbcppError(pThis, "Missing ')'");
     1801    }
     1802
     1803    return rcExit;
     1804}
     1805
     1806
     1807/**
     1808 * Expands the arguments referenced in the macro value.
     1809 *
     1810 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg.
     1811 * @param   pThis               The C preprocessor instance.
     1812 * @param   pExp                The expansion context.
     1813 * @param   pMacro              The macro.  Must be a function macro.
     1814 * @param   pStrBuf             String buffer containing the result. The caller
     1815 *                              should initialize and destroy this!
     1816 */
     1817static RTEXITCODE vbcppMacroExpandValueWithArguments(PVBCPP pThis, PVBCPPMACROEXP pExp, PVBCPPDEF pMacro,
     1818                                                     PVBCPPSTRBUF pStrBuf)
     1819{
     1820    Assert(pMacro->fFunction);
     1821
     1822    /*
     1823     * Empty?
     1824     */
     1825    if (   !pMacro->cchValue
     1826        || (pMacro->cchValue == 1 && !pMacro->szValue[0] == '#'))
     1827        return RTEXITCODE_SUCCESS;
     1828
     1829    /*
     1830     * Parse the value.
     1831     */
     1832    RTEXITCODE  rcExit    = RTEXITCODE_SUCCESS;
     1833    const char *pszSrc    = pMacro->szValue;
     1834    const char *pszSrcSeq;
     1835    char        ch;
     1836    while ((ch = *pszSrc++) != '\0')
     1837    {
     1838        Assert(ch != '\r'); Assert(ch != '\n'); /* probably not true atm. */
     1839        if (ch == '#')
     1840        {
     1841            if (*pszSrc == '#')
     1842            {
     1843                /* Concatenate operator. */
     1844                rcExit = vbcppError(pThis, "The '##' operatore is not yet implemented");
     1845            }
     1846            else
     1847            {
     1848                /* Stringify macro argument. */
     1849                rcExit = vbcppError(pThis, "The '#' operatore is not yet implemented");
     1850            }
     1851            return rcExit;
     1852        }
     1853        else if (ch == '"')
     1854        {
     1855            /* String litteral. */
     1856            pszSrcSeq = pszSrc - 1;
     1857            while ((ch = *pszSrc++) != '"')
     1858            {
     1859                if (ch == '\\')
     1860                    ch = *pszSrc++;
     1861                if (ch == '\0')
     1862                {
     1863                    rcExit = vbcppError(pThis, "String litteral is missing closing quote (\").");
     1864                    break;
     1865                }
     1866            }
     1867            rcExit = vbcppStrBufAppendN(pStrBuf, pszSrcSeq, pszSrc - pszSrcSeq);
     1868        }
     1869        else if (ch == '\'')
     1870        {
     1871            /* Character constant. */
     1872            pszSrcSeq = pszSrc - 1;
     1873            while ((ch = *pszSrc++) != '\'')
     1874            {
     1875                if (ch == '\\')
     1876                    ch = *pszSrc++;
     1877                if (ch == '\0')
     1878                {
     1879                    rcExit = vbcppError(pThis, "Character constant is missing closing quote (').");
     1880                    break;
     1881                }
     1882            }
     1883            rcExit = vbcppStrBufAppendN(pStrBuf, pszSrcSeq, pszSrc - pszSrcSeq);
     1884        }
     1885        else if (RT_C_IS_DIGIT(ch))
     1886        {
     1887            /* Process numerical constants correctly (i.e. don't mess with the suffix). */
     1888            pszSrcSeq = pszSrc - 1;
     1889            while (   (ch = *pszSrc) != '\0'
     1890                   && (   vbcppIsCIdentifierChar(ch)
     1891                       || ch == '.') )
     1892                pszSrc++;
     1893            rcExit = vbcppStrBufAppendN(pStrBuf, pszSrcSeq, pszSrc - pszSrcSeq);
     1894        }
     1895        else if (RT_C_IS_SPACE(ch))
     1896        {
     1897            /* join spaces */
     1898            if (RT_C_IS_SPACE(vbcppStrBufLastCh(pStrBuf)))
     1899                continue;
     1900            rcExit = vbcppStrBufAppendCh(pStrBuf, ch);
     1901        }
     1902        else if (vbcppIsCIdentifierLeadChar(ch))
     1903        {
     1904            /* Something we should replace? */
     1905            pszSrcSeq = pszSrc - 1;
     1906            while (   (ch = *pszSrc) != '\0'
     1907                   && vbcppIsCIdentifierChar(ch))
     1908                pszSrc++;
     1909            size_t      cchDefine = pszSrc - pszSrcSeq;
     1910            uint32_t    iArg;
     1911            if (   VBCPP_BITMAP_IS_SET(pMacro->bmArgs, *pszSrcSeq)
     1912                && (iArg = vbcppMacroLookupArg(pMacro, pszSrcSeq, cchDefine)) != UINT32_MAX)
     1913            {
     1914                /** @todo check out spaces here! */
     1915                if (iArg < pMacro->cArgs)
     1916                {
     1917                    Assert(iArg < pExp->cArgs);
     1918                    rcExit = vbcppStrBufAppend(pStrBuf, pExp->papszArgs[iArg]);
     1919                    if (*pExp->papszArgs[iArg] != '\0' && rcExit == RTEXITCODE_SUCCESS)
     1920                        rcExit = vbcppStrBufAppendCh(pStrBuf, ' ');
     1921                }
     1922                else
     1923                {
     1924                    /* __VA_ARGS__ */
     1925                    if (iArg < pExp->cArgs)
     1926                    {
     1927                        for (;;)
     1928                        {
     1929                            rcExit = vbcppStrBufAppend(pStrBuf, pExp->papszArgs[iArg]);
     1930                            if (rcExit != RTEXITCODE_SUCCESS)
     1931                                break;
     1932                            iArg++;
     1933                            if (iArg >= pExp->cArgs)
     1934                                break;
     1935                            rcExit = vbcppStrBufAppendCh(pStrBuf, ',');
     1936                            if (rcExit != RTEXITCODE_SUCCESS)
     1937                                break;
     1938                        }
     1939                    }
     1940                    if (rcExit == RTEXITCODE_SUCCESS)
     1941                        rcExit = vbcppStrBufAppendCh(pStrBuf, ' ');
     1942                }
     1943            }
     1944            /* Not an argument needing replacing. */
     1945            else
     1946                rcExit = vbcppStrBufAppendN(pStrBuf, pszSrcSeq, cchDefine);
     1947        }
     1948        else
     1949        {
     1950            rcExit = vbcppStrBufAppendCh(pStrBuf, ch);
     1951        }
     1952    }
     1953
     1954    return rcExit;
     1955}
     1956
     1957
     1958
     1959/**
     1960 * Expands the given macro.
     1961 *
     1962 * Caller already checked if a function macro should be expanded, i.e. whether
     1963 * there is a parameter list.
     1964 *
     1965 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg.
     1966 * @param   pThis               The C preprocessor instance.
     1967 * @param   pExp                The expansion context.
     1968 * @param   offMacro            Offset into the expansion buffer of the macro
     1969 *                              invocation.
     1970 * @param   pMacro              The macro.
     1971 * @param   offParameters       The start of the parameter list if applicable.
     1972 *                              If the parameter list starts at the current
     1973 *                              stream position shall be at the end of the
     1974 *                              expansion buffer.
     1975 */
     1976static RTEXITCODE vbcppMacroExpandIt(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offMacro, PVBCPPDEF pMacro,
     1977                                     size_t offParameters)
     1978{
     1979    RTEXITCODE rcExit;
     1980    Assert(offMacro + pMacro->Core.cchString <= pExp->cchBuf);
     1981    Assert(!pMacro->fExpanding);
     1982
     1983    /*
     1984     * Function macros are kind of difficult...
     1985     */
     1986    if (pMacro->fFunction)
     1987    {
     1988        size_t offEnd = offParameters;
     1989        rcExit = vbcppMacroExpandGatherParameters(pThis, pExp, &offEnd, pMacro->cArgs + pMacro->fVarArg);
     1990        if (rcExit == RTEXITCODE_SUCCESS)
     1991        {
     1992            if (pExp->cArgs > pMacro->cArgs && !pMacro->fVarArg)
     1993                rcExit = vbcppError(pThis, "Too many arguments to macro '%s' - found %u, expected %u",
     1994                                    pMacro->Core.pszString, pExp->cArgs, pMacro->cArgs);
     1995            else if (pExp->cArgs < pMacro->cArgs)
     1996                rcExit = vbcppError(pThis, "Too few arguments to macro '%s' - found %u, expected %u",
     1997                                    pMacro->Core.pszString, pExp->cArgs, pMacro->cArgs);
     1998        }
     1999        if (rcExit == RTEXITCODE_SUCCESS)
     2000        {
     2001            VBCPPSTRBUF ValueBuf;
     2002            vbcppStrBufInit(&ValueBuf, pThis);
     2003            rcExit = vbcppMacroExpandValueWithArguments(pThis, pExp, pMacro, &ValueBuf);
     2004            if (rcExit == RTEXITCODE_SUCCESS)
     2005                rcExit = vbcppMacroExpandReplace(pThis, pExp, offMacro, offEnd - offMacro, ValueBuf.pszBuf, ValueBuf.cchBuf);
     2006            vbcppStrBufDelete(&ValueBuf);
     2007        }
     2008    }
     2009    /*
     2010     * Object-like macros are easy. :-)
     2011     */
     2012    else
     2013        rcExit = vbcppMacroExpandReplace(pThis, pExp, offMacro, pMacro->Core.cchString, pMacro->szValue, pMacro->cchValue);
     2014    if (rcExit == RTEXITCODE_SUCCESS)
     2015    {
     2016        /*
     2017         * Push the macro onto the stack.
     2018         */
     2019        pMacro->fExpanding   = true;
     2020        pMacro->pUpExpanding = pExp->pMacroStack;
     2021        pExp->pMacroStack    = pMacro;
     2022    }
     2023
     2024    return rcExit;
     2025}
     2026
     2027
     2028/**
     2029 * Re-scan the expanded macro.
     2030 *
     2031 * @returns
     2032 * @param   pThis               .
     2033 * @param   pExp                .
     2034 */
     2035static RTEXITCODE vbcppMacroExpandReScan(PVBCPP pThis, PVBCPPMACROEXP pExp)
     2036{
     2037    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     2038    Assert(pExp->pMacroStack);
     2039    Assert(!pExp->pMacroStack->pUpExpanding);
     2040
     2041    return rcExit;
     2042}
     2043
     2044
     2045/**
     2046 * Cleans up the expansion context.
     2047 *
     2048 * This involves clearing VBCPPMACRO::fExpanding and VBCPPMACRO::pUpExpanding,
     2049 * and freeing the memory resources associated with the expansion context.
     2050 *
     2051 * @param   pExp                The expansion context.
     2052 */
     2053static void vbcppMacroExpandCleanup(PVBCPPMACROEXP pExp)
     2054{
     2055    while (pExp->pMacroStack)
     2056    {
     2057        PVBCPPDEF pMacro = pExp->pMacroStack;
     2058        pExp->pMacroStack = pMacro->pUpExpanding;
     2059
     2060        pMacro->fExpanding   = false;
     2061        pMacro->pUpExpanding = NULL;
     2062    }
     2063
     2064    while (pExp->cArgs > 0)
     2065    {
     2066        RTMemFree(pExp->papszArgs[--pExp->cArgs]);
     2067        pExp->papszArgs[pExp->cArgs] = NULL;
     2068    }
     2069
     2070    RTMemFree(pExp->papszArgs);
     2071    pExp->papszArgs = NULL;
     2072
     2073    RTMemFree(pExp->pszBuf);
     2074    pExp->pszBuf = NULL;
    11122075}
    11132076
     
    13402303
    13412304        /* Found and argument. First character is already validated. */
     2305        VBCPP_BITMAP_SET(pMacro->bmArgs, pszParams[off]);
    13422306        pMacro->papszArgs[iArg] = pszDst;
    13432307        do
     
    14312395    return vbcppMacroInsert(pThis, pMacro);
    14322396}
     2397
     2398
     2399/**
     2400 * Tries to convert a define into an inline D constant.
     2401 *
     2402 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg.
     2403 * @param   pThis               The C preprocessor instance.
     2404 * @param   pMacro              The macro.
     2405 */
     2406static RTEXITCODE vbcppMacroTryConvertToInlineD(PVBCPP pThis, PVBCPPDEF pMacro)
     2407{
     2408    AssertReturn(pMacro, vbcppError(pThis, "Internal error"));
     2409    if (pMacro->fFunction)
     2410        return RTEXITCODE_SUCCESS;
     2411
     2412    /*
     2413     * Do some simple macro resolving. (Mostly to make x86.h work.)
     2414     */
     2415    const char *pszDefine = pMacro->Core.pszString;
     2416    const char *pszValue  = pMacro->szValue;
     2417    size_t      cchValue  = pMacro->cchValue;
     2418
     2419    unsigned   i = 0;
     2420    PVBCPPDEF  pMacro2;
     2421    while (   i < 10
     2422           && cchValue > 0
     2423           && vbcppIsCIdentifierLeadChar(*pszValue)
     2424           && (pMacro2 = vbcppMacroLookup(pThis, pszValue, cchValue)) != NULL
     2425           && !pMacro2->fFunction )
     2426    {
     2427        pszValue = pMacro2->szValue;
     2428        cchValue = pMacro2->cchValue;
     2429        i++;
     2430    }
     2431
     2432    if (!pMacro->cchValue)
     2433        return RTEXITCODE_SUCCESS;
     2434
     2435
     2436    /*
     2437     * A lone value?
     2438     */
     2439    ssize_t  cch = 0;
     2440    uint64_t u64;
     2441    char    *pszNext;
     2442    int rc = RTStrToUInt64Ex(pszValue, &pszNext, 0, &u64);
     2443    if (RT_SUCCESS(rc))
     2444    {
     2445        if (   rc == VWRN_TRAILING_SPACES
     2446            || rc == VWRN_NEGATIVE_UNSIGNED
     2447            || rc == VWRN_NUMBER_TOO_BIG)
     2448            return RTEXITCODE_SUCCESS;
     2449        const char *pszType;
     2450        if (rc == VWRN_TRAILING_CHARS)
     2451        {
     2452            if (!strcmp(pszNext, "u") || !strcmp(pszNext, "U"))
     2453                pszType = "uint32_t";
     2454            else if (!strcmp(pszNext, "ul") || !strcmp(pszNext, "UL"))
     2455                pszType = "uintptr_t";
     2456            else if (!strcmp(pszNext, "ull") || !strcmp(pszNext, "ULL"))
     2457                pszType = "uint64_t";
     2458            else
     2459                pszType = NULL;
     2460        }
     2461        else if (u64 <= UINT8_MAX)
     2462            pszType = "uint8_t";
     2463        else if (u64 <= UINT16_MAX)
     2464            pszType = "uint16_t";
     2465        else if (u64 <= UINT32_MAX)
     2466            pszType = "uint32_t";
     2467        else
     2468            pszType = "uint64_t";
     2469        if (!pszType)
     2470            return RTEXITCODE_SUCCESS;
     2471        cch = ScmStreamPrintf(&pThis->StrmOutput, "inline %s %s = %.*s;\n",
     2472                              pszType, pszDefine, pszNext - pszValue, pszValue);
     2473    }
     2474    /*
     2475     * A value wrapped in a constant macro?
     2476     */
     2477    else if (   (pszNext = strchr(pszValue, '(')) != NULL
     2478             && pszValue[cchValue - 1] == ')' )
     2479    {
     2480        size_t      cchPrefix = pszNext - pszValue;
     2481        size_t      cchInnerValue  = cchValue - cchPrefix - 2;
     2482        const char *pchInnerValue  = &pszValue[cchPrefix + 1];
     2483        while (cchInnerValue > 0 && RT_C_IS_SPACE(*pchInnerValue))
     2484            cchInnerValue--, pchInnerValue++;
     2485        while (cchInnerValue > 0 && RT_C_IS_SPACE(pchInnerValue[cchInnerValue - 1]))
     2486            cchInnerValue--;
     2487        if (!cchInnerValue || !RT_C_IS_XDIGIT(*pchInnerValue))
     2488            return RTEXITCODE_SUCCESS;
     2489
     2490        rc = RTStrToUInt64Ex(pchInnerValue, &pszNext, 0, &u64);
     2491        if (   RT_FAILURE(rc)
     2492            || rc == VWRN_TRAILING_SPACES
     2493            || rc == VWRN_NEGATIVE_UNSIGNED
     2494            || rc == VWRN_NUMBER_TOO_BIG)
     2495            return RTEXITCODE_SUCCESS;
     2496
     2497        const char *pszType;
     2498#define MY_MATCH_STR(a_sz)  (sizeof(a_sz) - 1 == cchPrefix && !strncmp(pszValue, a_sz, sizeof(a_sz) - 1))
     2499        if (MY_MATCH_STR("UINT8_C"))
     2500            pszType = "uint8_t";
     2501        else if (MY_MATCH_STR("UINT16_C"))
     2502            pszType = "uint16_t";
     2503        else if (MY_MATCH_STR("UINT32_C"))
     2504            pszType = "uint32_t";
     2505        else if (MY_MATCH_STR("UINT64_C"))
     2506            pszType = "uint64_t";
     2507        else
     2508            pszType = NULL;
     2509        if (pszType)
     2510            cch = ScmStreamPrintf(&pThis->StrmOutput, "inline %s %s = %.*s;\n",
     2511                                  pszType, pszDefine, cchInnerValue, pchInnerValue);
     2512        else if (MY_MATCH_STR("RT_BIT") || MY_MATCH_STR("RT_BIT_32"))
     2513            cch = ScmStreamPrintf(&pThis->StrmOutput, "inline uint32_t %s = 1U << %llu;\n",
     2514                                  pszDefine, u64);
     2515        else if (MY_MATCH_STR("RT_BIT_64"))
     2516            cch = ScmStreamPrintf(&pThis->StrmOutput, "inline uint64_t %s = 1ULL << %llu;\n",
     2517                                  pszDefine, u64);
     2518        else
     2519            return RTEXITCODE_SUCCESS;
     2520#undef MY_MATCH_STR
     2521    }
     2522    /* Dunno what this is... */
     2523    else
     2524        return RTEXITCODE_SUCCESS;
     2525
     2526    /*
     2527     * Check for output error and clear the output suppression indicator.
     2528     */
     2529    if (cch < 0)
     2530        return vbcppError(pThis, "Output error");
     2531
     2532    pThis->fJustDroppedLine = false;
     2533    return RTEXITCODE_SUCCESS;
     2534}
     2535
    14332536
    14342537
     
    15232626                {
    15242627                    unsigned cchIndent = pThis->pCondStack ? pThis->pCondStack->iKeepLevel : 0;
    1525                     size_t   cch;
     2628                    ssize_t  cch;
    15262629                    if (pchParams)
    15272630                        cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*sdefine %.*s(%.*s)",
     
    15352638                        rcExit = vbcppError(pThis, "output error");
    15362639                }
    1537             }
    1538 
     2640                else if (   rcExit == RTEXITCODE_SUCCESS
     2641                         && pThis->enmMode == kVBCppMode_SelectiveD)
     2642                    rcExit = vbcppMacroTryConvertToInlineD(pThis, vbcppMacroLookup(pThis, pchDefine, cchDefine));
     2643                else
     2644                    pThis->fJustDroppedLine = true;
     2645            }
    15392646        }
    15402647    }
     
    15542661static RTEXITCODE vbcppDirectiveUndef(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart)
    15552662{
    1556     return vbcppError(pThis, "Not implemented %s", __FUNCTION__);
     2663    /*
     2664     * Parse it.
     2665     */
     2666    RTEXITCODE rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput);
     2667    if (rcExit == RTEXITCODE_SUCCESS)
     2668    {
     2669        size_t      cchDefine;
     2670        const char *pchDefine = ScmStreamCGetWord(pStrmInput, &cchDefine);
     2671        if (pchDefine)
     2672        {
     2673            size_t offMaybeComment = vbcppProcessSkipWhite(pStrmInput);
     2674            rcExit = vbcppProcessSkipWhiteEscapedEolAndCommentsCheckEol(pThis, pStrmInput);
     2675            if (rcExit == RTEXITCODE_SUCCESS)
     2676            {
     2677                /*
     2678                 * Take action.
     2679                 */
     2680                PVBCPPDEF pMacro = vbcppMacroLookup(pThis, pchDefine, cchDefine);
     2681                if (    pMacro
     2682                    &&  pThis->fRespectSourceDefines
     2683                    &&  (   !pMacro->fCmdLine
     2684                         || pThis->fAllowRedefiningCmdLineDefines ) )
     2685                {
     2686                    RTStrSpaceRemove(&pThis->StrSpace, pMacro->Core.pszString);
     2687                    vbcppMacroFree(&pMacro->Core, NULL);
     2688                }
     2689
     2690                /*
     2691                 * Pass thru.
     2692                 */
     2693                if (   rcExit == RTEXITCODE_SUCCESS
     2694                    && pThis->fPassThruDefines)
     2695                {
     2696                    unsigned cchIndent = pThis->pCondStack ? pThis->pCondStack->iKeepLevel : 0;
     2697                    ssize_t  cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*sundef %.*s",
     2698                                                   cchIndent, "", cchDefine, pchDefine);
     2699                    if (cch > 0)
     2700                        vbcppOutputComment(pThis, pStrmInput, offMaybeComment, cch, 1);
     2701                    else
     2702                        rcExit = vbcppError(pThis, "output error");
     2703                }
     2704
     2705            }
     2706        }
     2707        else
     2708            rcExit = vbcppError(pThis, "Malformed #ifndef");
     2709    }
     2710    return rcExit;
     2711
    15572712}
    15582713
     
    23993554                /* Pretty print the passthru. */
    24003555                unsigned cchIndent = pThis->pCondStack ? pThis->pCondStack->iKeepLevel : 0;
    2401                 size_t   cch;
     3556                ssize_t  cch;
    24023557                if (chType == '<')
    24033558                    cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*sinclude <%.*s>",
     
    24673622                {
    24683623                    unsigned cchIndent = pThis->pCondStack ? pThis->pCondStack->iKeepLevel : 0;
    2469                     size_t   cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*spragma %.*s",
     3624                    ssize_t  cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*spragma %.*s",
    24703625                                                   cchIndent, "", cchPragma, pchPragma);
    24713626                    if (cch > 0)
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