Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

575 lines
14 KiB

4 years ago
  1. /*----------------------------------------------------------------------------
  2. * *
  3. * PARSEBLD.C *
  4. * *
  5. * Copyright (C) Microsoft Corporation 1989. *
  6. * All Rights reserved. *
  7. * *
  8. *----------------------------------------------------------------------------*
  9. * *
  10. * Program Description: *
  11. * This contains the function related to building the Build Expression *
  12. * from string(i.e reverse polish expression ) and evaluating Build *
  13. * expression( i.e reverse polish expression. ) *
  14. * *
  15. * *
  16. *----------------------------------------------------------------------------*
  17. * *
  18. * Revision History: *
  19. * *
  20. * *
  21. *----------------------------------------------------------------------------*
  22. * *
  23. * Known Bugs: *
  24. * *
  25. *---------------------------------------------------------------------------*/
  26. #include "stdafx.h"
  27. #pragma hdrstop
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. const int MAX_STACK = 30;
  33. const int MAX_POLISH = 30;
  34. const int MAX_BUILDTAG = 32;
  35. const int MAX_FOOTBLDTAGS = 30;
  36. typedef enum {
  37. tokOpenBrace,
  38. tokCloseBrace,
  39. tokTag,
  40. tokAnd,
  41. tokOr,
  42. tokNot,
  43. tokVoidToken,
  44. tokValidToken,
  45. tokInvalidToken,
  46. } TOKEN;
  47. #define VALID_EXPRESSION TRUE
  48. #define INVALID_EXPRESSION FALSE
  49. // Rank values for different token
  50. static int rgiRankValue[] = { // Rank Table
  51. 0, // OPENBARCE
  52. 0, // CLOSEBRACE
  53. 1, // TAG
  54. -1, // AND
  55. -1, // OR
  56. 0 // NOT
  57. };
  58. typedef int PREC;
  59. typedef struct{
  60. PREC precInput;
  61. PREC precOutput;
  62. } PRECENT, * QPRECENT;
  63. // Input/Output precedence of various operators
  64. static PRECENT PrecTab[] = {
  65. 9, 0, // OPENBARCE
  66. 0, 0, // CLOSEBRACE
  67. 7, 8, // TAG
  68. 3, 4, // AND
  69. 1, 2, // OR
  70. 6, 5 // NOT , right to left
  71. };
  72. typedef struct ENTRY {
  73. TOKEN tok;
  74. int iTokValue;
  75. } STACK, * PSTACK;
  76. static STACK rgstackPolish[MAX_POLISH];
  77. static int iPolishTop;
  78. static PSTR szExpPtr;
  79. static INLINE BOOL FGetStackTop(PSTACK, int, PSTACK);
  80. static INLINE BOOL FMatchTag(int, int*, int);
  81. static INLINE BOOL FOutToPolishExp(PSTACK);
  82. static BOOL FPopStack(PSTACK, int*, PSTACK);
  83. static BOOL FPushStack(PSTACK, int*, PSTACK);
  84. static INLINE PREC PrecForTok(TOKEN, BOOL);
  85. static INLINE TOKEN TokDoToken(int);
  86. static TOKEN TokGetBldToken(int*);
  87. /*-----------------------------------------------------------------------------
  88. * FBuildPolishExpFromSz()
  89. *
  90. * Description:
  91. * This function builds the reversh polish expression from the given
  92. * string. If it is a valid expression, returns TRUE else returns FALSE.
  93. *
  94. * Arguments:
  95. * Build expression string.
  96. *
  97. * Returns;
  98. * TRUE, if a valid expression.
  99. * else FALSE
  100. *-----------------------------------------------------------------------------*/
  101. BOOL STDCALL FBuildPolishExpFromSz(PSTR szExp)
  102. {
  103. int iTokValue, iBldRank, iRetVal = VALID_EXPRESSION;
  104. int iStackTop;
  105. TOKEN tok;
  106. PREC precCur, precStackTop;
  107. STACK rgstackBld[MAX_STACK], stackTemp;
  108. PSTACK pstackTemp = &stackTemp;
  109. szExpPtr = szExp; // initialise line pointer
  110. strcat(szExp, ")"); // append the close brace to expression
  111. // Initialize stack and rank
  112. iPolishTop = iStackTop = iBldRank = 0;
  113. pstackTemp->tok = tokOpenBrace;
  114. pstackTemp -> iTokValue = '(';
  115. FPushStack(rgstackBld, &iStackTop, pstackTemp);
  116. while(iRetVal == VALID_EXPRESSION) {
  117. tok = TokGetBldToken(&iTokValue);
  118. if (tok == tokVoidToken)
  119. break;
  120. else if (tok != tokInvalidToken) {
  121. if (iStackTop < 1)
  122. iRetVal = INVALID_EXPRESSION;
  123. else {
  124. precCur = PrecForTok(tok, TRUE); // Get input precedence
  125. while(TRUE) {
  126. FGetStackTop(rgstackBld, iStackTop, pstackTemp);
  127. precStackTop = PrecForTok(pstackTemp->tok, FALSE);
  128. // Output prec
  129. if (precCur >= precStackTop)
  130. break;
  131. if (!FPopStack(rgstackBld, &iStackTop, pstackTemp))
  132. return(INVALID_EXPRESSION);
  133. if (!FOutToPolishExp(pstackTemp)) {
  134. VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
  135. return(INVALID_EXPRESSION);
  136. }
  137. iBldRank += rgiRankValue[pstackTemp->tok];
  138. if (iBldRank < 1) {
  139. iRetVal = INVALID_EXPRESSION;
  140. break;
  141. }
  142. }
  143. if (iRetVal != INVALID_EXPRESSION) {
  144. // Check for matching parentheses
  145. if (precCur != precStackTop) {
  146. pstackTemp->tok = tok;
  147. pstackTemp->iTokValue = iTokValue;
  148. if (!FPushStack(rgstackBld, &iStackTop, pstackTemp)) {
  149. VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
  150. return(INVALID_EXPRESSION);
  151. }
  152. }
  153. else {
  154. if (!FPopStack(rgstackBld, &iStackTop, pstackTemp))
  155. return(INVALID_EXPRESSION);
  156. }
  157. }
  158. }
  159. }
  160. else
  161. iRetVal = INVALID_EXPRESSION;
  162. }
  163. // Check for validation of expression
  164. if (iRetVal != INVALID_EXPRESSION) {
  165. if (iStackTop != 0 || iBldRank != 1)
  166. iRetVal = INVALID_EXPRESSION;
  167. }
  168. return iRetVal;
  169. }
  170. /*-----------------------------------------------------------------------------
  171. * PrecForToken()
  172. *
  173. * Description:
  174. * This function returns the input/output precedence of the given
  175. * depending on the flag.
  176. *
  177. * Arguments:
  178. * 1. tok - token type.
  179. * 2. fInput - if TRUE, return input precedence.
  180. * else return FALSE.
  181. *
  182. * Returns;
  183. * precedence value for the given token.
  184. *-----------------------------------------------------------------------------*/
  185. static INLINE PREC PrecForTok(TOKEN tok, BOOL fInput)
  186. {
  187. PRECENT* qprecTemp = &(PrecTab[tok]);
  188. if (fInput)
  189. return qprecTemp->precInput;
  190. else
  191. return qprecTemp->precOutput;
  192. }
  193. /*-----------------------------------------------------------------------------
  194. * FPushStack()
  195. *
  196. * Description:
  197. * This function stores the info about the token into the stack table in
  198. * the ith entry and increments the table index for the next free entry.
  199. *
  200. * Arguments:
  201. *
  202. * Returns;
  203. * precedence value for the given token.
  204. *-----------------------------------------------------------------------------*/
  205. static BOOL FPushStack(PSTACK qstackTab, int* qiTop, PSTACK qstackInfo)
  206. {
  207. if (*qiTop < MAX_STACK) {
  208. memcpy((qstackTab + *qiTop), qstackInfo, sizeof(STACK));
  209. (*qiTop) ++;
  210. return TRUE;
  211. }
  212. else
  213. return FALSE;
  214. }
  215. /*-----------------------------------------------------------------------------
  216. * FPopStack()
  217. *
  218. * Description:
  219. * This function returns the info about the token from the stack table
  220. * for the ith entry and decrements the table index pointing to the next
  221. * valid entry.
  222. *
  223. * Arguments:
  224. *
  225. * Returns;
  226. * precedence value for the given token.
  227. *-----------------------------------------------------------------------------*/
  228. static BOOL FPopStack(PSTACK qstackTab, int* qiTop, PSTACK qstackInfo)
  229. {
  230. if (*qiTop > 0) {
  231. (*qiTop) --;
  232. memcpy(qstackInfo, (qstackTab + *qiTop), sizeof(STACK));
  233. return TRUE;
  234. }
  235. else
  236. return FALSE;
  237. }
  238. /*-----------------------------------------------------------------------------
  239. * FGetStackTop()
  240. *
  241. * Description:
  242. * This function returns the info from the ith entry of the stack
  243. * table.
  244. *
  245. * Arguments:
  246. *
  247. * Returns;
  248. * precedence value for the given token.
  249. *-----------------------------------------------------------------------------*/
  250. static INLINE BOOL FGetStackTop(PSTACK qstackTab, int iTop, PSTACK qstackInfo)
  251. {
  252. if (iTop > 0) {
  253. memcpy(qstackInfo, (qstackTab + (iTop-1)), sizeof(STACK));
  254. return TRUE;
  255. }
  256. else
  257. return FALSE;
  258. }
  259. /*-----------------------------------------------------------------------------
  260. * TokGetBldToken()
  261. *
  262. * Description:
  263. * This function returns the token and token value by scanning the
  264. * footnote string pointed by the global variable szExpPtr.
  265. *
  266. * Arguments:
  267. *
  268. * Returns;
  269. * precedence value for the given token.
  270. *-----------------------------------------------------------------------------*/
  271. static TOKEN TokGetBldToken(int* pTokValue)
  272. {
  273. int iTemp;
  274. TOKEN tok;
  275. BOOL fContinue = TRUE, fSpecialToken = TRUE;
  276. char szBuildToken[256];
  277. PSTR pszToken;
  278. pszToken = szBuildToken;
  279. *pTokValue = -1;
  280. ASSERT(szExpPtr);
  281. szExpPtr = FirstNonSpace(szExpPtr, options.fDBCS); // skip the leading blanks
  282. if (*szExpPtr == '\0')
  283. return(tokVoidToken);
  284. while (fContinue) {
  285. switch(iTemp = *szExpPtr++) {
  286. case '&':
  287. case '|':
  288. case '~':
  289. case '(':
  290. case ')':
  291. case ' ':
  292. case '\n':
  293. case '\t':
  294. if (fSpecialToken) {
  295. *pTokValue = iTemp;
  296. tok = TokDoToken(iTemp);
  297. }
  298. else { // return the token
  299. tok = tokTag;
  300. szExpPtr--;
  301. }
  302. fContinue = FALSE;
  303. break;
  304. default:
  305. *pszToken++ = CharAnsiUpper(iTemp);
  306. fSpecialToken = FALSE;
  307. break;
  308. }
  309. }
  310. *pszToken = '\0';
  311. if (tok == tokTag) {
  312. // Is the string token valid?
  313. if (!ptblBuildtags ||
  314. !(*pTokValue = ptblBuildtags->IsStringInTable(szBuildToken)))
  315. tok = tokInvalidToken;
  316. }
  317. return(tok);
  318. }
  319. /*-----------------------------------------------------------------------------
  320. * TokDoToken()
  321. *
  322. * Description:
  323. * This function returns the token for the given integer value.
  324. *
  325. * Arguments:
  326. *
  327. * Returns;
  328. * precedence value for the given token.
  329. *-----------------------------------------------------------------------------*/
  330. static INLINE TOKEN TokDoToken(int iTokenValue)
  331. {
  332. switch(iTokenValue) {
  333. case '&':
  334. return tokAnd;
  335. case '|':
  336. return tokOr;
  337. case '~':
  338. return tokNot;
  339. case '(':
  340. return tokOpenBrace;
  341. case ')':
  342. return tokCloseBrace;
  343. default:
  344. return tokInvalidToken;
  345. }
  346. }
  347. /*-----------------------------------------------------------------------------
  348. * FOutPolishExp()
  349. *
  350. * Description:
  351. * This function pushes the stack info into the output polish stack and
  352. * increments the stack pointer.
  353. *
  354. * Arguments:
  355. *
  356. * Returns;
  357. * precedence value for the given token.
  358. *-----------------------------------------------------------------------------*/
  359. static INLINE BOOL FOutToPolishExp(PSTACK qstackInfo)
  360. {
  361. if (iPolishTop < MAX_STACK) {
  362. memcpy(&(rgstackPolish[iPolishTop]), qstackInfo, sizeof(STACK));
  363. iPolishTop++;
  364. return TRUE;
  365. }
  366. else
  367. return FALSE;
  368. }
  369. /***************************************************************************
  370. *
  371. - Name: FEvalBldExpSz
  372. -
  373. * Purpose:
  374. * Evaluates the build expression for the given list of build tags.
  375. *
  376. * Arguments:
  377. * pszTag: Semicolon separated list of build tags.
  378. * perr: Pointer to error information. NULL if errors are not
  379. * to be printed.
  380. *
  381. * Returns:
  382. * Result of evaluating the build expression with the given build tags.
  383. *
  384. * Globals:
  385. * Accesses global build expression stack.
  386. *
  387. ***************************************************************************/
  388. // REVIEW: 02-Sep-1993 [ralphw] This is pretty screwy. Rewrite when we
  389. // have a sample file to test it on.
  390. BOOL STDCALL FEvalBldExpSz(PSTR pszTag, PERR perr)
  391. {
  392. TOKEN tok;
  393. int iCount, iTokValue, iT, iEvalTop = 0, iInpBldTag;
  394. STACK rgstackEval[MAX_STACK], stackInfo1, stackInfo2;
  395. PSTACK qstackInfo1, qstackInfo2;
  396. int rgiTag[MAX_FOOTBLDTAGS], iInpTagCount = 0;
  397. int* qiTag;
  398. char szTagBuf[MAX_BUILDTAG + 1];
  399. if (fBldChk == -1) // invalid build expression
  400. return TRUE;
  401. if (!fBldChk) {
  402. if (perr != NULL)
  403. VReportError(HCERR_BUILD_MISSING, &errHpj);
  404. fBldChk = -1; // Don't give multiple error messages
  405. return TRUE; // no Build check is to be made
  406. }
  407. if (!ptblBuildtags) {
  408. if (perr != NULL)
  409. VReportError(HCERR_BUILD_TAG_MISSING, &errHpj);
  410. return TRUE;
  411. }
  412. while(*pszTag) {
  413. pszTag = SzGetKeySz(pszTag, szTagBuf, MAX_BUILDTAG, &iCount);
  414. if (iCount > MAX_BUILDTAG) {
  415. if (perr != NULL)
  416. VReportError(HCERR_BUILD_TAG_TOO_LONG, &errHpj, pszTag);
  417. continue;
  418. }
  419. iInpBldTag = ptblBuildtags->IsStringInTable(szTagBuf);
  420. if (!iInpBldTag) {
  421. if (perr != NULL)
  422. VReportError(HCERR_BUILD_ERROR, &errHpj);
  423. }
  424. else {
  425. // See if the build tag is not duplicated in the build footnote
  426. for (iT = 0, qiTag = rgiTag; iT < iInpTagCount; qiTag++, iT++) {
  427. if (*qiTag == iInpBldTag)
  428. break;
  429. }
  430. if (iInpTagCount >= MAX_FOOTBLDTAGS) {
  431. VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
  432. return FALSE;
  433. }
  434. if (iT == iInpTagCount)
  435. rgiTag[iInpTagCount++] = iInpBldTag;
  436. }
  437. }
  438. if (!iInpTagCount)
  439. return TRUE;
  440. qstackInfo1 = &stackInfo1;
  441. qstackInfo2 = &stackInfo2;
  442. for (iT = 1; iT <= iPolishTop; iT++) {
  443. FGetStackTop(rgstackPolish, iT, qstackInfo1);
  444. switch(qstackInfo1 -> tok) {
  445. case tokTag:
  446. qstackInfo1 -> iTokValue = FMatchTag(qstackInfo1 -> iTokValue,
  447. rgiTag, iInpTagCount);
  448. if (!FPushStack(rgstackEval, &iEvalTop, qstackInfo1)) {
  449. ASSERT(FALSE);
  450. VReportError(HCERR_BUILD_TOO_COMPLEX, &errHpj);
  451. return FALSE;
  452. }
  453. break;
  454. case tokNot:
  455. if (!FPopStack(rgstackEval, &iEvalTop, qstackInfo2))
  456. ASSERT(FALSE);
  457. ASSERT(qstackInfo2 -> tok == tokTag);
  458. if (qstackInfo2 -> iTokValue)
  459. qstackInfo2 -> iTokValue = FALSE;
  460. else qstackInfo2 -> iTokValue = TRUE;
  461. if (!FPushStack(rgstackEval, &iEvalTop, qstackInfo2))
  462. ASSERT(FALSE);
  463. break;
  464. case tokAnd:
  465. case tokOr:
  466. if (!FPopStack(rgstackEval, &iEvalTop, qstackInfo2))
  467. ASSERT(FALSE);
  468. tok = qstackInfo2 -> tok;
  469. iTokValue = qstackInfo2 -> iTokValue;
  470. ASSERT(tok == tokTag);
  471. if (!FPopStack(rgstackEval, &iEvalTop, qstackInfo2))
  472. ASSERT(FALSE);
  473. if (qstackInfo1 -> tok == tokAnd)
  474. qstackInfo2 -> iTokValue &= iTokValue;
  475. else
  476. qstackInfo2 -> iTokValue |= iTokValue;
  477. if (!FPushStack(rgstackEval, &iEvalTop, qstackInfo2))
  478. ASSERT(FALSE);
  479. break;
  480. default:
  481. break;
  482. }
  483. }
  484. ASSERT(iEvalTop == 1);
  485. ConfirmOrDie(FPopStack(rgstackEval, &iEvalTop, qstackInfo1));
  486. return(qstackInfo1 -> iTokValue);
  487. }
  488. /*-----------------------------------------------------------------------------
  489. * FMatchTag()
  490. *
  491. * Description:
  492. * This function matches the tag with the tag table formed from the
  493. * build tag footnote and returns TRUE if found else returns FALSE.
  494. *
  495. * Arguments:
  496. *
  497. * Returns;
  498. * precedence value for the given token.
  499. *-----------------------------------------------------------------------------*/
  500. static INLINE BOOL FMatchTag(int iTag, int* pTag, int iInpTagCount)
  501. {
  502. for (int i = 0; i < iInpTagCount; i++, pTag++) {
  503. if (*pTag == iTag)
  504. return TRUE;
  505. }
  506. return FALSE;
  507. }