VirtualBox

Changeset 41263 in vbox for trunk/src


Ignore:
Timestamp:
May 14, 2012 1:52:01 AM (13 years ago)
Author:
vboxsync
Message:

VBoxCPP: Hacked up real #if <expr> and #elfi <expr> support.

File:
1 edited

Legend:

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

    r41259 r41263  
    139139{
    140140    /** 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;
     141    VBCPPSTRBUF     StrBuf;
    146142    /** List of expanding macros (Stack). */
    147143    PVBCPPDEF       pMacroStack;
     
    160156
    161157/**
     158 * The vbcppMacroExpandReScan mode of operation.
     159 */
     160typedef enum VBCPPMACRORESCANMODE
     161{
     162    /** Invalid mode.  */
     163    kMacroReScanMode_Invalid = 0,
     164    /** Normal expansion mode. */
     165    kMacroReScanMode_Normal,
     166    /** Replaces known macros and heeds the 'defined' operator. */
     167    kMacroReScanMode_Expression,
     168    /** End of valid modes. */
     169    kMacroReScanMode_End
     170} VBCPPMACRORESCANMODE;
     171
     172
     173/**
    162174 * Evaluation result.
    163175 */
     
    207219    /** Whether we've seen the last else. */
    208220    bool                fSeenElse;
     221    /** Set if we have an else if which has already been decided. */
     222    bool                fElIfDecided;
    209223    /** The nesting level of this condition. */
    210224    uint16_t            iLevel;
     
    343357*******************************************************************************/
    344358static PVBCPPDEF    vbcppMacroLookup(PVBCPP pThis, const char *pszDefine, size_t cchDefine);
    345 static RTEXITCODE   vbcppMacroExpandIt(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offMacro, PVBCPPDEF pMacro, size_t offParameters);
    346 static RTEXITCODE   vbcppMacroExpandReScan(PVBCPP pThis, PVBCPPMACROEXP pExp);
     359static RTEXITCODE   vbcppMacroExpandIt(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offMacro, PVBCPPDEF pMacro, size_t *poffParameters);
     360static RTEXITCODE   vbcppMacroExpandReScan(PVBCPP pThis, PVBCPPMACROEXP pExp, VBCPPMACRORESCANMODE enmMode, size_t *pcReplacements);
    347361static void         vbcppMacroExpandCleanup(PVBCPPMACROEXP pExp);
    348362
     
    368382 * @param   pThis               The C preprocessor instance.
    369383 * @param   pszMsg              The message.
    370  * @param   ...                 Message arguments.
    371  */
    372 static RTEXITCODE vbcppError(PVBCPP pThis, const char *pszMsg, ...)
     384 * @param   va                  Message arguments.
     385 */
     386static RTEXITCODE vbcppErrorV(PVBCPP pThis, const char *pszMsg, va_list va)
    373387{
    374388    NOREF(pThis);
     
    382396        size_t const offLine = ScmStreamTell(pStrm);
    383397
    384         va_list va;
    385         va_start(va, pszMsg);
    386398        RTPrintf("%s:%d:%zd: error: %N.\n", pThis->pInputStack->szName, iLine + 1, off - offLine + 1, pszMsg, va);
    387         va_end(va);
    388399
    389400        size_t cchLine;
     
    398409    }
    399410    else
    400     {
    401         va_list va;
    402         va_start(va, pszMsg);
    403411        RTMsgErrorV(pszMsg, va);
    404         va_end(va);
    405     }
    406412    return pThis->rcExit = RTEXITCODE_FAILURE;
     413}
     414
     415
     416/**
     417 * Displays an error message.
     418 *
     419 * @returns RTEXITCODE_FAILURE
     420 * @param   pThis               The C preprocessor instance.
     421 * @param   pszMsg              The message.
     422 * @param   ...                 Message arguments.
     423 */
     424static RTEXITCODE vbcppError(PVBCPP pThis, const char *pszMsg, ...)
     425{
     426    va_list va;
     427    va_start(va, pszMsg);
     428    RTEXITCODE rcExit = vbcppErrorV(pThis, pszMsg, va);
     429    va_end(va);
     430    return rcExit;
    407431}
    408432
     
    13321356        ExpCtx.cArgs          = 0;
    13331357        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         }
    1363         else
    1364             rcExit = vbcppError(pThis, "out of memory");
     1358        vbcppStrBufInit(&ExpCtx.StrBuf, pThis);
     1359        rcExit = vbcppStrBufAppendN(&ExpCtx.StrBuf, pchDefine, cchDefine);
     1360        if (rcExit == RTEXITCODE_SUCCESS)
     1361        {
     1362            size_t offIgnore = cchDefine;
     1363            rcExit = vbcppMacroExpandIt(pThis, &ExpCtx, 0 /* offset */, pMacro, &offIgnore);
     1364        }
     1365        if (rcExit == RTEXITCODE_SUCCESS)
     1366            rcExit = vbcppMacroExpandReScan(pThis, &ExpCtx, kMacroReScanMode_Normal, NULL);
     1367        if (rcExit == RTEXITCODE_SUCCESS)
     1368        {
     1369            /*
     1370             * Insert it into the output stream.  Make sure there is a
     1371             * whitespace following it.
     1372             */
     1373            int rc = ScmStreamWrite(&pThis->StrmOutput, ExpCtx.StrBuf.pszBuf, ExpCtx.StrBuf.cchBuf);
     1374            if (RT_SUCCESS(rc))
     1375            {
     1376                unsigned chAfter = ScmStreamPeekCh(pStrmInput);
     1377                if (chAfter != ~(unsigned)0 && !RT_C_IS_SPACE(chAfter))
     1378                    rcExit = vbcppOutputCh(pThis, ' ');
     1379            }
     1380            else
     1381                rcExit = vbcppError(pThis, "Output error: %Rrc", rc);
     1382        }
     1383        vbcppMacroExpandCleanup(&ExpCtx);
    13651384    }
    13661385    else
     
    14641483     */
    14651484    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]);
     1485                                       && !RT_C_IS_SPACE(pExp->StrBuf.pszBuf[off - 1]);
     1486    bool const fTrailingSpace           = off + cchToReplace < pExp->StrBuf.cchBuf
     1487                                       && !RT_C_IS_SPACE(pExp->StrBuf.pszBuf[off + cchToReplace]);
    14691488    size_t const cchActualReplacement   = fLeadingSpace + cchReplacement + fTrailingSpace;
    14701489
     
    14771496
    14781497        /* 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         }
     1498        size_t cbMinBuf = offMore + pExp->StrBuf.cchBuf + 1;
     1499        RTEXITCODE rcExit = vbcppStrBufGrow(&pExp->StrBuf, cbMinBuf);
     1500        if (rcExit != RTEXITCODE_SUCCESS)
     1501            return rcExit;
    14931502
    14941503        /* 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;
     1504        memmove(&pExp->StrBuf.pszBuf[off + cchToReplace + offMore],
     1505                &pExp->StrBuf.pszBuf[off + cchToReplace],
     1506                pExp->StrBuf.cchBuf - off - cchToReplace + 1);
     1507        pExp->StrBuf.cchBuf += offMore;
    14991508
    15001509    }
     
    15041513
    15051514        /* 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;
     1515        memmove(&pExp->StrBuf.pszBuf[off + cchToReplace - offLess],
     1516                &pExp->StrBuf.pszBuf[off + cchToReplace],
     1517                pExp->StrBuf.cchBuf - off - cchToReplace + 1);
     1518        pExp->StrBuf.cchBuf -= offLess;
    15101519    }
    15111520
     
    15131522     * Insert the replacement string.
    15141523     */
    1515     char *pszCur = &pExp->pszBuf[off];
     1524    char *pszCur = &pExp->StrBuf.pszBuf[off];
    15161525    if (fLeadingSpace)
    15171526        *pszCur++ = ' ';
     
    15201529        *pszCur++ = ' ';
    15211530
    1522     Assert(strlen(pExp->pszBuf) == pExp->cchBuf);
    1523     Assert(pExp->cchBuf < pExp->cbBufAllocated);
     1531    Assert(strlen(pExp->StrBuf.pszBuf) == pExp->StrBuf.cchBuf);
    15241532
    15251533    return RTEXITCODE_SUCCESS;
     
    15301538{
    15311539    size_t off = *poff;
    1532     if (off >= pExp->cchBuf)
    1533         return ScmStreamPeekCh(pExp->pStrmInput);
    1534     return pExp->pszBuf[off];
     1540    if (off >= pExp->StrBuf.cchBuf)
     1541        return pExp->pStrmInput ? ScmStreamPeekCh(pExp->pStrmInput) : ~(unsigned)0;
     1542    return pExp->StrBuf.pszBuf[off];
    15351543}
    15361544
     
    15391547{
    15401548    size_t off = *poff;
    1541     if (off >= pExp->cchBuf)
    1542         return ScmStreamGetCh(pExp->pStrmInput);
     1549    if (off >= pExp->StrBuf.cchBuf)
     1550        return pExp->pStrmInput ? ScmStreamGetCh(pExp->pStrmInput) : ~(unsigned)0;
    15431551    *poff = off + 1;
    1544     return pExp->pszBuf[off];
     1552    return pExp->StrBuf.pszBuf[off];
    15451553}
    15461554
     
    16831691    while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0)
    16841692    {
     1693/** @todo check for '#directives'! */
    16851694        if (ch == ')' && !chQuote)
    16861695        {
     
    19691978 *                              invocation.
    19701979 * @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.
     1980 * @param   poffParameters      The start of the parameter list if applicable.
     1981 *                              Ignored if not function macro.
     1982 *
     1983 *                              If the parameter list starts at the current stream position shall
     1984 *                              be at the end of the expansion buffer.
     1985 *
     1986 *                              Will be advanced to the character following the
     1987 *                              closing parenthesis on success.  Undefined on
     1988 *                              failure.
    19751989 */
    19761990static RTEXITCODE vbcppMacroExpandIt(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offMacro, PVBCPPDEF pMacro,
    1977                                      size_t offParameters)
     1991                                     size_t *poffParameters)
    19781992{
    19791993    RTEXITCODE rcExit;
    1980     Assert(offMacro + pMacro->Core.cchString <= pExp->cchBuf);
     1994    Assert(offMacro + pMacro->Core.cchString <= pExp->StrBuf.cchBuf);
    19811995    Assert(!pMacro->fExpanding);
    19821996
     
    19862000    if (pMacro->fFunction)
    19872001    {
    1988         size_t offEnd = offParameters;
    1989         rcExit = vbcppMacroExpandGatherParameters(pThis, pExp, &offEnd, pMacro->cArgs + pMacro->fVarArg);
     2002        rcExit = vbcppMacroExpandGatherParameters(pThis, pExp, poffParameters, pMacro->cArgs + pMacro->fVarArg);
    19902003        if (rcExit == RTEXITCODE_SUCCESS)
    19912004        {
     
    20032016            rcExit = vbcppMacroExpandValueWithArguments(pThis, pExp, pMacro, &ValueBuf);
    20042017            if (rcExit == RTEXITCODE_SUCCESS)
    2005                 rcExit = vbcppMacroExpandReplace(pThis, pExp, offMacro, offEnd - offMacro, ValueBuf.pszBuf, ValueBuf.cchBuf);
     2018                rcExit = vbcppMacroExpandReplace(pThis, pExp, offMacro, *poffParameters - offMacro,
     2019                                                 ValueBuf.pszBuf, ValueBuf.cchBuf);
    20062020            vbcppStrBufDelete(&ValueBuf);
    20072021        }
     
    20272041
    20282042/**
     2043 * Looks for a left parenthesis in the macro expansion buffer and the input
     2044 * stream.
     2045 *
     2046 * @retval  true if found. The stream position at opening parenthesis.
     2047 * @retval  false if not found. The stream position is unchanged.
     2048 *
     2049 * @param   pThis               The C preprocessor instance.
     2050 * @param   pExp                The expansion context.
     2051 * @param   poff                The current offset in the expansion context.
     2052 *                              Will be updated on success.
     2053 *
     2054 * @sa vbcppInputLookForLeftParenthesis
     2055 */
     2056static bool vbcppMacroExpandLookForLeftParenthesis(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t *poff)
     2057{
     2058    /*
     2059     * Search the buffer first. (No comments there.)
     2060     */
     2061    size_t off = *poff;
     2062    while (off < pExp->StrBuf.cchBuf)
     2063    {
     2064        char ch = pExp->StrBuf.pszBuf[off];
     2065        if (!RT_C_IS_SPACE(ch))
     2066        {
     2067            if (ch == '(')
     2068            {
     2069                *poff = off;
     2070                return true;
     2071            }
     2072            return false;
     2073        }
     2074        off++;
     2075    }
     2076
     2077    /*
     2078     * Reached the end of the buffer, continue searching in the stream.
     2079     */
     2080    PSCMSTREAM pStrmInput = pExp->pStrmInput;
     2081    size_t     offSaved   = ScmStreamTell(pStrmInput);
     2082    RTEXITCODE rcExit     = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput);
     2083    unsigned ch = ScmStreamPeekCh(pStrmInput);
     2084    if (ch == '(')
     2085    {
     2086        *poff = pExp->StrBuf.cchBuf;
     2087        return true;
     2088    }
     2089
     2090    int rc = ScmStreamSeekAbsolute(pStrmInput, offSaved);
     2091    AssertFatalRC(rc);
     2092    return false;
     2093}
     2094
     2095
     2096/**
     2097 * Implements the 'defined' unary operator for \#if and \#elif expressions.
     2098 *
     2099 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg.
     2100 * @param   pThis               The C preprocessor instance.
     2101 * @param   pExp                The expansion context.
     2102 * @param   offStart            The expansion buffer offset where the 'defined'
     2103 *                              occurs.
     2104 * @param   poff                Where to store the offset at which the re-scan
     2105 *                              shall resume upon return.
     2106 */
     2107static RTEXITCODE vbcppMacroExpandDefinedOperator(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offStart, size_t *poff)
     2108{
     2109    Assert(!pExp->pStrmInput); /* offset usage below. */
     2110
     2111    /*
     2112     * Skip white space.
     2113     */
     2114    unsigned ch;
     2115    while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0)
     2116        if (!RT_C_IS_SPACE(ch))
     2117            break;
     2118    bool const fWithParenthesis = ch == '(';
     2119    if (fWithParenthesis)
     2120        while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0)
     2121            if (!RT_C_IS_SPACE(ch))
     2122                break;
     2123
     2124    /*
     2125     * Macro identifier.
     2126     */
     2127    if (!vbcppIsCIdentifierLeadChar(ch))
     2128        return vbcppError(pThis, "Expected macro name after 'defined' operator");
     2129
     2130    size_t const offDefine = *poff - 1;
     2131    while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0)
     2132        if (!vbcppIsCIdentifierChar(ch))
     2133            break;
     2134    size_t const cchDefine = *poff - offDefine;
     2135
     2136    /*
     2137     * Check for closing parenthesis.
     2138     */
     2139    if (fWithParenthesis)
     2140    {
     2141        while (RT_C_IS_SPACE(ch))
     2142            ch = vbcppMacroExpandGetCh(pExp, poff);
     2143        if (ch != ')')
     2144            return vbcppError(pThis, "Expected closing parenthesis after macro name");
     2145    }
     2146
     2147    /*
     2148     * Do the job.
     2149     */
     2150    const char *pszResult = vbcppMacroExists(pThis, &pExp->StrBuf.pszBuf[offDefine], cchDefine)
     2151                          ? "1" : "0";
     2152    RTEXITCODE  rcExit    = vbcppMacroExpandReplace(pThis, pExp, offStart, *poff - offStart, pszResult, 1);
     2153    *poff = offStart + 1;
     2154    return rcExit;
     2155}
     2156
     2157
     2158/**
    20292159 * Re-scan the expanded macro.
    20302160 *
    2031  * @returns
    2032  * @param   pThis               .
    2033  * @param   pExp                .
    2034  */
    2035 static RTEXITCODE vbcppMacroExpandReScan(PVBCPP pThis, PVBCPPMACROEXP pExp)
    2036 {
    2037     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    2038     Assert(pExp->pMacroStack);
    2039     Assert(!pExp->pMacroStack->pUpExpanding);
     2161 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE + msg.
     2162 * @param   pThis               The C preprocessor instance.
     2163 * @param   pExp                The expansion context.
     2164 * @param   enmMode             The re-scan mode.
     2165 * @param   pcReplacements      Where to return the number of replacements
     2166 *                              performed.  Optional.
     2167 */
     2168static RTEXITCODE vbcppMacroExpandReScan(PVBCPP pThis, PVBCPPMACROEXP pExp, VBCPPMACRORESCANMODE enmMode, size_t *pcReplacements)
     2169{
     2170    RTEXITCODE  rcExit        = RTEXITCODE_SUCCESS;
     2171    size_t      cReplacements = 0;
     2172    size_t      off           = 0;
     2173    unsigned    ch;
     2174    while (   off < pExp->StrBuf.cchBuf
     2175           && (ch = vbcppMacroExpandGetCh(pExp, &off)) != ~(unsigned)0)
     2176    {
     2177        /*
     2178         * String litteral or character constant.
     2179         */
     2180        if (ch == '\'' || ch == '"')
     2181        {
     2182            unsigned const chEndQuote = ch;
     2183            while (   off < pExp->StrBuf.cchBuf
     2184                   && (ch = vbcppMacroExpandGetCh(pExp, &off)) != ~(unsigned)0)
     2185            {
     2186                if (ch == '\\')
     2187                {
     2188                    ch = vbcppMacroExpandGetCh(pExp, &off);
     2189                    if (ch == ~(unsigned)0)
     2190                        break;
     2191                }
     2192                else if (ch == chEndQuote)
     2193                    break;
     2194            }
     2195            if (ch == ~(unsigned)0)
     2196                return vbcppError(pThis, "Missing end quote (%c)", chEndQuote);
     2197        }
     2198        /*
     2199         * Number constant.
     2200         */
     2201        else if (   RT_C_IS_DIGIT(ch)
     2202                 || (   ch == '.'
     2203                     && off + 1 < pExp->StrBuf.cchBuf
     2204                     && RT_C_IS_DIGIT(vbcppMacroExpandPeekCh(pExp, &off))
     2205                    )
     2206                )
     2207        {
     2208            while (   off < pExp->StrBuf.cchBuf
     2209                   && (ch = vbcppMacroExpandPeekCh(pExp, &off)) != ~(unsigned)0
     2210                   && vbcppIsCIdentifierChar(ch) )
     2211                vbcppMacroExpandGetCh(pExp, &off);
     2212        }
     2213        /*
     2214         * Something that can be replaced?
     2215         */
     2216        else if (vbcppIsCIdentifierLeadChar(ch))
     2217        {
     2218            size_t offDefine = off - 1;
     2219            while (   off < pExp->StrBuf.cchBuf
     2220                   && (ch = vbcppMacroExpandPeekCh(pExp, &off)) != ~(unsigned)0
     2221                   && vbcppIsCIdentifierChar(ch) )
     2222                vbcppMacroExpandGetCh(pExp, &off);
     2223            size_t cchDefine = off - offDefine;
     2224
     2225            PVBCPPDEF pMacro = vbcppMacroLookup(pThis, &pExp->StrBuf.pszBuf[offDefine], cchDefine);
     2226            if (   pMacro
     2227                && (   !pMacro->fFunction
     2228                    || vbcppMacroExpandLookForLeftParenthesis(pThis, pExp, &off)) )
     2229                rcExit = vbcppMacroExpandIt(pThis, pExp, offDefine, pMacro, &off);
     2230            else
     2231            {
     2232                if (   !pMacro
     2233                         && enmMode == kMacroReScanMode_Expression
     2234                         && cchDefine == sizeof("defined") - 1
     2235                         && !strncmp(&pExp->StrBuf.pszBuf[offDefine], "defined", cchDefine))
     2236                    rcExit = vbcppMacroExpandDefinedOperator(pThis, pExp, offDefine, &off);
     2237                else
     2238                    off = offDefine + cchDefine;
     2239            }
     2240        }
     2241        else
     2242        {
     2243            Assert(RT_C_IS_SPACE(ch) || RT_C_IS_PUNCT(ch));
     2244            Assert(ch != '\r' && ch != '\n');
     2245        }
     2246    }
    20402247
    20412248    return rcExit;
     
    20712278    pExp->papszArgs = NULL;
    20722279
    2073     RTMemFree(pExp->pszBuf);
    2074     pExp->pszBuf = NULL;
     2280    vbcppStrBufDelete(&pExp->StrBuf);
    20752281}
    20762282
     
    27762982    pCond->enmStackResult   = pUp ? vbcppCondCombine(enmResult, pUp->enmStackResult) : enmResult;
    27772983    pCond->fSeenElse        = false;
     2984    pCond->fElIfDecided     = enmResult == kVBCppEval_True;
    27782985    pCond->iLevel           = pThis->cCondStackDepth;
    27792986    pCond->iKeepLevel       = (pUp ? pUp->iKeepLevel : 0) + enmResult == kVBCppEval_Undecided;
     
    28133020
    28143021
    2815 #if 0
    28163022typedef enum VBCPPEXPRKIND
    28173023{
    28183024    kVBCppExprKind_Invalid = 0,
     3025    kVBCppExprKind_Unary,
    28193026    kVBCppExprKind_Binary,
    2820     kVBCppExprKind_Unary,
     3027    kVBCppExprKind_Ternary,
    28213028    kVBCppExprKind_SignedValue,
    28223029    kVBCppExprKind_UnsignedValue,
    2823     kVBCppExprKind_Define,
    28243030    kVBCppExprKind_End
    28253031} VBCPPEXPRKIND;
    28263032
     3033#define VBCPPOP_PRECEDENCE(a_iPrecedence)   ((a_iPrecedence) << 8)
     3034#define VBCPPOP_PRECEDENCE_MASK             0xff00
     3035#define VBCPPOP_L2R                         (1 << 16)
     3036#define VBCPPOP_R2L                         (2 << 16)
     3037
     3038typedef enum VBCPPUNARYOP
     3039{
     3040    kVBCppUnaryOp_Invalid = 0,
     3041    kVBCppUnaryOp_Pluss             = VBCPPOP_R2L | VBCPPOP_PRECEDENCE( 3) |  5,
     3042    kVBCppUnaryOp_Minus             = VBCPPOP_R2L | VBCPPOP_PRECEDENCE( 3) |  6,
     3043    kVBCppUnaryOp_LogicalNot        = VBCPPOP_R2L | VBCPPOP_PRECEDENCE( 3) |  7,
     3044    kVBCppUnaryOp_BitwiseNot        = VBCPPOP_R2L | VBCPPOP_PRECEDENCE( 3) |  8,
     3045    kVBCppUnaryOp_Parenthesis       = VBCPPOP_R2L | VBCPPOP_PRECEDENCE(15) |  9,
     3046    kVBCppUnaryOp_End
     3047} VBCPPUNARYOP;
     3048
     3049typedef enum VBCPPBINARYOP
     3050{
     3051    kVBCppBinary_Invalid = 0,
     3052//    kVBCppBinary_SizeOf             = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 3) |  1,
     3053    kVBCppBinary_Multiplication     = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 5) |  2,
     3054    kVBCppBinary_Division           = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 5) |  4,
     3055    kVBCppBinary_Modulo             = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 5) |  5,
     3056    kVBCppBinary_Addition           = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 6) |  6,
     3057    kVBCppBinary_Subtraction        = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 6) |  7,
     3058    kVBCppBinary_LeftShift          = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 7) |  8,
     3059    kVBCppBinary_RightShift         = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 7) |  9,
     3060    kVBCppBinary_LessThan           = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 8) | 10,
     3061    kVBCppBinary_LessThanOrEqual    = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 8) | 11,
     3062    kVBCppBinary_GreaterThan        = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 8) | 12,
     3063    kVBCppBinary_GreaterThanOrEqual = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 8) | 13,
     3064    kVBCppBinary_EqualTo            = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 9) | 14,
     3065    kVBCppBinary_NotEqualTo         = VBCPPOP_L2R | VBCPPOP_PRECEDENCE( 9) | 15,
     3066    kVBCppBinary_BitwiseAnd         = VBCPPOP_L2R | VBCPPOP_PRECEDENCE(10) | 16,
     3067    kVBCppBinary_BitwiseXor         = VBCPPOP_L2R | VBCPPOP_PRECEDENCE(11) | 17,
     3068    kVBCppBinary_BitwiseOr          = VBCPPOP_L2R | VBCPPOP_PRECEDENCE(12) | 18,
     3069    kVBCppBinary_LogicalAnd         = VBCPPOP_L2R | VBCPPOP_PRECEDENCE(13) | 19,
     3070    kVBCppBinary_LogicalOr          = VBCPPOP_L2R | VBCPPOP_PRECEDENCE(14) | 20,
     3071    kVBCppBinary_End
     3072} VBCPPBINARYOP;
     3073
     3074/** The precedence of the ternary operator (expr ? true : false). */
     3075#define VBCPPTERNAROP_PRECEDENCE   VBCPPOP_PRECEDENCE(16)
     3076
     3077
    28273078typedef struct VBCPPEXPR *PVBCPPEXPR;
    28283079
     
    28323083typedef struct VBCPPEXPR
    28333084{
    2834     /** Pointer to the first byte of the expression. */
    2835     const char         *pchExpr;
    2836     /** The length of the expression. */
    2837     size_t              cchExpr;
    2838 
    2839     uint32_t            iDepth;
     3085    /** Parent expression. */
     3086    PVBCPPEXPR          pParent;
     3087    /** Whether the expression is complete or not. */
     3088    bool                fComplete;
    28403089    /** The kind of expression. */
    28413090    VBCPPEXPRKIND       enmKind;
    2842     /** */
     3091    /** Content specific. */
    28433092    union
    28443093    {
     
    28583107        struct
    28593108        {
     3109            PVBCPPEXPR      pExpr;
     3110            PVBCPPEXPR      pTrue;
     3111            PVBCPPEXPR      pFalse;
     3112        } Ternary;
     3113
     3114        struct
     3115        {
    28603116            int64_t         s64;
    2861             unsigned        cBits;
    28623117        } SignedValue;
    28633118
     
    28653120        {
    28663121            uint64_t        u64;
    2867             unsigned        cBits;
    28683122        } UnsignedValue;
    28693123
    2870         struct
    2871         {
    2872             const char     *pch;
    2873             size_t          cch;
    2874         } Define;
    2875 
    28763124    } u;
    2877     /** Parent expression. */
    2878     PVBCPPEXPR          pParent;
    28793125} VBCPPEXPR;
    28803126
    28813127
    28823128
    2883 typedef struct VBCPPEXPRPARSER
    2884 {
    2885     PVBCPPEXPR          pStack
    2886 } VBCPPEXPRPARSER;
    2887 
    2888 
    28893129/**
    28903130 * Operator return statuses.
    28913131 */
    2892 typedef enum
     3132typedef enum VBCPPEXPRRET
    28933133{
    28943134    kExprRet_Error = -1,
    28953135    kExprRet_Ok = 0,
    2896     kExprRet_Operator,
    2897     kExprRet_Operand,
     3136    kExprRet_UnaryOperator,
     3137    kExprRet_Value,
    28983138    kExprRet_EndOfExpr,
    28993139    kExprRet_End
    29003140} VBCPPEXPRRET;
    29013141
    2902 
    2903 static VBCPPEXPRRET vbcppExprEatUnaryOrOperand(PVBCPPEXPRPARSER pThis, PSCMSTREAM pStrmInput)
    2904 {
    2905 
    2906 }
    2907 
     3142/**
     3143 * Expression parser context.
     3144 */
     3145typedef struct VBCPPEXPRPARSER
     3146{
     3147    /** The current expression posistion. */
     3148    const char         *pszCur;
     3149    /** The root node. */
     3150    PVBCPPEXPR          pRoot;
     3151    /** The current expression node. */
     3152    PVBCPPEXPR          pCur;
     3153    /** Where to insert the next expression. */
     3154    PVBCPPEXPR         *ppCur;
     3155    /** The expression. */
     3156    const char         *pszExpr;
     3157    /** The number of undefined macros we've encountered while parsing. */
     3158    size_t              cUndefined;
     3159    /** Pointer to the C preprocessor instance. */
     3160    PVBCPP              pThis;
     3161} VBCPPEXPRPARSER;
     3162/** Pointer to an expression parser context. */
     3163typedef VBCPPEXPRPARSER *PVBCPPEXPRPARSER;
     3164
     3165
     3166/**
     3167 * Recursively destroys the expression tree.
     3168 *
     3169 * @param   pExpr               The root of the expression tree to destroy.
     3170 */
     3171static void vbcppExprDestoryTree(PVBCPPEXPR pExpr)
     3172{
     3173    if (!pExpr)
     3174        return;
     3175
     3176    switch (pExpr->enmKind)
     3177    {
     3178        case kVBCppExprKind_Unary:
     3179            vbcppExprDestoryTree(pExpr->u.Unary.pArg);
     3180            break;
     3181        case kVBCppExprKind_Binary:
     3182            vbcppExprDestoryTree(pExpr->u.Binary.pLeft);
     3183            vbcppExprDestoryTree(pExpr->u.Binary.pRight);
     3184            break;
     3185        case kVBCppExprKind_Ternary:
     3186            vbcppExprDestoryTree(pExpr->u.Ternary.pExpr);
     3187            vbcppExprDestoryTree(pExpr->u.Ternary.pExpr);
     3188            vbcppExprDestoryTree(pExpr->u.Ternary.pFalse);
     3189            break;
     3190        case kVBCppExprKind_SignedValue:
     3191        case kVBCppExprKind_UnsignedValue:
     3192            break;
     3193        default:
     3194            AssertFailed();
     3195            return;
     3196    }
     3197    RTMemFree(pExpr);
     3198}
     3199
     3200
     3201static VBCPPEXPRRET vbcppExprParserError(PVBCPPEXPRPARSER pParser, const char *pszMsg, ...)
     3202{
     3203    va_list va;
     3204    va_start(va, pszMsg);
     3205    vbcppErrorV(pParser->pThis, pszMsg, va);
     3206    va_end(va);
     3207    return kExprRet_Error;
     3208}
     3209
     3210
     3211static void vbcppExprParseSkipWhiteSpace(PVBCPPEXPRPARSER pParser)
     3212{
     3213    while (RT_C_IS_SPACE(*pParser->pszCur))
     3214        pParser->pszCur++;
     3215}
     3216
     3217
     3218static PVBCPPEXPR vbcppExprParseAllocNode(PVBCPPEXPRPARSER pParser)
     3219{
     3220    PVBCPPEXPR pExpr = (PVBCPPEXPR)RTMemAllocZ(sizeof(*pExpr));
     3221    return pExpr;
     3222}
     3223
     3224
     3225static VBCPPEXPRRET vbcppExprParserBinaryOrEoeOrRparen(PVBCPPEXPRPARSER pParser)
     3226{
     3227    Assert(!pParser->ppCur);
     3228
     3229    /*
     3230     * Right parenthesis closes
     3231     */
     3232    char ch;
     3233    for (;;)
     3234    {
     3235        vbcppExprParseSkipWhiteSpace(pParser);
     3236        ch = *pParser->pszCur;
     3237        if (ch == '\0')
     3238            return kExprRet_EndOfExpr;
     3239        if (ch != ')')
     3240            break;
     3241        pParser->pszCur++;
     3242
     3243        PVBCPPEXPR pCur = pParser->pCur;
     3244        while (   pCur
     3245               && (   pCur->enmKind != kVBCppExprKind_Unary
     3246                   || pCur->u.Unary.enmOperator != kVBCppUnaryOp_Parenthesis))
     3247        {
     3248            switch (pCur->enmKind)
     3249            {
     3250                case kVBCppExprKind_SignedValue:
     3251                case kVBCppExprKind_UnsignedValue:
     3252                    Assert(pCur->fComplete);
     3253                    break;
     3254                case kVBCppExprKind_Unary:
     3255                    AssertReturn(pCur->u.Unary.pArg, vbcppExprParserError(pParser, "internal error"));
     3256                    pCur->fComplete = true;
     3257                    break;
     3258                case kVBCppExprKind_Binary:
     3259                    AssertReturn(pCur->u.Binary.pLeft, vbcppExprParserError(pParser, "internal error"));
     3260                    AssertReturn(pCur->u.Binary.pRight, vbcppExprParserError(pParser, "internal error"));
     3261                    pCur->fComplete = true;
     3262                    break;
     3263                case kVBCppExprKind_Ternary:
     3264#if 1 /** @todo Check out the ternary operator implementation. */
     3265                    return vbcppExprParserError(pParser, "The ternary operator is not implemented");
     3266#else
     3267                    Assert(pCur->u.Ternary.pExpr);
     3268                    if (!pCur->u.Ternary.pTrue)
     3269                        return vbcppExprParserError(pParser, "?!?!?");
     3270                    if (!pCur->u.Ternary.pFalse)
     3271                        return vbcppExprParserError(pParser, "?!?!?!?");
     3272                    pCur->fComplete = true;
    29083273#endif
     3274                    break;
     3275                default:
     3276                    return vbcppExprParserError(pParser, "Internal error (enmKind=%d)", pCur->enmKind);
     3277            }
     3278            pCur = pCur->pParent;
     3279        }
     3280        if (!pCur)
     3281            return vbcppExprParserError(pParser, "Right parenthesis without a left one");
     3282        pCur->fComplete = true;
     3283
     3284        while (   pCur->enmKind == kVBCppExprKind_Unary
     3285               && pCur->u.Unary.enmOperator != kVBCppUnaryOp_Parenthesis
     3286               && pCur->pParent)
     3287        {
     3288            AssertReturn(pCur->u.Unary.pArg, vbcppExprParserError(pParser, "internal error"));
     3289            pCur->fComplete = true;
     3290            pCur = pCur->pParent;
     3291        }
     3292    }
     3293
     3294    /*
     3295     * Binary or ternary operator should follow now.
     3296     */
     3297    VBCPPBINARYOP enmOp;
     3298    switch (ch)
     3299    {
     3300        case '*':
     3301            if (pParser->pszCur[1] == '=')
     3302                return vbcppExprParserError(pParser, "The assignment by product operator is not valid in a preprocessor expression");
     3303            enmOp = kVBCppBinary_Multiplication;
     3304            break;
     3305        case '/':
     3306            if (pParser->pszCur[1] == '=')
     3307                return vbcppExprParserError(pParser, "The assignment by quotient operator is not valid in a preprocessor expression");
     3308            enmOp = kVBCppBinary_Division;
     3309            break;
     3310        case '%':
     3311            if (pParser->pszCur[1] == '=')
     3312                return vbcppExprParserError(pParser, "The assignment by remainder operator is not valid in a preprocessor expression");
     3313            enmOp = kVBCppBinary_Modulo;
     3314            break;
     3315        case '+':
     3316            if (pParser->pszCur[1] == '=')
     3317                return vbcppExprParserError(pParser, "The assignment by sum operator is not valid in a preprocessor expression");
     3318            enmOp = kVBCppBinary_Addition;
     3319            break;
     3320        case '-':
     3321            if (pParser->pszCur[1] == '=')
     3322                return vbcppExprParserError(pParser, "The assignment by difference operator is not valid in a preprocessor expression");
     3323            enmOp = kVBCppBinary_Subtraction;
     3324            break;
     3325        case '<':
     3326            enmOp = kVBCppBinary_LessThan;
     3327            if (pParser->pszCur[1] == '=')
     3328            {
     3329                pParser->pszCur++;
     3330                enmOp = kVBCppBinary_LessThanOrEqual;
     3331            }
     3332            else if (pParser->pszCur[1] == '<')
     3333            {
     3334                pParser->pszCur++;
     3335                if (pParser->pszCur[1] == '=')
     3336                    return vbcppExprParserError(pParser, "The assignment by bitwise left shift operator is not valid in a preprocessor expression");
     3337                enmOp = kVBCppBinary_LeftShift;
     3338            }
     3339            break;
     3340        case '>':
     3341            enmOp = kVBCppBinary_GreaterThan; break;
     3342            if (pParser->pszCur[1] == '=')
     3343            {
     3344                pParser->pszCur++;
     3345                enmOp = kVBCppBinary_GreaterThanOrEqual;
     3346            }
     3347            else if (pParser->pszCur[1] == '<')
     3348            {
     3349                pParser->pszCur++;
     3350                if (pParser->pszCur[1] == '=')
     3351                    return vbcppExprParserError(pParser, "The assignment by bitwise right shift operator is not valid in a preprocessor expression");
     3352                enmOp = kVBCppBinary_LeftShift;
     3353            }
     3354            break;
     3355        case '=':
     3356            if (pParser->pszCur[1] != '=')
     3357                return vbcppExprParserError(pParser, "The assignment operator is not valid in a preprocessor expression");
     3358            pParser->pszCur++;
     3359            enmOp = kVBCppBinary_EqualTo;
     3360            break;
     3361
     3362        case '!':
     3363            if (pParser->pszCur[1] != '=')
     3364                return vbcppExprParserError(pParser, "Expected binary operator, found the unary operator logical NOT");
     3365            pParser->pszCur++;
     3366            enmOp = kVBCppBinary_NotEqualTo;
     3367            break;
     3368
     3369        case '&':
     3370            if (pParser->pszCur[1] == '=')
     3371                return vbcppExprParserError(pParser, "The assignment by bitwise AND operator is not valid in a preprocessor expression");
     3372            if (pParser->pszCur[1] == '&')
     3373            {
     3374                pParser->pszCur++;
     3375                enmOp = kVBCppBinary_LogicalAnd;
     3376            }
     3377            else
     3378                enmOp = kVBCppBinary_BitwiseAnd;
     3379            break;
     3380        case '^':
     3381            if (pParser->pszCur[1] == '=')
     3382                return vbcppExprParserError(pParser, "The assignment by bitwise XOR operator is not valid in a preprocessor expression");
     3383            enmOp = kVBCppBinary_BitwiseXor;
     3384            break;
     3385        case '|':
     3386            if (pParser->pszCur[1] == '=')
     3387                return vbcppExprParserError(pParser, "The assignment by bitwise AND operator is not valid in a preprocessor expression");
     3388            if (pParser->pszCur[1] == '|')
     3389            {
     3390                pParser->pszCur++;
     3391                enmOp = kVBCppBinary_LogicalOr;
     3392            }
     3393            else
     3394                enmOp = kVBCppBinary_BitwiseOr;
     3395            break;
     3396        case '~':
     3397            return vbcppExprParserError(pParser, "Expected binary operator, found the unary operator bitwise NOT");
     3398
     3399        case ':':
     3400        case '?':
     3401            return vbcppExprParserError(pParser, "The ternary operator is not yet implemented");
     3402
     3403        default:
     3404            return vbcppExprParserError(pParser, "Expected binary operator, found '%.20s'", pParser->pszCur);
     3405    }
     3406    pParser->pszCur++;
     3407
     3408    /*
     3409     * Create a binary operator node.
     3410     */
     3411    PVBCPPEXPR pExpr = vbcppExprParseAllocNode(pParser);
     3412    if (!pExpr)
     3413        return kExprRet_Error;
     3414    pExpr->fComplete            = true;
     3415    pExpr->enmKind              = kVBCppExprKind_Binary;
     3416    pExpr->u.Binary.enmOperator = enmOp;
     3417    pExpr->u.Binary.pLeft       = NULL;
     3418    pExpr->u.Binary.pRight      = NULL;
     3419
     3420    /*
     3421     * Back up the tree until we find our spot.
     3422     */
     3423    PVBCPPEXPR *ppPlace = NULL;
     3424    PVBCPPEXPR  pChild  = NULL;
     3425    PVBCPPEXPR  pParent = pParser->pCur;
     3426    while (pParent)
     3427    {
     3428        if (pParent->enmKind == kVBCppExprKind_Unary)
     3429        {
     3430            if (pParent->u.Unary.enmOperator == kVBCppUnaryOp_Parenthesis)
     3431            {
     3432                ppPlace = &pParent->u.Unary.pArg;
     3433                break;
     3434            }
     3435            AssertReturn(pParent->u.Unary.pArg, vbcppExprParserError(pParser, "internal error"));
     3436            pParent->fComplete = true;
     3437        }
     3438        else if (pParent->enmKind == kVBCppExprKind_Binary)
     3439        {
     3440            AssertReturn(pParent->u.Binary.pLeft, vbcppExprParserError(pParser, "internal error"));
     3441            AssertReturn(pParent->u.Binary.pRight, vbcppExprParserError(pParser, "internal error"));
     3442            if ((pParent->u.Binary.enmOperator & VBCPPOP_PRECEDENCE_MASK) >= (enmOp & VBCPPOP_PRECEDENCE_MASK))
     3443            {
     3444                AssertReturn(pChild, vbcppExprParserError(pParser, "internal error"));
     3445
     3446                if (pParent->u.Binary.pRight == pChild)
     3447                    ppPlace = &pParent->u.Binary.pRight;
     3448                else
     3449                    ppPlace = &pParent->u.Binary.pLeft;
     3450                AssertReturn(*ppPlace == pChild, vbcppExprParserError(pParser, "internal error"));
     3451                break;
     3452            }
     3453            pParent->fComplete = true;
     3454        }
     3455        else if (pParent->enmKind == kVBCppExprKind_Ternary)
     3456        {
     3457            return vbcppExprParserError(pParser, "The ternary operator is not implemented");
     3458        }
     3459        else
     3460            AssertReturn(   pParent->enmKind == kVBCppExprKind_SignedValue
     3461                         || pParent->enmKind == kVBCppExprKind_UnsignedValue,
     3462                         vbcppExprParserError(pParser, "internal error"));
     3463
     3464        /* Up on level */
     3465        pChild  = pParent;
     3466        pParent = pParent->pParent;
     3467    }
     3468
     3469    /*
     3470     * Do the rotation.
     3471     */
     3472    Assert(pChild);
     3473    Assert(pChild->pParent == pParent);
     3474    pChild->pParent       = pExpr;
     3475
     3476    pExpr->u.Binary.pLeft = pChild;
     3477    pExpr->pParent        = pParent;
     3478
     3479    if (!pParent)
     3480        pParser->pRoot    = pExpr;
     3481    else
     3482        *ppPlace          = pExpr;
     3483
     3484    pParser->ppCur = &pExpr->u.Binary.pRight;
     3485    pParser->pCur  = pExpr;
     3486
     3487    return kExprRet_Ok;
     3488}
     3489
     3490
     3491static VBCPPEXPRRET vbcppExprParseIdentifier(PVBCPPEXPRPARSER pParser)
     3492{
     3493    pParser->cUndefined++;
     3494
     3495    /* Find the end. */
     3496    const char *pszMacro = pParser->pszCur;
     3497    const char *pszNext  = pszMacro + 1;
     3498    while (vbcppIsCIdentifierChar(*pszNext))
     3499        pszNext++;
     3500    size_t cchMacro = pszNext - pszMacro;
     3501
     3502    /* Create a signed value node. */
     3503    PVBCPPEXPR pExpr = vbcppExprParseAllocNode(pParser);
     3504    if (!pExpr)
     3505        return kExprRet_Error;
     3506    pExpr->fComplete            = true;
     3507    pExpr->enmKind              = kVBCppExprKind_UnsignedValue;
     3508    pExpr->u.UnsignedValue.u64  = 0;
     3509
     3510    /* Link it. */
     3511    pExpr->pParent              = pParser->pCur;
     3512    pParser->pCur               = pExpr;
     3513    *pParser->ppCur             = pExpr;
     3514    pParser->ppCur              = NULL;
     3515
     3516    /* Skip spaces and check for parenthesis. */
     3517    pParser->pszCur = pszNext;
     3518    vbcppExprParseSkipWhiteSpace(pParser);
     3519    if (*pParser->pszCur == '(')
     3520        return vbcppExprParserError(pParser, "Unknown unary operator '%.*s'", cchMacro, pszMacro);
     3521
     3522
     3523    return kExprRet_Value;
     3524
     3525}
     3526
     3527
     3528static VBCPPEXPRRET vbcppExprParseNumber(PVBCPPEXPRPARSER pParser)
     3529{
     3530    bool        fSigned;
     3531    char       *pszNext;
     3532    uint64_t    u64;
     3533    char        ch    = *pParser->pszCur++;
     3534    char        ch2   = *pParser->pszCur;
     3535    if (   ch == '0'
     3536        && (ch == 'x' || ch == 'X'))
     3537    {
     3538        ch2 = *++pParser->pszCur;
     3539        if (!RT_C_IS_XDIGIT(ch2))
     3540            return vbcppExprParserError(pParser, "Expected hex digit following '0x'");
     3541        int rc = RTStrToUInt64Ex(pParser->pszCur, &pszNext, 16, &u64);
     3542        if (   RT_FAILURE(rc)
     3543            || rc == VWRN_NUMBER_TOO_BIG)
     3544            return vbcppExprParserError(pParser, "Invalid hex value '%.20s...' (%Rrc)", pParser->pszCur, rc);
     3545        fSigned = false;
     3546    }
     3547    else if (ch == '0')
     3548    {
     3549        int rc = RTStrToUInt64Ex(pParser->pszCur - 1, &pszNext, 8, &u64);
     3550        if (   RT_FAILURE(rc)
     3551            || rc == VWRN_NUMBER_TOO_BIG)
     3552            return vbcppExprParserError(pParser, "Invalid octal value '%.20s...' (%Rrc)", pParser->pszCur, rc);
     3553        fSigned = u64 > (uint64_t)INT64_MAX ? false : true;
     3554    }
     3555    else
     3556    {
     3557        int rc = RTStrToUInt64Ex(pParser->pszCur - 1, &pszNext, 10, &u64);
     3558        if (   RT_FAILURE(rc)
     3559            || rc == VWRN_NUMBER_TOO_BIG)
     3560            return vbcppExprParserError(pParser, "Invalid decimal value '%.20s...' (%Rrc)", pParser->pszCur, rc);
     3561        fSigned = u64 > (uint64_t)INT64_MAX ? false : true;
     3562    }
     3563
     3564    /* suffix. */
     3565    if (vbcppIsCIdentifierLeadChar(*pszNext))
     3566    {
     3567        size_t cchSuffix = 1;
     3568        while (vbcppIsCIdentifierLeadChar(pszNext[cchSuffix]))
     3569            cchSuffix++;
     3570
     3571        if (cchSuffix == '1' && (*pszNext == 'u' || *pszNext == 'U'))
     3572            fSigned = false;
     3573        else if (   cchSuffix == '1'
     3574                 && (*pszNext == 'l' || *pszNext == 'L'))
     3575            fSigned = true;
     3576        else if (   cchSuffix == '2'
     3577                 && (!strncmp(pszNext, "ul", 2) || !strncmp(pszNext, "UL", 2)))
     3578            fSigned = false;
     3579        else if (   cchSuffix == '2'
     3580                 && (!strncmp(pszNext, "ll", 2) || !strncmp(pszNext, "LL", 2)))
     3581            fSigned = true;
     3582        else if (   cchSuffix == '3'
     3583                 && (!strncmp(pszNext, "ull", 3) || !strncmp(pszNext, "ULL", 3)))
     3584            fSigned = false;
     3585        else
     3586            return vbcppExprParserError(pParser, "Invalid number suffix '%.*s'", cchSuffix, pszNext);
     3587
     3588        pszNext += cchSuffix;
     3589    }
     3590    pParser->pszCur = pszNext;
     3591
     3592    /* Create a signed value node. */
     3593    PVBCPPEXPR pExpr = vbcppExprParseAllocNode(pParser);
     3594    if (!pExpr)
     3595        return kExprRet_Error;
     3596    pExpr->fComplete            = true;
     3597    if (fSigned)
     3598    {
     3599        pExpr->enmKind              = kVBCppExprKind_SignedValue;
     3600        pExpr->u.SignedValue.s64    = (int64_t)u64;
     3601    }
     3602    else
     3603    {
     3604        pExpr->enmKind              = kVBCppExprKind_UnsignedValue;
     3605        pExpr->u.UnsignedValue.u64  = u64;
     3606    }
     3607
     3608    /* Link it. */
     3609    pExpr->pParent              = pParser->pCur;
     3610    pParser->pCur               = pExpr;
     3611    *pParser->ppCur             = pExpr;
     3612    pParser->ppCur              = NULL;
     3613
     3614    return kExprRet_Value;
     3615}
     3616
     3617
     3618static VBCPPEXPRRET vbcppExprParseCharacterConstant(PVBCPPEXPRPARSER pParser)
     3619{
     3620    char ch  = *pParser->pszCur++;
     3621    char ch2 = *pParser->pszCur++;
     3622    if (ch2 == '\'')
     3623        return vbcppExprParserError(pParser, "Empty character constant");
     3624    int64_t s64;
     3625    if (ch2 == '\\')
     3626    {
     3627        ch2 = *pParser->pszCur++;
     3628        switch (ch2)
     3629        {
     3630            case '0': s64 = 0x00; break;
     3631            case 'n': s64 = 0x0d; break;
     3632            case 'r': s64 = 0x0a; break;
     3633            case 't': s64 = 0x09; break;
     3634            default:
     3635                return vbcppExprParserError(pParser, "Escape character '%c' is not implemented", ch2);
     3636        }
     3637    }
     3638    else
     3639        s64 = ch2;
     3640    if (*pParser->pszCur != '\'')
     3641        return vbcppExprParserError(pParser, "Character constant contains more than one character");
     3642
     3643    /* Create a signed value node. */
     3644    PVBCPPEXPR pExpr = vbcppExprParseAllocNode(pParser);
     3645    if (!pExpr)
     3646        return kExprRet_Error;
     3647    pExpr->fComplete            = true;
     3648    pExpr->enmKind              = kVBCppExprKind_SignedValue;
     3649    pExpr->u.SignedValue.s64    = s64;
     3650
     3651    /* Link it. */
     3652    pExpr->pParent              = pParser->pCur;
     3653    pParser->pCur               = pExpr;
     3654    *pParser->ppCur             = pExpr;
     3655    pParser->ppCur              = NULL;
     3656
     3657    return kExprRet_Value;
     3658}
     3659
     3660
     3661static VBCPPEXPRRET vbcppExprParseUnaryOrValueOrEoe(PVBCPPEXPRPARSER pParser)
     3662{
     3663    vbcppExprParseSkipWhiteSpace(pParser);
     3664    char ch = *pParser->pszCur;
     3665    if (ch == '\0')
     3666        return vbcppExprParserError(pParser, "Premature end of expression");
     3667
     3668    /*
     3669     * Value?
     3670     */
     3671    if (ch == '\'')
     3672        return vbcppExprParseCharacterConstant(pParser);
     3673    if (RT_C_IS_DIGIT(ch))
     3674        return vbcppExprParseNumber(pParser);
     3675    if (ch == '"')
     3676        return vbcppExprParserError(pParser, "String litteral");
     3677    if (vbcppIsCIdentifierLeadChar(ch))
     3678        return vbcppExprParseIdentifier(pParser);
     3679
     3680    /*
     3681     * Operator?
     3682     */
     3683    VBCPPUNARYOP enmOperator;
     3684    if (ch == '+')
     3685    {
     3686        enmOperator = kVBCppUnaryOp_Pluss;
     3687        if (pParser->pszCur[1] == '+')
     3688            return vbcppExprParserError(pParser, "The prefix increment operator is not valid in a preprocessor expression");
     3689    }
     3690    else if (ch == '-')
     3691    {
     3692        enmOperator = kVBCppUnaryOp_Minus;
     3693        if (pParser->pszCur[1] == '-')
     3694            return vbcppExprParserError(pParser, "The prefix decrement operator is not valid in a preprocessor expression");
     3695    }
     3696    else if (ch == '!')
     3697        enmOperator = kVBCppUnaryOp_LogicalNot;
     3698    else if (ch == '~')
     3699        enmOperator = kVBCppUnaryOp_BitwiseNot;
     3700    else if (ch == '(')
     3701        enmOperator = kVBCppUnaryOp_Parenthesis;
     3702    else
     3703        return vbcppExprParserError(pParser, "Unknown token '%.*s'", 32, pParser->pszCur - 1);
     3704    pParser->pszCur++;
     3705
     3706    /* Create an operator node. */
     3707    PVBCPPEXPR pExpr = vbcppExprParseAllocNode(pParser);
     3708    if (!pExpr)
     3709        return kExprRet_Error;
     3710    pExpr->fComplete            = false;
     3711    pExpr->enmKind              = kVBCppExprKind_Unary;
     3712    pExpr->u.Unary.enmOperator  = enmOperator;
     3713    pExpr->u.Unary.pArg         = NULL;
     3714
     3715    /* Link it into the tree. */
     3716    pExpr->pParent              = pParser->pCur;
     3717    pParser->pCur               = pExpr;
     3718    *pParser->ppCur             = pExpr;
     3719    pParser->ppCur              = &pExpr->u.Unary.pArg;
     3720
     3721    return kExprRet_UnaryOperator;
     3722}
     3723
     3724
     3725
     3726static RTEXITCODE vbcppExprParse(PVBCPP pThis, char *pszExpr, size_t cchExpr, PVBCPPEXPR *ppExprTree, size_t *pcUndefined)
     3727{
     3728    RTEXITCODE rcExit = RTEXITCODE_FAILURE;
     3729
     3730    /*
     3731     * Initialize the parser context structure.
     3732     */
     3733    VBCPPEXPRPARSER Parser;
     3734    Parser.pszCur       = pszExpr;
     3735    Parser.pRoot        = NULL;
     3736    Parser.pCur         = NULL;
     3737    Parser.ppCur        = &Parser.pRoot;
     3738    Parser.pszExpr      = pszExpr;
     3739    Parser.cUndefined   = 0;
     3740    Parser.pThis        = pThis;
     3741
     3742    /*
     3743     * Do the parsing.
     3744     */
     3745    VBCPPEXPRRET enmRet;
     3746    for (;;)
     3747    {
     3748        /*
     3749         * Eat unary operators until we hit a value.
     3750         */
     3751        do
     3752            enmRet = vbcppExprParseUnaryOrValueOrEoe(&Parser);
     3753        while (enmRet == kExprRet_UnaryOperator);
     3754        if (enmRet == kExprRet_Error)
     3755            break;
     3756        AssertBreakStmt(enmRet == kExprRet_Value, enmRet = vbcppExprParserError(&Parser, "Expected value (enmRet=%d)", enmRet));
     3757
     3758        /*
     3759         * Non-unary operator, right parenthesis or end of expression is up next.
     3760         */
     3761        enmRet = vbcppExprParserBinaryOrEoeOrRparen(&Parser);
     3762        if (enmRet == kExprRet_Error)
     3763            break;
     3764        if (enmRet == kExprRet_EndOfExpr)
     3765        {
     3766            /** @todo check if there are any open parentheses. */
     3767            rcExit = RTEXITCODE_SUCCESS;
     3768            break;
     3769        }
     3770        AssertBreakStmt(enmRet == kExprRet_Ok, enmRet = vbcppExprParserError(&Parser, "Expected value (enmRet=%d)", enmRet));
     3771    }
     3772
     3773    if (rcExit != RTEXITCODE_SUCCESS)
     3774    {
     3775        vbcppExprDestoryTree(Parser.pRoot);
     3776        return rcExit;
     3777    }
     3778
     3779    if (pcUndefined)
     3780        *pcUndefined = Parser.cUndefined;
     3781    *ppExprTree = Parser.pRoot;
     3782    return rcExit;
     3783}
     3784
     3785
     3786static bool vbcppExprIsExprTrue(PVBCPPEXPR pExpr)
     3787{
     3788    Assert(pExpr->enmKind == kVBCppExprKind_SignedValue || pExpr->enmKind == kVBCppExprKind_UnsignedValue);
     3789    return pExpr->enmKind == kVBCppExprKind_SignedValue
     3790         ? pExpr->u.SignedValue.s64   != 0
     3791         : pExpr->u.UnsignedValue.u64 != 0;
     3792}
     3793
     3794
     3795static RTEXITCODE vbcppExprEvaluteTree(PVBCPP pThis, PVBCPPEXPR pRoot, PVBCPPEXPR pResult)
     3796{
     3797    RTEXITCODE rcExit;
     3798    switch (pRoot->enmKind)
     3799    {
     3800        case kVBCppExprKind_SignedValue:
     3801            pResult->enmKind                = kVBCppExprKind_SignedValue;
     3802            pResult->u.SignedValue.s64      = pRoot->u.SignedValue.s64;
     3803            return RTEXITCODE_SUCCESS;
     3804
     3805        case kVBCppExprKind_UnsignedValue:
     3806            pResult->enmKind                = kVBCppExprKind_UnsignedValue;
     3807            pResult->u.UnsignedValue.u64    = pRoot->u.UnsignedValue.u64;
     3808            return RTEXITCODE_SUCCESS;
     3809
     3810        case kVBCppExprKind_Unary:
     3811            rcExit = vbcppExprEvaluteTree(pThis, pRoot->u.Unary.pArg, pResult);
     3812            if (rcExit != RTEXITCODE_SUCCESS)
     3813                return rcExit;
     3814
     3815            /* Apply the unary operator to the value */
     3816            switch (pRoot->u.Unary.enmOperator)
     3817            {
     3818                case kVBCppUnaryOp_Minus:
     3819                    if (pResult->enmKind == kVBCppExprKind_SignedValue)
     3820                        pResult->u.SignedValue.s64   = -pResult->u.SignedValue.s64;
     3821                    else
     3822                        pResult->u.UnsignedValue.u64 = (uint64_t)-(int64_t)pResult->u.UnsignedValue.u64;
     3823                    break;
     3824
     3825                case kVBCppUnaryOp_LogicalNot:
     3826                    if (pResult->enmKind == kVBCppExprKind_SignedValue)
     3827                        pResult->u.SignedValue.s64   = !pResult->u.SignedValue.s64;
     3828                    else
     3829                        pResult->u.UnsignedValue.u64 = !pResult->u.UnsignedValue.u64;
     3830                    break;
     3831
     3832                case kVBCppUnaryOp_BitwiseNot:
     3833                    if (pResult->enmKind == kVBCppExprKind_SignedValue)
     3834                        pResult->u.SignedValue.s64   = ~pResult->u.SignedValue.s64;
     3835                    else
     3836                        pResult->u.UnsignedValue.u64 = ~pResult->u.UnsignedValue.u64;
     3837                    break;
     3838
     3839                case kVBCppUnaryOp_Pluss:
     3840                case kVBCppUnaryOp_Parenthesis:
     3841                    /* do nothing. */
     3842                    break;
     3843
     3844                default:
     3845                    return vbcppError(pThis, "Internal error: u.Unary.enmOperator=%d", pRoot->u.Unary.enmOperator);
     3846            }
     3847            return RTEXITCODE_SUCCESS;
     3848
     3849        case kVBCppExprKind_Binary:
     3850        {
     3851            /* Always evalute the left side. */
     3852            rcExit = vbcppExprEvaluteTree(pThis, pRoot->u.Binary.pLeft, pResult);
     3853            if (rcExit != RTEXITCODE_SUCCESS)
     3854                return rcExit;
     3855
     3856            /* If logical AND or OR we can sometimes skip evaluting the right side. */
     3857            if (   pRoot->u.Binary.enmOperator == kVBCppBinary_LogicalAnd
     3858                && !vbcppExprIsExprTrue(pResult))
     3859                return RTEXITCODE_SUCCESS;
     3860
     3861            if (   pRoot->u.Binary.enmOperator == kVBCppBinary_LogicalOr
     3862                && vbcppExprIsExprTrue(pResult))
     3863                return RTEXITCODE_SUCCESS;
     3864
     3865            /* Evalute the right side. */
     3866            VBCPPEXPR Result2;
     3867            rcExit = vbcppExprEvaluteTree(pThis, pRoot->u.Binary.pLeft, &Result2);
     3868            if (rcExit != RTEXITCODE_SUCCESS)
     3869                return rcExit;
     3870
     3871            /* If one of them is unsigned, promote the other to unsigned as well. */
     3872            if (   pResult->enmKind == kVBCppExprKind_UnsignedValue
     3873                && Result2.enmKind  == kVBCppExprKind_SignedValue)
     3874            {
     3875                Result2.enmKind              = kVBCppExprKind_UnsignedValue;
     3876                Result2.u.UnsignedValue.u64  = Result2.u.SignedValue.s64;
     3877            }
     3878            else if (   pResult->enmKind == kVBCppExprKind_SignedValue
     3879                     && Result2.enmKind  == kVBCppExprKind_UnsignedValue)
     3880            {
     3881                pResult->enmKind             = kVBCppExprKind_UnsignedValue;
     3882                pResult->u.UnsignedValue.u64 = pResult->u.SignedValue.s64;
     3883            }
     3884
     3885            /* Perform the operation. */
     3886            if (pResult->enmKind == kVBCppExprKind_UnsignedValue)
     3887            {
     3888                switch (pRoot->u.Binary.enmOperator)
     3889                {
     3890                    case kVBCppBinary_Multiplication:
     3891                        pResult->u.UnsignedValue.u64 *= Result2.u.UnsignedValue.u64;
     3892                        break;
     3893                    case kVBCppBinary_Division:
     3894                        if (!Result2.u.UnsignedValue.u64)
     3895                            return vbcppError(pThis, "Divide by zero");
     3896                        pResult->u.UnsignedValue.u64 /= Result2.u.UnsignedValue.u64;
     3897                        break;
     3898                    case kVBCppBinary_Modulo:
     3899                        if (!Result2.u.UnsignedValue.u64)
     3900                            return vbcppError(pThis, "Divide by zero");
     3901                        pResult->u.UnsignedValue.u64 %= Result2.u.UnsignedValue.u64;
     3902                        break;
     3903                    case kVBCppBinary_Addition:
     3904                        pResult->u.UnsignedValue.u64 += Result2.u.UnsignedValue.u64;
     3905                        break;
     3906                    case kVBCppBinary_Subtraction:
     3907                        pResult->u.UnsignedValue.u64 -= Result2.u.UnsignedValue.u64;
     3908                        break;
     3909                    case kVBCppBinary_LeftShift:
     3910                        pResult->u.UnsignedValue.u64 <<= Result2.u.UnsignedValue.u64;
     3911                        break;
     3912                    case kVBCppBinary_RightShift:
     3913                        pResult->u.UnsignedValue.u64 >>= Result2.u.UnsignedValue.u64;
     3914                        break;
     3915                    case kVBCppBinary_LessThan:
     3916                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 < Result2.u.UnsignedValue.u64;
     3917                        break;
     3918                    case kVBCppBinary_LessThanOrEqual:
     3919                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 <= Result2.u.UnsignedValue.u64;
     3920                        break;
     3921                    case kVBCppBinary_GreaterThan:
     3922                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 > Result2.u.UnsignedValue.u64;
     3923                        break;
     3924                    case kVBCppBinary_GreaterThanOrEqual:
     3925                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 >= Result2.u.UnsignedValue.u64;
     3926                        break;
     3927                    case kVBCppBinary_EqualTo:
     3928                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 == Result2.u.UnsignedValue.u64;
     3929                        break;
     3930                    case kVBCppBinary_NotEqualTo:
     3931                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 != Result2.u.UnsignedValue.u64;
     3932                        break;
     3933                    case kVBCppBinary_BitwiseAnd:
     3934                        pResult->u.UnsignedValue.u64 &= Result2.u.UnsignedValue.u64;
     3935                        break;
     3936                    case kVBCppBinary_BitwiseXor:
     3937                        pResult->u.UnsignedValue.u64 ^= Result2.u.UnsignedValue.u64;
     3938                        break;
     3939                    case kVBCppBinary_BitwiseOr:
     3940                        pResult->u.UnsignedValue.u64 |= Result2.u.UnsignedValue.u64;
     3941                        break;
     3942                    case kVBCppBinary_LogicalAnd:
     3943                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 && Result2.u.UnsignedValue.u64;
     3944                        break;
     3945                    case kVBCppBinary_LogicalOr:
     3946                        pResult->u.UnsignedValue.u64 = pResult->u.UnsignedValue.u64 || Result2.u.UnsignedValue.u64;
     3947                        break;
     3948                    default:
     3949                        return vbcppError(pThis, "Internal error: u.Binary.enmOperator=%d", pRoot->u.Binary.enmOperator);
     3950                }
     3951            }
     3952            else
     3953            {
     3954                switch (pRoot->u.Binary.enmOperator)
     3955                {
     3956                    case kVBCppBinary_Multiplication:
     3957                        pResult->u.SignedValue.s64 *= Result2.u.SignedValue.s64;
     3958                        break;
     3959                    case kVBCppBinary_Division:
     3960                        if (!Result2.u.SignedValue.s64)
     3961                            return vbcppError(pThis, "Divide by zero");
     3962                        pResult->u.SignedValue.s64 /= Result2.u.SignedValue.s64;
     3963                        break;
     3964                    case kVBCppBinary_Modulo:
     3965                        if (!Result2.u.SignedValue.s64)
     3966                            return vbcppError(pThis, "Divide by zero");
     3967                        pResult->u.SignedValue.s64 %= Result2.u.SignedValue.s64;
     3968                        break;
     3969                    case kVBCppBinary_Addition:
     3970                        pResult->u.SignedValue.s64 += Result2.u.SignedValue.s64;
     3971                        break;
     3972                    case kVBCppBinary_Subtraction:
     3973                        pResult->u.SignedValue.s64 -= Result2.u.SignedValue.s64;
     3974                        break;
     3975                    case kVBCppBinary_LeftShift:
     3976                        pResult->u.SignedValue.s64 <<= Result2.u.SignedValue.s64;
     3977                        break;
     3978                    case kVBCppBinary_RightShift:
     3979                        pResult->u.SignedValue.s64 >>= Result2.u.SignedValue.s64;
     3980                        break;
     3981                    case kVBCppBinary_LessThan:
     3982                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 < Result2.u.SignedValue.s64;
     3983                        break;
     3984                    case kVBCppBinary_LessThanOrEqual:
     3985                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 <= Result2.u.SignedValue.s64;
     3986                        break;
     3987                    case kVBCppBinary_GreaterThan:
     3988                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 > Result2.u.SignedValue.s64;
     3989                        break;
     3990                    case kVBCppBinary_GreaterThanOrEqual:
     3991                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 >= Result2.u.SignedValue.s64;
     3992                        break;
     3993                    case kVBCppBinary_EqualTo:
     3994                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 == Result2.u.SignedValue.s64;
     3995                        break;
     3996                    case kVBCppBinary_NotEqualTo:
     3997                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 != Result2.u.SignedValue.s64;
     3998                        break;
     3999                    case kVBCppBinary_BitwiseAnd:
     4000                        pResult->u.SignedValue.s64 &= Result2.u.SignedValue.s64;
     4001                        break;
     4002                    case kVBCppBinary_BitwiseXor:
     4003                        pResult->u.SignedValue.s64 ^= Result2.u.SignedValue.s64;
     4004                        break;
     4005                    case kVBCppBinary_BitwiseOr:
     4006                        pResult->u.SignedValue.s64 |= Result2.u.SignedValue.s64;
     4007                        break;
     4008                    case kVBCppBinary_LogicalAnd:
     4009                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 && Result2.u.SignedValue.s64;
     4010                        break;
     4011                    case kVBCppBinary_LogicalOr:
     4012                        pResult->u.SignedValue.s64 = pResult->u.SignedValue.s64 || Result2.u.SignedValue.s64;
     4013                        break;
     4014                    default:
     4015                        return vbcppError(pThis, "Internal error: u.Binary.enmOperator=%d", pRoot->u.Binary.enmOperator);
     4016                }
     4017            }
     4018            return rcExit;
     4019        }
     4020
     4021        case kVBCppExprKind_Ternary:
     4022            rcExit = vbcppExprEvaluteTree(pThis, pRoot->u.Ternary.pExpr, pResult);
     4023            if (rcExit != RTEXITCODE_SUCCESS)
     4024                return rcExit;
     4025            if (vbcppExprIsExprTrue(pResult))
     4026                return vbcppExprEvaluteTree(pThis, pRoot->u.Ternary.pTrue, pResult);
     4027            return vbcppExprEvaluteTree(pThis, pRoot->u.Ternary.pFalse, pResult);
     4028
     4029        default:
     4030            return vbcppError(pThis, "Internal error: enmKind=%d", pRoot->enmKind);
     4031    }
     4032}
    29094033
    29104034
     
    29184042 * @param   penmResult          Where to store the result.
    29194043 */
    2920 static RTEXITCODE vbcppExprEval(PVBCPP pThis, char *pszExpr, size_t cchExpr, VBCPPEVAL *penmResult)
    2921 {
    2922 #if 0
    2923     Assert(strlen(pszExpr) == cchExpr);
    2924     /** @todo */
    2925 #else           /* Greatly simplified for getting DTrace working. */
    2926 RTStrmPrintf(g_pStdErr, "expr: '%.*s'\n", cchExpr, pszExpr);
    2927     RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    2928     if (   !strcmp(pszExpr, "1")
    2929         || !strcmp(pszExpr, "64  == 64")
    2930         || !strcmp(pszExpr, "64  != 32")
    2931         || !strcmp(pszExpr, "32  != 64")
    2932         )
    2933         *penmResult = kVBCppEval_True;
    2934     else if (   !strcmp(pszExpr, "0")
    2935              || !strcmp(pszExpr, "32  == 64")
    2936              || !strcmp(pszExpr, "64  == 32")
    2937              || !strcmp(pszExpr, "64  != 64")
    2938              || !strcmp(pszExpr, "32  != 32")
    2939              )
    2940         *penmResult = kVBCppEval_False;
    2941     else if (pThis->fUndecidedConditionals)
    2942         *penmResult = kVBCppEval_Undecided;
    2943     else if (   !strcmp(pszExpr, "defined(IN_RING0)")
    2944              || !strcmp(pszExpr, "defined(IN_RC) || defined(IN_RING0)")
    2945              || !strcmp(pszExpr, "defined(VBOX_WITHOUT_UNNAMED_UNIONS)")
    2946              )
    2947         *penmResult = kVBCppEval_True;
    2948     else if (   !strcmp(pszExpr, "HC_ARCH_BITS == 32")
    2949              || !strcmp(pszExpr, "HC_ARCH_BITS != 32")
    2950              || !strcmp(pszExpr, "HC_ARCH_BITS == 64")
    2951              || !strcmp(pszExpr, "HC_ARCH_BITS != 64"))
    2952     {
    2953         PVBCPPDEF pMacro = vbcppMacroLookup(pThis, RT_STR_TUPLE("HC_ARCH_BITS"));
    2954         if (pMacro)
    2955         {
    2956             if (  !strcmp(pMacro->szValue, "32")
    2957                 ?    !strcmp(pszExpr, "HC_ARCH_BITS == 32")
    2958                   || !strcmp(pszExpr, "HC_ARCH_BITS != 64")
    2959                 :    !strcmp(pszExpr, "HC_ARCH_BITS == 64")
    2960                   || !strcmp(pszExpr, "HC_ARCH_BITS != 32"))
    2961                 *penmResult = kVBCppEval_True;
    2962             else
    2963                 *penmResult = kVBCppEval_False;
     4044static RTEXITCODE vbcppExprEval(PVBCPP pThis, char *pszExpr, size_t cchExpr, size_t cReplacements, VBCPPEVAL *penmResult)
     4045{
     4046    //Assert(strlen(pszExpr) == cchExpr);
     4047    size_t      cUndefined;
     4048    PVBCPPEXPR  pExprTree;
     4049    RTEXITCODE  rcExit = vbcppExprParse(pThis, pszExpr, cchExpr, &pExprTree, &cUndefined);
     4050    if (rcExit == RTEXITCODE_SUCCESS)
     4051    {
     4052        if (   !cUndefined
     4053            || pThis->enmMode == kVBCppMode_SelectiveD
     4054            || pThis->enmMode == kVBCppMode_Standard)
     4055        {
     4056            VBCPPEXPR Result;
     4057            rcExit = vbcppExprEvaluteTree(pThis, pExprTree, &Result);
     4058            if (rcExit == RTEXITCODE_SUCCESS)
     4059            {
     4060                if (vbcppExprIsExprTrue(&Result))
     4061                    *penmResult = kVBCppEval_True;
     4062                else
     4063                    *penmResult = kVBCppEval_False;
     4064            }
    29644065        }
    29654066        else
    2966             *penmResult = kVBCppEval_False;
    2967     }
    2968     else if (   !strcmp(pszExpr, "64  == 32 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)")
    2969              || !strcmp(pszExpr, "32  == 32 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)") )
    2970     {
    2971         PVBCPPDEF pMacro = vbcppMacroLookup(pThis, RT_STR_TUPLE("VBOX_WITH_HYBRID_32BIT_KERNEL"));
    2972         if (!pMacro && *pszExpr == '3')
    2973             *penmResult = kVBCppEval_True;
     4067            *penmResult = kVBCppEval_Undecided;
     4068    }
     4069    return rcExit;
     4070}
     4071
     4072
     4073static RTEXITCODE vbcppExtractSkipCommentLine(PVBCPP pThis, PSCMSTREAM pStrmInput)
     4074{
     4075    unsigned chPrev = ScmStreamGetCh(pStrmInput); Assert(chPrev == '/');
     4076    unsigned ch;
     4077    while ((ch = ScmStreamPeekCh(pStrmInput)) != ~(unsigned)0)
     4078    {
     4079        if (ch == '\r' || ch == '\n')
     4080        {
     4081            if (chPrev != '\\')
     4082                break;
     4083            ScmStreamSeekByLine(pStrmInput, ScmStreamTellLine(pStrmInput) + 1);
     4084            chPrev = ch;
     4085        }
    29744086        else
    2975             *penmResult = kVBCppEval_False;
    2976     }
    2977     else if (   !strcmp(pszExpr, "64  == 64 || defined(VBOX_WITH_HYBRID_32BIT_KERNEL)")
    2978              || !strcmp(pszExpr, "32  == 64 || defined(VBOX_WITH_HYBRID_32BIT_KERNEL)")
    2979              )
    2980     {
    2981         PVBCPPDEF pMacro = vbcppMacroLookup(pThis, RT_STR_TUPLE("VBOX_WITH_HYBRID_32BIT_KERNEL"));
    2982         if (*pszExpr == '6' || pMacro)
    2983             *penmResult = kVBCppEval_True;
     4087        {
     4088            chPrev = ScmStreamGetCh(pStrmInput);
     4089            Assert(chPrev == ch);
     4090        }
     4091    }
     4092    return RTEXITCODE_SUCCESS;
     4093}
     4094
     4095
     4096static RTEXITCODE vbcppExtractSkipComment(PVBCPP pThis, PSCMSTREAM pStrmInput)
     4097{
     4098    unsigned ch = ScmStreamGetCh(pStrmInput); Assert(ch == '*');
     4099    while ((ch = ScmStreamGetCh(pStrmInput)) != ~(unsigned)0)
     4100    {
     4101        if (ch == '*')
     4102        {
     4103            ch = ScmStreamGetCh(pStrmInput);
     4104            if (ch == '/')
     4105                return RTEXITCODE_SUCCESS;
     4106        }
     4107    }
     4108    return vbcppError(pThis, "Expected '*/'");
     4109}
     4110
     4111
     4112static RTEXITCODE vbcppExtractQuotedString(PVBCPP pThis, PSCMSTREAM pStrmInput, PVBCPPSTRBUF pStrBuf,
     4113                                           char chOpen, char chClose)
     4114{
     4115    unsigned ch = ScmStreamGetCh(pStrmInput);
     4116    Assert(ch == (unsigned)chOpen);
     4117
     4118    RTEXITCODE rcExit = vbcppStrBufAppendCh(pStrBuf, chOpen);
     4119    if (rcExit != RTEXITCODE_SUCCESS)
     4120        return rcExit;
     4121
     4122    for (;;)
     4123    {
     4124        ch = ScmStreamGetCh(pStrmInput);
     4125        if (ch == '\\')
     4126        {
     4127            ch = ScmStreamGetCh(pStrmInput);
     4128            if (ch == ~(unsigned)0)
     4129                break;
     4130            rcExit = vbcppStrBufAppendCh(pStrBuf, '\\');
     4131            if (rcExit == RTEXITCODE_SUCCESS)
     4132                rcExit = vbcppStrBufAppendCh(pStrBuf, ch);
     4133            if (rcExit != RTEXITCODE_SUCCESS)
     4134                return rcExit;
     4135        }
     4136        else if (ch != ~(unsigned)0)
     4137        {
     4138            rcExit = vbcppStrBufAppendCh(pStrBuf, ch);
     4139            if (rcExit != RTEXITCODE_SUCCESS)
     4140                return rcExit;
     4141            if (ch == (unsigned)chClose)
     4142                return RTEXITCODE_SUCCESS;
     4143        }
    29844144        else
    2985             *penmResult = kVBCppEval_False;
    2986     }
    2987     else if (   !strcmp(pszExpr, "defined(VBOX_WITH_HYBRID_32BIT_KERNEL) && ( 32  != 32 || R0_ARCH_BITS != 32)")
    2988              || !strcmp(pszExpr, "defined(VBOX_WITH_HYBRID_32BIT_KERNEL) && ( 64  != 32 || R0_ARCH_BITS != 32)") )
    2989     {
    2990         PVBCPPDEF pMacro1 = vbcppMacroLookup(pThis, RT_STR_TUPLE("VBOX_WITH_HYBRID_32BIT_KERNEL"));
    2991         PVBCPPDEF pMacro2 = vbcppMacroLookup(pThis, RT_STR_TUPLE("HC_ARCH_BITS"));
    2992         PVBCPPDEF pMacro3 = vbcppMacroLookup(pThis, RT_STR_TUPLE("R0_ARCH_BITS"));
    2993         if  (   pMacro1
    2994              && (   (!pMacro2 || strcmp(pMacro2->szValue, "32"))
    2995                  || (!pMacro3 || strcmp(pMacro3->szValue, "32"))))
    2996             *penmResult = kVBCppEval_True;
    2997         else
    2998             *penmResult = kVBCppEval_False;
    2999     }
    3000     else
    3001         rcExit = vbcppError(pThis, "Too compliated expression '%s'", pszExpr);
    3002 #endif
    3003     return rcExit;
    3004 }
    3005 
    3006 
    3007 /**
    3008  * Expands known macros in the expression.
    3009  *
    3010  * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg.
    3011  * @param   pThis               The C preprocessor instance.
    3012  * @param   ppszExpr            The expression to expand. Input/Output.
    3013  * @param   pcchExpr            The length of the expression. Input/Output.
    3014  * @param   pcReplacements      Where to store the number of replacements made.
    3015  *                              Optional.
    3016  */
    3017 static RTEXITCODE vbcppExprExpand(PVBCPP pThis, char **ppszExpr, size_t *pcchExpr, size_t *pcReplacements)
    3018 {
    3019     RTEXITCODE  rcExit      = RTEXITCODE_SUCCESS;
    3020     char       *pszExpr     = *ppszExpr;
    3021     size_t      cchExpr     = pcchExpr ? *pcchExpr :  strlen(pszExpr);
    3022     size_t      cbExprAlloc = cchExpr + 1;
    3023     size_t      cHits       = 0;
    3024     size_t      off         = 0;
    3025     char        ch;
    3026     while ((ch = pszExpr[off]) != '\0')
    3027     {
    3028         if (!vbcppIsCIdentifierLeadChar(ch))
    3029             off++;
    3030         else
    3031         {
    3032             /* Extract the identifier. */
    3033             size_t const offIdentifier = off++;
    3034             while (   off < cchExpr
    3035                    && vbcppIsCIdentifierChar(pszExpr[off]))
    3036                 off++;
    3037             size_t const cchIdentifier = off - offIdentifier;
    3038 
    3039             /* Does it exist?  Will save a whole lot of trouble if it doesn't. */
    3040             PVBCPPDEF pMacro = vbcppMacroLookup(pThis, &pszExpr[offIdentifier], cchIdentifier);
    3041             if (pMacro)
    3042             {
    3043                 /* Skip white space and check for parenthesis. */
    3044                 while (   off < cchExpr
    3045                        && RT_C_IS_SPACE(pszExpr[off]))
    3046                     off++;
    3047                 if (   off < cchExpr
    3048                     && pszExpr[off] == '(')
    3049                 {
    3050                     /* Try expand function define. */
    3051                     rcExit = vbcppError(pThis, "Expanding function macros is not yet implemented");
    3052                     break;
    3053                 }
    3054                 else
    3055                 {
    3056                     /* Expand simple define if found. */
    3057                     if (pMacro->cchValue + 2 < cchIdentifier)
    3058                     {
    3059                         size_t offDelta = cchIdentifier - pMacro->cchValue - 2;
    3060                         memmove(&pszExpr[offIdentifier], &pszExpr[offIdentifier + offDelta],
    3061                                 cchExpr - offIdentifier - offDelta + 1); /* Lazy bird is moving too much! */
    3062                         cchExpr -= offDelta;
    3063                     }
    3064                     else if (pMacro->cchValue + 2 > cchIdentifier)
    3065                     {
    3066                         size_t offDelta = pMacro->cchValue + 2 - cchIdentifier;
    3067                         if (cchExpr + offDelta + 1 > cbExprAlloc)
    3068                         {
    3069                             do
    3070                             {
    3071                                 cbExprAlloc *= 2;
    3072                             } while (cchExpr + offDelta + 1 > cbExprAlloc);
    3073                             void *pv = RTMemRealloc(pszExpr,  cbExprAlloc);
    3074                             if (!pv)
    3075                             {
    3076                                 rcExit = vbcppError(pThis, "out of memory (%zu bytes)", cbExprAlloc);
    3077                                 break;
    3078                             }
    3079                             pszExpr = (char *)pv;
    3080                         }
    3081                         memmove(&pszExpr[offIdentifier + offDelta], &pszExpr[offIdentifier],
    3082                                 cchExpr - offIdentifier + 1); /* Lazy bird is moving too much! */
    3083                         cchExpr += offDelta;
    3084                     }
    3085 
    3086                     /* Insert with spaces around it. Not entirely sure how
    3087                        standard compliant this is... */
    3088                     pszExpr[offIdentifier] = ' ';
    3089                     memcpy(&pszExpr[offIdentifier + 1], pMacro->szValue, pMacro->cchValue);
    3090                     pszExpr[offIdentifier + 1 + pMacro->cchValue] = ' ';
    3091 
    3092                     /* Restart parsing at the inserted macro. */
    3093                     off = offIdentifier + 1;
    3094                 }
    3095             }
    3096         }
    3097     }
    3098 
    3099     return rcExit;
    3100 }
    3101 
    3102 
    3103 
    3104 /**
    3105  * Extracts the expression.
     4145            break;
     4146    }
     4147
     4148    return vbcppError(pThis, "File ended with an open character constant");
     4149}
     4150
     4151
     4152/**
     4153 * Extracts a line from the stream, stripping it for comments and maybe
     4154 * optimzing some of the whitespace.
    31064155 *
    31074156 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg.
    31084157 * @param   pThis               The C preprocessor instance.
    31094158 * @param   pStrmInput          The input stream.
    3110  * @param   ppszExpr            Where to return the expression string..
    3111  * @param   pcchExpr            Where to return the expression length.
    3112  *                              Optional.
     4159 * @param   pStrBuf             Where to store the extracted line. Caller must
     4160 *                              initialize this prior to the call an delete it
     4161 *                              after use (even on failure).
    31134162 * @param   poffComment         Where to note down the position of the final
    31144163 *                              comment. Optional.
    31154164 */
    3116 static RTEXITCODE vbcppExprExtract(PVBCPP pThis, PSCMSTREAM pStrmInput,
    3117                                    char **ppszExpr, size_t *pcchExpr, size_t *poffComment)
    3118 {
    3119     RTEXITCODE  rcExit      = RTEXITCODE_SUCCESS;
    3120     size_t      cbExprAlloc = 0;
    3121     size_t      cchExpr     = 0;
    3122     char       *pszExpr     = NULL;
    3123     bool        fInComment  = false;
     4165static RTEXITCODE vbcppExtractDirectiveLine(PVBCPP pThis, PSCMSTREAM pStrmInput, PVBCPPSTRBUF pStrBuf, size_t *poffComment)
     4166{
    31244167    size_t      offComment  = ~(size_t)0;
    3125     unsigned    chPrev      = 0;
    31264168    unsigned    ch;
    31274169    while ((ch = ScmStreamPeekCh(pStrmInput)) != ~(unsigned)0)
    31284170    {
    3129         if (ch == '\r' || ch == '\n')
    3130         {
    3131             if (chPrev == '\\')
     4171        RTEXITCODE rcExit;
     4172        if (ch == '/')
     4173        {
     4174            /* Comment? */
     4175            unsigned ch2 = ScmStreamGetCh(pStrmInput); Assert(ch == ch2);
     4176            ch = ScmStreamPeekCh(pStrmInput);
     4177            if (ch == '*')
     4178            {
     4179                offComment = ScmStreamTell(pStrmInput) - 1;
     4180                rcExit = vbcppExtractSkipComment(pThis, pStrmInput);
     4181            }
     4182            else if (ch == '/')
     4183            {
     4184                offComment = ScmStreamTell(pStrmInput) - 1;
     4185                rcExit = vbcppExtractSkipCommentLine(pThis, pStrmInput);
     4186            }
     4187            else
     4188                rcExit = vbcppStrBufAppendCh(pStrBuf, '/');
     4189        }
     4190        else if (ch == '\'')
     4191        {
     4192            offComment = ~(size_t)0;
     4193            rcExit = vbcppExtractQuotedString(pThis, pStrmInput, pStrBuf, '\'', '\'');
     4194        }
     4195        else if (ch == '"')
     4196        {
     4197            offComment = ~(size_t)0;
     4198            rcExit = vbcppExtractQuotedString(pThis, pStrmInput, pStrBuf, '"', '"');
     4199        }
     4200        else if (ch == '\r' || ch == '\n')
     4201        {
     4202            break; /* done */
     4203        }
     4204        else if (RT_C_IS_SPACE(ch) && RT_C_IS_SPACE(vbcppStrBufLastCh(pStrBuf)))
     4205        {
     4206            unsigned ch2 = ScmStreamGetCh(pStrmInput);
     4207            Assert(ch == ch2);
     4208        }
     4209        else
     4210        {
     4211            unsigned ch2 = ScmStreamGetCh(pStrmInput); Assert(ch == ch2);
     4212
     4213            /* Escaped newline? */
     4214            if (   ch == '\\'
     4215                && (   (ch2 = ScmStreamPeekCh(pStrmInput)) == '\r'
     4216                    || ch2 == '\n'))
    31324217            {
    31334218                ScmStreamSeekByLine(pStrmInput, ScmStreamTellLine(pStrmInput) + 1);
    3134                 pszExpr[--cchExpr] = '\0';
    3135                 continue;
    3136             }
    3137             if (!fInComment)
    3138                 break;
    3139             /* The expression continues after multi-line comments. Cool. :-) */
    3140         }
    3141         else if (!fInComment)
    3142         {
    3143             if (chPrev == '/' && ch == '*' )
    3144             {
    3145                 pszExpr[--cchExpr] = '\0';
    3146                 fInComment = true;
    3147                 offComment = ScmStreamTell(pStrmInput) - 1;
    3148             }
    3149             else if (chPrev == '/' && ch == '/')
    3150             {
    3151                 offComment = ScmStreamTell(pStrmInput) - 1;
    3152                 rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput);
    3153                 break;                  /* done */
    3154             }
    3155             /* Append the char to the expression. */
     4219            }
    31564220            else
    31574221            {
    3158                 if (cchExpr + 2 > cbExprAlloc)
    3159                 {
    3160                     cbExprAlloc = cbExprAlloc ? cbExprAlloc * 2 : 8;
    3161                     void *pv = RTMemRealloc(pszExpr, cbExprAlloc);
    3162                     if (!pv)
    3163                     {
    3164                         rcExit = vbcppError(pThis, "out of memory (%zu bytes)", cbExprAlloc);
    3165                         break;
    3166                     }
    3167                     pszExpr = (char *)pv;
    3168                 }
    3169                 pszExpr[cchExpr++] = ch;
    3170                 pszExpr[cchExpr]   = '\0';
    3171             }
    3172         }
    3173         else if (ch == '/' && chPrev == '*')
    3174             fInComment = false;
    3175 
    3176         /* advance */
    3177         chPrev = ch;
    3178         ch = ScmStreamGetCh(pStrmInput); Assert(ch == chPrev);
    3179     }
    3180 
    3181     if (rcExit == RTEXITCODE_SUCCESS)
    3182     {
    3183         *ppszExpr = pszExpr;
    3184         if (pcchExpr)
    3185             *pcchExpr = cchExpr;
    3186         if (poffComment)
    3187             *poffComment = offComment;
    3188     }
    3189     else
    3190         RTMemFree(pszExpr);
    3191     return rcExit;
     4222                offComment = ~(size_t)0;
     4223                rcExit = vbcppStrBufAppendCh(pStrBuf, ch);
     4224            }
     4225        }
     4226        if (rcExit != RTEXITCODE_SUCCESS)
     4227            return rcExit;
     4228    }
     4229
     4230    if (poffComment)
     4231        *poffComment = offComment;
     4232    return RTEXITCODE_SUCCESS;
    31924233}
    31934234
     
    32044245 */
    32054246static RTEXITCODE vbcppDirectiveIfOrElif(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart,
    3206                                        VBCPPCONDKIND enmKind)
     4247                                         VBCPPCONDKIND enmKind)
    32074248{
    32084249    /*
     
    32144255
    32154256    /*
    3216      * Extract and expand the expression string.
    3217      */
    3218     const char *pchCondition = ScmStreamGetCur(pStrmInput);
    3219     char       *pszExpr;
    3220     size_t      cchExpr;
    3221     size_t      offComment;
    3222     RTEXITCODE  rcExit = vbcppExprExtract(pThis, pStrmInput, &pszExpr, &cchExpr, &offComment);
     4257     * Extract the expression string.
     4258     */
     4259    const char         *pchCondition = ScmStreamGetCur(pStrmInput);
     4260    size_t              offComment;
     4261    VBCPPMACROEXP       ExpCtx;
     4262    ExpCtx.pMacroStack    = NULL;
     4263    ExpCtx.pStrmInput     = NULL;
     4264    ExpCtx.papszArgs      = NULL;
     4265    ExpCtx.cArgs          = 0;
     4266    ExpCtx.cArgsAlloced   = 0;
     4267    vbcppStrBufInit(&ExpCtx.StrBuf, pThis);
     4268    RTEXITCODE  rcExit = vbcppExtractDirectiveLine(pThis, pStrmInput, &ExpCtx.StrBuf, &offComment);
    32234269    if (rcExit == RTEXITCODE_SUCCESS)
    32244270    {
    32254271        size_t const    cchCondition = ScmStreamGetCur(pStrmInput) - pchCondition;
     4272
     4273        /*
     4274         * Expand known macros in it.
     4275         */
    32264276        size_t          cReplacements;
    3227         rcExit = vbcppExprExpand(pThis, &pszExpr, &cchExpr, &cReplacements);
     4277        rcExit = vbcppMacroExpandReScan(pThis, &ExpCtx, kMacroReScanMode_Expression, &cReplacements);
    32284278        if (rcExit == RTEXITCODE_SUCCESS)
    32294279        {
     
    32314281             * Strip it and check that it's not empty.
    32324282             */
    3233             char *pszExpr2 = pszExpr;
    3234             while (cchExpr > 0 && RT_C_IS_SPACE(*pszExpr2))
    3235                 pszExpr2++, cchExpr--;
    3236 
    3237             while (cchExpr > 0 && RT_C_IS_SPACE(pszExpr2[cchExpr - 1]))
    3238                 pszExpr2[--cchExpr] = '\0';
     4283            char   *pszExpr = ExpCtx.StrBuf.pszBuf;
     4284            size_t  cchExpr = ExpCtx.StrBuf.cchBuf;
     4285            while (cchExpr > 0 && RT_C_IS_SPACE(*pszExpr))
     4286                pszExpr++, cchExpr--;
     4287
     4288            while (cchExpr > 0 && RT_C_IS_SPACE(pszExpr[cchExpr - 1]))
     4289            {
     4290                pszExpr[--cchExpr] = '\0';
     4291                ExpCtx.StrBuf.cchBuf--;
     4292            }
    32394293            if (cchExpr)
    32404294            {
     
    32434297                 */
    32444298                VBCPPEVAL enmResult;
    3245                 rcExit = vbcppExprEval(pThis, pszExpr2, cchExpr, &enmResult);
     4299                rcExit = vbcppExprEval(pThis, pszExpr, cchExpr, cReplacements, &enmResult);
    32464300                if (rcExit == RTEXITCODE_SUCCESS)
    32474301                {
     
    32544308                    else
    32554309                    {
     4310
    32564311                        PVBCPPCOND pCond = pThis->pCondStack;
    32574312                        if (   pCond->enmResult != kVBCppEval_Undecided
     
    32594314                                || pCond->pUp->enmStackResult == kVBCppEval_True))
    32604315                        {
    3261                             if (enmResult == kVBCppEval_True)
     4316                            Assert(enmResult == kVBCppEval_True || enmResult == kVBCppEval_False);
     4317                            if (   pCond->enmResult == kVBCppEval_False
     4318                                && enmResult        == kVBCppEval_True
     4319                                && !pCond->fElIfDecided)
     4320                            {
     4321                                pCond->enmStackResult = kVBCppEval_True;
     4322                                pCond->fElIfDecided   = true;
     4323                            }
     4324                            else
    32624325                                pCond->enmStackResult = kVBCppEval_False;
    3263                             else
    3264                                 pCond->enmStackResult = kVBCppEval_True;
    32654326                            pThis->fIf0Mode = pCond->enmStackResult == kVBCppEval_False;
    32664327                        }
     4328                        pCond->enmKind   = kVBCppCondKind_ElIf;
    32674329                        pCond->enmResult = enmResult;
    32684330                        pCond->pchCond   = pchCondition;
     
    32894351                rcExit = vbcppError(pThis, "Empty #if expression");
    32904352        }
    3291         RTMemFree(pszExpr);
    3292     }
     4353    }
     4354    vbcppMacroExpandCleanup(&ExpCtx);
    32934355    return rcExit;
    32944356}
     
    34184480                        || pCond->pUp->enmStackResult == kVBCppEval_True))
    34194481                {
    3420                     if (pCond->enmResult == kVBCppEval_True)
     4482                    if (   pCond->enmResult == kVBCppEval_True
     4483                        || pCond->fElIfDecided)
     4484
    34214485                        pCond->enmStackResult = kVBCppEval_False;
    34224486                    else
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