- Timestamp:
- May 14, 2012 1:52:01 AM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/VBoxCPP.cpp
r41259 r41263 139 139 { 140 140 /** The expansion buffer. */ 141 char *pszBuf; 142 /** The length of the string in the expansion buffer. */ 143 size_t cchBuf; 144 /** The current allocated buffer size. */ 145 size_t cbBufAllocated; 141 VBCPPSTRBUF StrBuf; 146 142 /** List of expanding macros (Stack). */ 147 143 PVBCPPDEF pMacroStack; … … 160 156 161 157 /** 158 * The vbcppMacroExpandReScan mode of operation. 159 */ 160 typedef 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 /** 162 174 * Evaluation result. 163 175 */ … … 207 219 /** Whether we've seen the last else. */ 208 220 bool fSeenElse; 221 /** Set if we have an else if which has already been decided. */ 222 bool fElIfDecided; 209 223 /** The nesting level of this condition. */ 210 224 uint16_t iLevel; … … 343 357 *******************************************************************************/ 344 358 static 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 );359 static RTEXITCODE vbcppMacroExpandIt(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offMacro, PVBCPPDEF pMacro, size_t *poffParameters); 360 static RTEXITCODE vbcppMacroExpandReScan(PVBCPP pThis, PVBCPPMACROEXP pExp, VBCPPMACRORESCANMODE enmMode, size_t *pcReplacements); 347 361 static void vbcppMacroExpandCleanup(PVBCPPMACROEXP pExp); 348 362 … … 368 382 * @param pThis The C preprocessor instance. 369 383 * @param pszMsg The message. 370 * @param ...Message arguments.371 */ 372 static RTEXITCODE vbcppError (PVBCPP pThis, const char *pszMsg, ...)384 * @param va Message arguments. 385 */ 386 static RTEXITCODE vbcppErrorV(PVBCPP pThis, const char *pszMsg, va_list va) 373 387 { 374 388 NOREF(pThis); … … 382 396 size_t const offLine = ScmStreamTell(pStrm); 383 397 384 va_list va;385 va_start(va, pszMsg);386 398 RTPrintf("%s:%d:%zd: error: %N.\n", pThis->pInputStack->szName, iLine + 1, off - offLine + 1, pszMsg, va); 387 va_end(va);388 399 389 400 size_t cchLine; … … 398 409 } 399 410 else 400 {401 va_list va;402 va_start(va, pszMsg);403 411 RTMsgErrorV(pszMsg, va); 404 va_end(va);405 }406 412 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 */ 424 static 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; 407 431 } 408 432 … … 1332 1356 ExpCtx.cArgs = 0; 1333 1357 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); 1365 1384 } 1366 1385 else … … 1464 1483 */ 1465 1484 bool const fLeadingSpace = off > 0 1466 && !RT_C_IS_SPACE(pExp-> pszBuf[off - 1]);1467 bool const fTrailingSpace = off + cchToReplace < pExp-> cchBuf1468 && !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]); 1469 1488 size_t const cchActualReplacement = fLeadingSpace + cchReplacement + fTrailingSpace; 1470 1489 … … 1477 1496 1478 1497 /* 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; 1493 1502 1494 1503 /* 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; 1499 1508 1500 1509 } … … 1504 1513 1505 1514 /* 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; 1510 1519 } 1511 1520 … … 1513 1522 * Insert the replacement string. 1514 1523 */ 1515 char *pszCur = &pExp-> pszBuf[off];1524 char *pszCur = &pExp->StrBuf.pszBuf[off]; 1516 1525 if (fLeadingSpace) 1517 1526 *pszCur++ = ' '; … … 1520 1529 *pszCur++ = ' '; 1521 1530 1522 Assert(strlen(pExp->pszBuf) == pExp->cchBuf); 1523 Assert(pExp->cchBuf < pExp->cbBufAllocated); 1531 Assert(strlen(pExp->StrBuf.pszBuf) == pExp->StrBuf.cchBuf); 1524 1532 1525 1533 return RTEXITCODE_SUCCESS; … … 1530 1538 { 1531 1539 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]; 1535 1543 } 1536 1544 … … 1539 1547 { 1540 1548 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; 1543 1551 *poff = off + 1; 1544 return pExp-> pszBuf[off];1552 return pExp->StrBuf.pszBuf[off]; 1545 1553 } 1546 1554 … … 1683 1691 while ((ch = vbcppMacroExpandGetCh(pExp, poff)) != ~(unsigned)0) 1684 1692 { 1693 /** @todo check for '#directives'! */ 1685 1694 if (ch == ')' && !chQuote) 1686 1695 { … … 1969 1978 * invocation. 1970 1979 * @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. 1975 1989 */ 1976 1990 static RTEXITCODE vbcppMacroExpandIt(PVBCPP pThis, PVBCPPMACROEXP pExp, size_t offMacro, PVBCPPDEF pMacro, 1977 size_t offParameters)1991 size_t *poffParameters) 1978 1992 { 1979 1993 RTEXITCODE rcExit; 1980 Assert(offMacro + pMacro->Core.cchString <= pExp-> cchBuf);1994 Assert(offMacro + pMacro->Core.cchString <= pExp->StrBuf.cchBuf); 1981 1995 Assert(!pMacro->fExpanding); 1982 1996 … … 1986 2000 if (pMacro->fFunction) 1987 2001 { 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); 1990 2003 if (rcExit == RTEXITCODE_SUCCESS) 1991 2004 { … … 2003 2016 rcExit = vbcppMacroExpandValueWithArguments(pThis, pExp, pMacro, &ValueBuf); 2004 2017 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); 2006 2020 vbcppStrBufDelete(&ValueBuf); 2007 2021 } … … 2027 2041 2028 2042 /** 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 */ 2056 static 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 */ 2107 static 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 /** 2029 2159 * Re-scan the expanded macro. 2030 2160 * 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 */ 2168 static 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 } 2040 2247 2041 2248 return rcExit; … … 2071 2278 pExp->papszArgs = NULL; 2072 2279 2073 RTMemFree(pExp->pszBuf); 2074 pExp->pszBuf = NULL; 2280 vbcppStrBufDelete(&pExp->StrBuf); 2075 2281 } 2076 2282 … … 2776 2982 pCond->enmStackResult = pUp ? vbcppCondCombine(enmResult, pUp->enmStackResult) : enmResult; 2777 2983 pCond->fSeenElse = false; 2984 pCond->fElIfDecided = enmResult == kVBCppEval_True; 2778 2985 pCond->iLevel = pThis->cCondStackDepth; 2779 2986 pCond->iKeepLevel = (pUp ? pUp->iKeepLevel : 0) + enmResult == kVBCppEval_Undecided; … … 2813 3020 2814 3021 2815 #if 02816 3022 typedef enum VBCPPEXPRKIND 2817 3023 { 2818 3024 kVBCppExprKind_Invalid = 0, 3025 kVBCppExprKind_Unary, 2819 3026 kVBCppExprKind_Binary, 2820 kVBCppExprKind_ Unary,3027 kVBCppExprKind_Ternary, 2821 3028 kVBCppExprKind_SignedValue, 2822 3029 kVBCppExprKind_UnsignedValue, 2823 kVBCppExprKind_Define,2824 3030 kVBCppExprKind_End 2825 3031 } VBCPPEXPRKIND; 2826 3032 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 3038 typedef 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 3049 typedef 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 2827 3078 typedef struct VBCPPEXPR *PVBCPPEXPR; 2828 3079 … … 2832 3083 typedef struct VBCPPEXPR 2833 3084 { 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; 2840 3089 /** The kind of expression. */ 2841 3090 VBCPPEXPRKIND enmKind; 2842 /** */3091 /** Content specific. */ 2843 3092 union 2844 3093 { … … 2858 3107 struct 2859 3108 { 3109 PVBCPPEXPR pExpr; 3110 PVBCPPEXPR pTrue; 3111 PVBCPPEXPR pFalse; 3112 } Ternary; 3113 3114 struct 3115 { 2860 3116 int64_t s64; 2861 unsigned cBits;2862 3117 } SignedValue; 2863 3118 … … 2865 3120 { 2866 3121 uint64_t u64; 2867 unsigned cBits;2868 3122 } UnsignedValue; 2869 3123 2870 struct2871 {2872 const char *pch;2873 size_t cch;2874 } Define;2875 2876 3124 } u; 2877 /** Parent expression. */2878 PVBCPPEXPR pParent;2879 3125 } VBCPPEXPR; 2880 3126 2881 3127 2882 3128 2883 typedef struct VBCPPEXPRPARSER2884 {2885 PVBCPPEXPR pStack2886 } VBCPPEXPRPARSER;2887 2888 2889 3129 /** 2890 3130 * Operator return statuses. 2891 3131 */ 2892 typedef enum 3132 typedef enum VBCPPEXPRRET 2893 3133 { 2894 3134 kExprRet_Error = -1, 2895 3135 kExprRet_Ok = 0, 2896 kExprRet_ Operator,2897 kExprRet_ Operand,3136 kExprRet_UnaryOperator, 3137 kExprRet_Value, 2898 3138 kExprRet_EndOfExpr, 2899 3139 kExprRet_End 2900 3140 } VBCPPEXPRRET; 2901 3141 2902 2903 static VBCPPEXPRRET vbcppExprEatUnaryOrOperand(PVBCPPEXPRPARSER pThis, PSCMSTREAM pStrmInput) 2904 { 2905 2906 } 2907 3142 /** 3143 * Expression parser context. 3144 */ 3145 typedef 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. */ 3163 typedef VBCPPEXPRPARSER *PVBCPPEXPRPARSER; 3164 3165 3166 /** 3167 * Recursively destroys the expression tree. 3168 * 3169 * @param pExpr The root of the expression tree to destroy. 3170 */ 3171 static 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 3201 static 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 3211 static void vbcppExprParseSkipWhiteSpace(PVBCPPEXPRPARSER pParser) 3212 { 3213 while (RT_C_IS_SPACE(*pParser->pszCur)) 3214 pParser->pszCur++; 3215 } 3216 3217 3218 static PVBCPPEXPR vbcppExprParseAllocNode(PVBCPPEXPRPARSER pParser) 3219 { 3220 PVBCPPEXPR pExpr = (PVBCPPEXPR)RTMemAllocZ(sizeof(*pExpr)); 3221 return pExpr; 3222 } 3223 3224 3225 static 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; 2908 3273 #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 3491 static 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 3528 static 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 3618 static 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 3661 static 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 3726 static 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 3786 static 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 3795 static 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 } 2909 4033 2910 4034 … … 2918 4042 * @param penmResult Where to store the result. 2919 4043 */ 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; 4044 static 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 } 2964 4065 } 2965 4066 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 4073 static 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 } 2974 4086 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 4096 static 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 4112 static 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 } 2984 4144 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. 3106 4155 * 3107 4156 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 3108 4157 * @param pThis The C preprocessor instance. 3109 4158 * @param pStrmInput The input stream. 3110 * @param p pszExpr 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). 3113 4162 * @param poffComment Where to note down the position of the final 3114 4163 * comment. Optional. 3115 4164 */ 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; 4165 static RTEXITCODE vbcppExtractDirectiveLine(PVBCPP pThis, PSCMSTREAM pStrmInput, PVBCPPSTRBUF pStrBuf, size_t *poffComment) 4166 { 3124 4167 size_t offComment = ~(size_t)0; 3125 unsigned chPrev = 0;3126 4168 unsigned ch; 3127 4169 while ((ch = ScmStreamPeekCh(pStrmInput)) != ~(unsigned)0) 3128 4170 { 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')) 3132 4217 { 3133 4218 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 } 3156 4220 else 3157 4221 { 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; 3192 4233 } 3193 4234 … … 3204 4245 */ 3205 4246 static RTEXITCODE vbcppDirectiveIfOrElif(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart, 3206 VBCPPCONDKIND enmKind)4247 VBCPPCONDKIND enmKind) 3207 4248 { 3208 4249 /* … … 3214 4255 3215 4256 /* 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); 3223 4269 if (rcExit == RTEXITCODE_SUCCESS) 3224 4270 { 3225 4271 size_t const cchCondition = ScmStreamGetCur(pStrmInput) - pchCondition; 4272 4273 /* 4274 * Expand known macros in it. 4275 */ 3226 4276 size_t cReplacements; 3227 rcExit = vbcpp ExprExpand(pThis, &pszExpr, &cchExpr, &cReplacements);4277 rcExit = vbcppMacroExpandReScan(pThis, &ExpCtx, kMacroReScanMode_Expression, &cReplacements); 3228 4278 if (rcExit == RTEXITCODE_SUCCESS) 3229 4279 { … … 3231 4281 * Strip it and check that it's not empty. 3232 4282 */ 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 } 3239 4293 if (cchExpr) 3240 4294 { … … 3243 4297 */ 3244 4298 VBCPPEVAL enmResult; 3245 rcExit = vbcppExprEval(pThis, pszExpr 2, cchExpr, &enmResult);4299 rcExit = vbcppExprEval(pThis, pszExpr, cchExpr, cReplacements, &enmResult); 3246 4300 if (rcExit == RTEXITCODE_SUCCESS) 3247 4301 { … … 3254 4308 else 3255 4309 { 4310 3256 4311 PVBCPPCOND pCond = pThis->pCondStack; 3257 4312 if ( pCond->enmResult != kVBCppEval_Undecided … … 3259 4314 || pCond->pUp->enmStackResult == kVBCppEval_True)) 3260 4315 { 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 3262 4325 pCond->enmStackResult = kVBCppEval_False; 3263 else3264 pCond->enmStackResult = kVBCppEval_True;3265 4326 pThis->fIf0Mode = pCond->enmStackResult == kVBCppEval_False; 3266 4327 } 4328 pCond->enmKind = kVBCppCondKind_ElIf; 3267 4329 pCond->enmResult = enmResult; 3268 4330 pCond->pchCond = pchCondition; … … 3289 4351 rcExit = vbcppError(pThis, "Empty #if expression"); 3290 4352 } 3291 RTMemFree(pszExpr);3292 }4353 } 4354 vbcppMacroExpandCleanup(&ExpCtx); 3293 4355 return rcExit; 3294 4356 } … … 3418 4480 || pCond->pUp->enmStackResult == kVBCppEval_True)) 3419 4481 { 3420 if (pCond->enmResult == kVBCppEval_True) 4482 if ( pCond->enmResult == kVBCppEval_True 4483 || pCond->fElIfDecided) 4484 3421 4485 pCond->enmStackResult = kVBCppEval_False; 3422 4486 else
Note:
See TracChangeset
for help on using the changeset viewer.