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