- Timestamp:
- May 8, 2012 3:03:48 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bldprogs/VBoxCPP.cpp
r41204 r41209 101 101 /** Lead character bitmap for the argument names. */ 102 102 VBCPP_BITMAP_TYPE bmArgs[VBCPP_BITMAP_SIZE]; 103 /** The value length. */ 104 size_t cchValue; 103 105 /** The define value. (This is followed by the name and arguments.) */ 104 106 char szValue[1]; … … 932 934 933 935 /** 936 * Looks up a define. 937 * 938 * @returns Pointer to the define if found, NULL if not. 939 * @param pThis The C preprocessor instance. 940 * @param pszDefine The define name and optionally the argument 941 * list. 942 * @param cchDefine The length of the name. RTSTR_MAX is ok. 943 */ 944 static PVBCPPDEF vbcppDefineLookup(PVBCPP pThis, const char *pszDefine, size_t cchDefine) 945 { 946 if (!cchDefine) 947 return NULL; 948 if (!VBCPP_BITMAP_IS_SET(pThis->bmDefined, *pszDefine)) 949 return NULL; 950 return (PVBCPPDEF)RTStrSpaceGetN(&pThis->StrSpace, pszDefine, cchDefine); 951 } 952 953 954 /** 934 955 * Frees a define. 935 956 * … … 994 1015 static RTEXITCODE vbcppDefineInsert(PVBCPP pThis, PVBCPPDEF pDef) 995 1016 { 1017 /* 1018 * Reject illegal macro names. 1019 */ 1020 if (!strcmp(pDef->Core.pszString, "defined")) 1021 { 1022 RTEXITCODE rcExit = vbcppError(pThis, "Cannot use '%s' as a macro name", pDef->Core.pszString); 1023 vbcppFreeDefine(&pDef->Core, NULL); 1024 return rcExit; 1025 } 1026 996 1027 /* 997 1028 * Ignore in source-file defines when doing selective preprocessing. … … 1121 1152 pDef->papszArgs = (const char **)((uintptr_t)pDef + cbDef - sizeof(const char *) * cArgs); 1122 1153 VBCPP_BITMAP_EMPTY(pDef->bmArgs); 1154 pDef->cchValue = cchValue; 1123 1155 memcpy(pDef->szValue, pszValue, cchValue); 1124 1156 pDef->szValue[cchValue] = '\0'; … … 1231 1263 pDef->papszArgs = NULL; 1232 1264 VBCPP_BITMAP_EMPTY(pDef->bmArgs); 1265 pDef->cchValue = cchValue; 1233 1266 memcpy(pDef->szValue, pszValue, cchValue); 1234 1267 pDef->szValue[cchValue] = '\0'; … … 1309 1342 ScmStreamSeekByLine(pStrmInput, ScmStreamTellLine(pStrmInput) + 1); 1310 1343 } 1311 ScmStreamGetCh(pStrmInput);1344 chPrev = ScmStreamGetCh(pStrmInput); 1312 1345 } 1313 1346 size_t cchValue = ScmStreamGetCur(pStrmInput) - pchValue; … … 1461 1494 1462 1495 1496 #if 0 1497 typedef enum VBCPPEXPRKIND 1498 { 1499 kVBCppExprKind_Invalid = 0, 1500 kVBCppExprKind_Binary, 1501 kVBCppExprKind_Unary, 1502 kVBCppExprKind_SignedValue, 1503 kVBCppExprKind_UnsignedValue, 1504 kVBCppExprKind_Define, 1505 kVBCppExprKind_End 1506 } VBCPPEXPRKIND; 1507 1508 typedef struct VBCPPEXPR *PVBCPPEXPR; 1509 1510 /** 1511 * Expression parsing structure. 1512 */ 1513 typedef struct VBCPPEXPR 1514 { 1515 /** Pointer to the first byte of the expression. */ 1516 const char *pchExpr; 1517 /** The length of the expression. */ 1518 size_t cchExpr; 1519 1520 uint32_t iDepth; 1521 /** The kind of expression. */ 1522 VBCPPEXPRKIND enmKind; 1523 /** */ 1524 union 1525 { 1526 struct 1527 { 1528 VBCPPUNARYOP enmOperator; 1529 PVBCPPEXPR pArg; 1530 } Unary; 1531 1532 struct 1533 { 1534 VBCPPBINARYOP enmOperator; 1535 PVBCPPEXPR pLeft; 1536 PVBCPPEXPR pRight; 1537 } Binary; 1538 1539 struct 1540 { 1541 int64_t s64; 1542 unsigned cBits; 1543 } SignedValue; 1544 1545 struct 1546 { 1547 uint64_t u64; 1548 unsigned cBits; 1549 } UnsignedValue; 1550 1551 struct 1552 { 1553 const char *pch; 1554 size_t cch; 1555 } Define; 1556 1557 } u; 1558 /** Parent expression. */ 1559 PVBCPPEXPR pParent; 1560 } VBCPPEXPR; 1561 1562 1563 1564 typedef struct VBCPPEXPRPARSER 1565 { 1566 PVBCPPEXPR pStack 1567 } VBCPPEXPRPARSER; 1568 1569 1570 /** 1571 * Operator return statuses. 1572 */ 1573 typedef enum 1574 { 1575 kExprRet_Error = -1, 1576 kExprRet_Ok = 0, 1577 kExprRet_Operator, 1578 kExprRet_Operand, 1579 kExprRet_EndOfExpr, 1580 kExprRet_End 1581 } VBCPPEXPRRET; 1582 1583 1584 static VBCPPEXPRRET vbcppExprEatUnaryOrOperand(PVBCPPEXPRPARSER pThis, PSCMSTREAM pStrmInput) 1585 { 1586 1587 } 1588 1589 #endif 1590 1591 1592 /** 1593 * Evalutes the expression. 1594 * 1595 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1596 * @param pThis The C preprocessor instance. 1597 * @param pszExpr The expression. 1598 * @param cchExpr The length of the expression. 1599 * @param penmResult Where to store the result. 1600 */ 1601 static RTEXITCODE vbcppExprEval(PVBCPP pThis, char *pszExpr, size_t cchExpr, VBCPPEVAL *penmResult) 1602 { 1603 Assert(strlen(pszExpr) == cchExpr); 1604 #if 0 1605 /** @todo */ 1606 #else /* Greatly simplified for getting DTrace working. */ 1607 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 1608 if (strcmp(pszExpr, "1")) 1609 *penmResult = kVBCppEval_True; 1610 else if (strcmp(pszExpr, "0")) 1611 *penmResult = kVBCppEval_False; 1612 else if (pThis->fUndecidedConditionals) 1613 *penmResult = kVBCppEval_Undecided; 1614 else 1615 rcExit = vbcppError(pThis, "Too compliated expression '%s'", pszExpr); 1616 #endif 1617 return rcExit; 1618 } 1619 1620 1621 /** 1622 * Expands known macros in the expression. 1623 * 1624 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1625 * @param pThis The C preprocessor instance. 1626 * @param ppszExpr The expression to expand. Input/Output. 1627 * @param pcchExpr The length of the expression. Input/Output. 1628 * @param pcReplacements Where to store the number of replacements made. 1629 * Optional. 1630 */ 1631 static RTEXITCODE vbcppExprExpand(PVBCPP pThis, char **ppszExpr, size_t *pcchExpr, size_t *pcReplacements) 1632 { 1633 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 1634 char *pszExpr = *ppszExpr; 1635 size_t cchExpr = pcchExpr ? *pcchExpr : strlen(pszExpr); 1636 size_t cbExprAlloc = cchExpr + 1; 1637 size_t cHits = 0; 1638 size_t off = 0; 1639 char ch; 1640 while ((ch = pszExpr[off]) != '\0') 1641 { 1642 if (!vbcppIsCIdentifierLeadChar(ch)) 1643 off++; 1644 else 1645 { 1646 /* Extract the identifier. */ 1647 size_t const offIdentifier = off++; 1648 while ( off < cchExpr 1649 && vbcppIsCIdentifierChar(pszExpr[off])) 1650 off++; 1651 size_t const cchIdentifier = off - offIdentifier; 1652 1653 /* Does it exist? Will save a whole lot of trouble if it doesn't. */ 1654 PVBCPPDEF pDef = vbcppDefineLookup(pThis, &pszExpr[offIdentifier], cchIdentifier); 1655 if (pDef) 1656 { 1657 /* Skip white space and check for parenthesis. */ 1658 while ( off < cchExpr 1659 && RT_C_IS_SPACE(pszExpr[off])) 1660 off++; 1661 if ( off < cchExpr 1662 && pszExpr[off] == '(') 1663 { 1664 /* Try expand function define. */ 1665 rcExit = vbcppError(pThis, "Expanding function macros is not yet implemented"); 1666 break; 1667 } 1668 else 1669 { 1670 /* Expand simple define if found. */ 1671 if (pDef->cchValue + 2 < cchIdentifier) 1672 { 1673 size_t offDelta = cchIdentifier - pDef->cchValue - 2; 1674 memmove(&pszExpr[offIdentifier], &pszExpr[offIdentifier + offDelta], 1675 cchExpr - offIdentifier - offDelta + 1); /* Lazy bird is moving too much! */ 1676 cchExpr -= offDelta; 1677 } 1678 else if (pDef->cchValue + 2 > cchIdentifier) 1679 { 1680 size_t offDelta = pDef->cchValue + 2 - cchIdentifier; 1681 if (cchExpr + offDelta + 1 > cbExprAlloc) 1682 { 1683 do 1684 { 1685 cbExprAlloc *= 2; 1686 } while (cchExpr + offDelta + 1 > cbExprAlloc); 1687 void *pv = RTMemRealloc(pszExpr, cbExprAlloc); 1688 if (!pv) 1689 { 1690 rcExit = vbcppError(pThis, "out of memory (%zu bytes)", cbExprAlloc); 1691 break; 1692 } 1693 pszExpr = (char *)pv; 1694 } 1695 memmove(&pszExpr[offIdentifier + offDelta], &pszExpr[offIdentifier], 1696 cchExpr - offIdentifier + 1); /* Lazy bird is moving too much! */ 1697 cchExpr += offDelta; 1698 } 1699 1700 /* Insert with spaces around it. Not entirely sure how 1701 standard compliant this is... */ 1702 pszExpr[offIdentifier] = ' '; 1703 memcpy(&pszExpr[offIdentifier + 1], pDef->szValue, pDef->cchValue); 1704 pszExpr[offIdentifier + 1 + pDef->cchValue] = ' '; 1705 1706 /* Restart parsing at the inserted macro. */ 1707 off = offIdentifier + 1; 1708 } 1709 } 1710 } 1711 } 1712 1713 return rcExit; 1714 } 1715 1716 1717 1718 /** 1719 * Extracts the expression. 1720 * 1721 * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE+msg. 1722 * @param pThis The C preprocessor instance. 1723 * @param pStrmInput The input stream. 1724 * @param ppszExpr Where to return the expression string.. 1725 * @param pcchExpr Where to return the expression length. 1726 * Optional. 1727 * @param poffComment Where to note down the position of the final 1728 * comment. Optional. 1729 */ 1730 static RTEXITCODE vbcppExprExtract(PVBCPP pThis, PSCMSTREAM pStrmInput, 1731 char **ppszExpr, size_t *pcchExpr, size_t *poffComment) 1732 { 1733 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 1734 size_t cbExprAlloc = 0; 1735 size_t cchExpr = 0; 1736 char *pszExpr = NULL; 1737 bool fInComment = false; 1738 size_t offComment = ~(size_t)0; 1739 unsigned chPrev = 0; 1740 unsigned ch; 1741 while ((ch = ScmStreamPeekCh(pStrmInput)) != ~(unsigned)0) 1742 { 1743 if (ch == '\r' || ch == '\n') 1744 { 1745 if (chPrev == '\\') 1746 { 1747 ScmStreamSeekByLine(pStrmInput, ScmStreamTellLine(pStrmInput) + 1); 1748 pszExpr[--cchExpr] = '\0'; 1749 continue; 1750 } 1751 if (!fInComment) 1752 break; 1753 /* The expression continues after multi-line comments. Cool. :-) */ 1754 } 1755 else if (!fInComment) 1756 { 1757 if (chPrev == '/' && ch == '*' ) 1758 { 1759 pszExpr[--cchExpr] = '\0'; 1760 fInComment = true; 1761 offComment = ScmStreamTell(pStrmInput) - 1; 1762 } 1763 else if (chPrev == '/' && ch == '/') 1764 { 1765 offComment = ScmStreamTell(pStrmInput) - 1; 1766 rcExit = vbcppProcessSkipWhiteEscapedEolAndComments(pThis, pStrmInput); 1767 break; /* done */ 1768 } 1769 /* Append the char to the expression. */ 1770 else 1771 { 1772 if (cchExpr + 2 > cbExprAlloc) 1773 { 1774 cbExprAlloc = cbExprAlloc ? cbExprAlloc * 2 : 8; 1775 void *pv = RTMemRealloc(pszExpr, cbExprAlloc); 1776 if (!pv) 1777 { 1778 rcExit = vbcppError(pThis, "out of memory (%zu bytes)", cbExprAlloc); 1779 break; 1780 } 1781 pszExpr = (char *)pv; 1782 } 1783 pszExpr[cchExpr++] = ch; 1784 pszExpr[cchExpr] = '\0'; 1785 } 1786 } 1787 else if (ch == '/' && chPrev == '*') 1788 fInComment = false; 1789 1790 /* advance */ 1791 chPrev = ch; 1792 ch = ScmStreamGetCh(pStrmInput); Assert(ch == chPrev); 1793 } 1794 1795 if (rcExit == RTEXITCODE_SUCCESS) 1796 { 1797 *ppszExpr = pszExpr; 1798 if (pcchExpr) 1799 *pcchExpr = cchExpr; 1800 if (poffComment) 1801 *poffComment; 1802 } 1803 else 1804 RTMemFree(pszExpr); 1805 return rcExit; 1806 } 1807 1808 1463 1809 /** 1464 1810 * Processes a abbreviated line number directive. … … 1469 1815 * @param offStart The stream position where the directive 1470 1816 * started (for pass thru). 1471 */ 1472 static RTEXITCODE vbcppProcessIf(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart) 1473 { 1474 return vbcppError(pThis, "Not implemented %s", __FUNCTION__); 1817 * @param enmKind The kind of directive we're processing. 1818 */ 1819 static RTEXITCODE vbcppProcessIfOrElif(PVBCPP pThis, PSCMSTREAM pStrmInput, size_t offStart, 1820 VBCPPCONDKIND enmKind) 1821 { 1822 /* 1823 * Check for missing #if if #elif. 1824 */ 1825 if ( enmKind == kVBCppCondKind_ElIf 1826 && !pThis->pCondStack ) 1827 return vbcppError(pThis, "#elif without #if"); 1828 1829 /* 1830 * Extract and expand the expression string. 1831 */ 1832 const char *pchCondition = ScmStreamGetCur(pStrmInput); 1833 char *pszExpr; 1834 size_t cchExpr; 1835 size_t offComment; 1836 RTEXITCODE rcExit = vbcppExprExtract(pThis, pStrmInput, &pszExpr, &cchExpr, &offComment); 1837 if (rcExit == RTEXITCODE_SUCCESS) 1838 { 1839 size_t const cchCondition = ScmStreamGetCur(pStrmInput) - pchCondition; 1840 size_t cReplacements; 1841 rcExit = vbcppExprExpand(pThis, &pszExpr, &cchExpr, &cReplacements); 1842 if (rcExit == RTEXITCODE_SUCCESS) 1843 { 1844 /* 1845 * Strip it and check that it's not empty. 1846 */ 1847 char *pszExpr2 = pszExpr; 1848 while (cchExpr > 0 && RT_C_IS_SPACE(*pszExpr2)) 1849 pszExpr2++, cchExpr--; 1850 1851 while (cchExpr > 0 && RT_C_IS_SPACE(pszExpr2[cchExpr - 1])) 1852 pszExpr2[--cchExpr] = '\0'; 1853 if (cchExpr) 1854 { 1855 /* 1856 * Now, evalute the expression. 1857 */ 1858 VBCPPEVAL enmResult; 1859 rcExit = vbcppExprEval(pThis, pszExpr2, cchExpr, &enmResult); 1860 if (rcExit == RTEXITCODE_SUCCESS) 1861 { 1862 /* 1863 * Take action. 1864 */ 1865 if (enmKind != kVBCppCondKind_ElIf) 1866 rcExit = vbcppCondPush(pThis, pStrmInput, offComment, enmKind, enmResult, 1867 pchCondition, cchCondition); 1868 else 1869 { 1870 PVBCPPCOND pCond = pThis->pCondStack; 1871 if ( pCond->enmResult != kVBCppEval_Undecided 1872 && ( !pCond->pUp 1873 || pCond->pUp->enmStackResult == kVBCppEval_True)) 1874 { 1875 if (enmResult == kVBCppEval_True) 1876 pCond->enmStackResult = kVBCppEval_False; 1877 else 1878 pCond->enmStackResult = kVBCppEval_True; 1879 pThis->fIf0Mode = pCond->enmStackResult == kVBCppEval_False; 1880 } 1881 pCond->enmResult = enmResult; 1882 pCond->pchCond = pchCondition; 1883 pCond->cchCond = cchCondition; 1884 1885 /* 1886 * Do #elif pass thru. 1887 */ 1888 if ( !pThis->fIf0Mode 1889 && pCond->enmResult == kVBCppEval_Undecided) 1890 { 1891 ssize_t cch = ScmStreamPrintf(&pThis->StrmOutput, "#%*selif", pCond->iKeepLevel - 1, ""); 1892 if (cch > 0) 1893 rcExit = vbcppOutputComment(pThis, pStrmInput, offStart, cch, 2); 1894 else 1895 rcExit = vbcppError(pThis, "Output error %Rrc", (int)cch); 1896 } 1897 } 1898 } 1899 } 1900 else 1901 rcExit = vbcppError(pThis, "Empty #if expression"); 1902 } 1903 RTMemFree(pszExpr); 1904 } 1905 return rcExit; 1475 1906 } 1476 1907 … … 1506 1937 if (vbcppDefineExists(pThis, pchDefine, cchDefine)) 1507 1938 enmEval = kVBCppEval_True; 1508 else if ( pThis->fUndecidedConditionals1939 else if ( !pThis->fUndecidedConditionals 1509 1940 || RTStrSpaceGetN(&pThis->UndefStrSpace, pchDefine, cchDefine) != NULL) 1510 1941 enmEval = kVBCppEval_False; … … 1552 1983 if (vbcppDefineExists(pThis, pchDefine, cchDefine)) 1553 1984 enmEval = kVBCppEval_False; 1554 else if ( pThis->fUndecidedConditionals1985 else if ( !pThis->fUndecidedConditionals 1555 1986 || RTStrSpaceGetN(&pThis->UndefStrSpace, pchDefine, cchDefine) != NULL) 1556 1987 enmEval = kVBCppEval_True; … … 1887 2318 #define IS_DIRECTIVE(a_sz) ( sizeof(a_sz) - 1 == cchDirective && strncmp(pchDirective, a_sz, sizeof(a_sz) - 1) == 0) 1888 2319 if (IS_DIRECTIVE("if")) 1889 rcExit = vbcppProcessIf(pThis, pStrmInput, offStart); 2320 rcExit = vbcppProcessIfOrElif(pThis, pStrmInput, offStart, kVBCppCondKind_If); 2321 else if (IS_DIRECTIVE("elif")) 2322 rcExit = vbcppProcessIfOrElif(pThis, pStrmInput, offStart, kVBCppCondKind_ElIf); 1890 2323 else if (IS_DIRECTIVE("ifdef")) 1891 2324 rcExit = vbcppProcessIfDef(pThis, pStrmInput, offStart);
Note:
See TracChangeset
for help on using the changeset viewer.