Leaked source code of windows server 2003
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.

1036 lines
36 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. /* macros1.c - functions that implement macros */
  3. #include "gpdparse.h"
  4. // ---- functions defined in macros1.c ---- //
  5. BOOL BevaluateMacros(
  6. PGLOBL pglobl) ;
  7. BOOL BDefineValueMacroName(
  8. PTKMAP pNewtkmap,
  9. DWORD dwNewTKMindex,
  10. PGLOBL pglobl) ;
  11. BOOL BResolveValueMacroReference(
  12. PTKMAP ptkmap,
  13. DWORD dwTKMindex,
  14. PGLOBL pglobl) ;
  15. BOOL BdelimitName(
  16. PABSARRAYREF paarValue, // the remainder of the string without the Name
  17. PABSARRAYREF paarToken, // contains the Name
  18. PBYTE pubChar ) ;
  19. BOOL BCatToTmpHeap(
  20. PABSARRAYREF paarDest,
  21. PABSARRAYREF paarSrc,
  22. PGLOBL pglobl) ;
  23. BOOL BResolveBlockMacroReference(
  24. PTKMAP ptkmap,
  25. DWORD dwMacRefIndex,
  26. PGLOBL pglobl) ;
  27. BOOL BDefineBlockMacroName(
  28. PTKMAP pNewtkmap,
  29. DWORD dwNewTKMindex,
  30. PGLOBL pglobl) ;
  31. BOOL BIncreaseMacroLevel(
  32. BOOL bMacroInProgress,
  33. PGLOBL pglobl) ;
  34. BOOL BDecreaseMacroLevel(
  35. PTKMAP pNewtkmap,
  36. DWORD dwNewTKMindex,
  37. PGLOBL pglobl) ;
  38. VOID VEnumBlockMacro(
  39. PTKMAP pNewtkmap,
  40. PBLOCKMACRODICTENTRY pBlockMacroDictEntry,
  41. PGLOBL pglobl ) ;
  42. // ---------------------------------------------------- //
  43. BOOL BevaluateMacros(
  44. PGLOBL pglobl)
  45. // and expand shortcuts
  46. // this function scans through the tokenMap
  47. // making a copy of the tokenMap without
  48. // the macrodefinitions or references. All references
  49. // are replaced by the definitions inserted in-line!
  50. // This function assumes the temp heap is availible for
  51. // storage of expanded macros.
  52. {
  53. PTKMAP ptkmap, pNewtkmap ; // start of tokenmap
  54. DWORD dwNewTKMindex, dwEntry, dwKeywordID ;
  55. CONSTRUCT eConstruct ;
  56. KEYWORD_TYPE eType ;
  57. BOOL bStatus = TRUE ,
  58. bValueMacroState = FALSE ; // set to TRUE when
  59. // we parse into a *Macros construct.
  60. gMasterTable[MTI_BLOCKMACROARRAY].dwCurIndex =
  61. gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex =
  62. gMasterTable[MTI_MACROLEVELSTACK].dwCurIndex = 0 ;
  63. // to push new values onto stack: write then increment stackptr
  64. // to pop values off the stack: decrement stackptr then read from stack
  65. pNewtkmap = (PTKMAP)gMasterTable[MTI_NEWTOKENMAP].pubStruct ;
  66. ptkmap = (PTKMAP)gMasterTable[MTI_TOKENMAP].pubStruct ;
  67. for(dwEntry = 0 ; geErrorSev < ERRSEV_RESTART ; dwEntry++)
  68. {
  69. // These ID's must be processed separately
  70. // because they do not index into the mainKeyword table.
  71. // The code for generic ID's will fail.
  72. dwKeywordID = ptkmap[dwEntry].dwKeywordID ;
  73. if (dwKeywordID == gdwID_IgnoreBlock)
  74. {
  75. VIgnoreBlock(ptkmap + dwEntry, TRUE, pglobl) ;
  76. continue ;
  77. }
  78. switch(dwKeywordID)
  79. {
  80. case (ID_EOF):
  81. {
  82. {
  83. DWORD dwEntry, dwTKMindex, dwTKIndexOpen, dwTKIndexClose ;
  84. PBLOCKMACRODICTENTRY pBlockMacroDictEntry ;
  85. PVALUEMACRODICTENTRY pValueMacroDictEntry ;
  86. // remove all traces of expired block and value macro definitions
  87. pBlockMacroDictEntry =
  88. (PBLOCKMACRODICTENTRY)gMasterTable[MTI_BLOCKMACROARRAY].pubStruct ;
  89. pValueMacroDictEntry =
  90. (PVALUEMACRODICTENTRY)gMasterTable[MTI_VALUEMACROARRAY].pubStruct ;
  91. for(dwEntry = 0 ;
  92. dwEntry < gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex ;
  93. dwEntry++)
  94. {
  95. dwTKMindex = pValueMacroDictEntry[dwEntry].dwTKIndexValue ;
  96. pNewtkmap[dwTKMindex].dwKeywordID = ID_NULLENTRY ;
  97. }
  98. for(dwEntry = 0 ;
  99. dwEntry < gMasterTable[MTI_BLOCKMACROARRAY].dwCurIndex ;
  100. dwEntry++)
  101. {
  102. dwTKIndexOpen = pBlockMacroDictEntry[dwEntry].dwTKIndexOpen ;
  103. dwTKIndexClose = pBlockMacroDictEntry[dwEntry].dwTKIndexClose ;
  104. for(dwTKMindex = dwTKIndexOpen ; dwTKMindex <= dwTKIndexClose ;
  105. dwTKMindex++)
  106. pNewtkmap[dwTKMindex].dwKeywordID = ID_NULLENTRY ;
  107. }
  108. }
  109. if(gMasterTable[MTI_MACROLEVELSTACK].dwCurIndex)
  110. {
  111. ERR(("Too few closing braces. Fatal syntax error.\n"));
  112. geErrorSev = ERRSEV_FATAL ;
  113. geErrorType = ERRTY_SYNTAX ;
  114. return(FALSE);
  115. }
  116. // transfer all tokenmap fields to newTokenMap
  117. if(!BallocElementFromMasterTable(
  118. MTI_NEWTOKENMAP, &dwNewTKMindex, pglobl) )
  119. {
  120. geErrorSev = ERRSEV_RESTART ;
  121. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  122. gdwMasterTabIndex = MTI_NEWTOKENMAP ;
  123. return(FALSE);
  124. }
  125. pNewtkmap[dwNewTKMindex] = ptkmap[dwEntry] ;
  126. bStatus = (mdwCurStsPtr) ? (FALSE) : (TRUE);
  127. if(geErrorSev >= ERRSEV_RESTART)
  128. bStatus = FALSE ;
  129. return(bStatus) ;
  130. }
  131. case (ID_NULLENTRY):
  132. {
  133. continue ; // skip to next entry.
  134. }
  135. default :
  136. break ;
  137. }
  138. if(bValueMacroState)
  139. {
  140. if(dwKeywordID == ID_UNRECOGNIZED)
  141. {
  142. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  143. ERR(("Only valueMacroDefinitions permitted within *Macros constructs.\n"));
  144. }
  145. else if(dwKeywordID == ID_SYMBOL)
  146. {
  147. // transfer all tokenmap fields to newTokenMap
  148. if(!BallocElementFromMasterTable(
  149. MTI_NEWTOKENMAP, &dwNewTKMindex, pglobl) )
  150. {
  151. geErrorSev = ERRSEV_RESTART ;
  152. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  153. gdwMasterTabIndex = MTI_NEWTOKENMAP ;
  154. continue ;
  155. }
  156. pNewtkmap[dwNewTKMindex] = ptkmap[dwEntry] ;
  157. if(!BDefineValueMacroName(pNewtkmap, dwNewTKMindex, pglobl) )
  158. {
  159. pNewtkmap[dwNewTKMindex].dwKeywordID = ID_NULLENTRY ;
  160. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  161. ERR(("Internal Error: valueMacro name registration failed.\n"));
  162. }
  163. else if(ptkmap[dwEntry].dwFlags & TKMF_MACROREF)
  164. {
  165. if(!BResolveValueMacroReference(pNewtkmap , dwNewTKMindex, pglobl))
  166. {
  167. pNewtkmap[dwNewTKMindex].dwKeywordID = ID_NULLENTRY ;
  168. gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex-- ;
  169. // remove macrodef from dictionary.
  170. }
  171. }
  172. }
  173. else // keywords that should be defined in the MainKeywordTable
  174. {
  175. eType = mMainKeywordTable[dwKeywordID].eType ;
  176. eConstruct = (CONSTRUCT)(mMainKeywordTable[dwKeywordID].dwSubType) ;
  177. if(eType == TY_CONSTRUCT && eConstruct == CONSTRUCT_CLOSEBRACE)
  178. {
  179. bValueMacroState = FALSE ; // just don't copy it.
  180. }
  181. else
  182. {
  183. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  184. ERR(("Only valueMacroDefinitions permitted within *Macros constructs.\n"));
  185. }
  186. }
  187. continue ; // end of processing for this statement
  188. }
  189. // the remainder of the block handles the case
  190. // bValueMacroState = FALSE ;
  191. if(dwKeywordID == ID_UNRECOGNIZED || dwKeywordID == ID_SYMBOL)
  192. {
  193. // Note: currently SYMBOLs only occur within ValueMacro
  194. // constructs so they could be flagged as an error here. But
  195. // let it slide here since one day the parser may allow them
  196. // to be used elsewhere.
  197. // do nothing in this block, just use it to skip to code at the
  198. // bottom after all the else if statements.
  199. ; // empty statement.
  200. }
  201. else // only valid KeywordIDs enter this block.
  202. {
  203. eType = mMainKeywordTable[dwKeywordID].eType ;
  204. eConstruct = (CONSTRUCT)(mMainKeywordTable[dwKeywordID].dwSubType) ;
  205. if(eType == TY_CONSTRUCT && eConstruct == CONSTRUCT_BLOCKMACRO)
  206. {
  207. if(!BDefineBlockMacroName(ptkmap, dwEntry, pglobl))
  208. {
  209. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  210. ERR(("Internal Error: blockMacro name registration failed.\n"));
  211. continue ;
  212. }
  213. // skip NULL_ENTRIES
  214. for( dwEntry++ ; ptkmap[dwEntry].dwKeywordID == ID_NULLENTRY ; dwEntry++)
  215. ;
  216. dwKeywordID = ptkmap[dwEntry].dwKeywordID ;
  217. if(dwKeywordID < ID_SPECIAL)
  218. {
  219. eType = mMainKeywordTable[dwKeywordID].eType ;
  220. eConstruct = (CONSTRUCT)(mMainKeywordTable[dwKeywordID].dwSubType) ;
  221. if(eType == TY_CONSTRUCT && eConstruct == CONSTRUCT_OPENBRACE)
  222. {
  223. PBLOCKMACRODICTENTRY pBlockMacroDictEntry ;
  224. if(!BallocElementFromMasterTable(
  225. MTI_NEWTOKENMAP, &dwNewTKMindex, pglobl) )
  226. {
  227. geErrorSev = ERRSEV_RESTART ;
  228. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  229. gdwMasterTabIndex = MTI_NEWTOKENMAP ;
  230. continue ;
  231. }
  232. pNewtkmap[dwNewTKMindex] = ptkmap[dwEntry] ;
  233. pBlockMacroDictEntry =
  234. (PBLOCKMACRODICTENTRY)gMasterTable[MTI_BLOCKMACROARRAY].pubStruct ;
  235. pBlockMacroDictEntry[gMasterTable[MTI_BLOCKMACROARRAY].dwCurIndex - 1].dwTKIndexOpen =
  236. dwNewTKMindex ;
  237. BIncreaseMacroLevel(TRUE, pglobl) ;
  238. continue ; // end of processing for this statement
  239. }
  240. }
  241. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  242. ERR(("expected openbrace to follow *BlockMacros keyword.\n"));
  243. geErrorType = ERRTY_SYNTAX ;
  244. geErrorSev = ERRSEV_FATAL ;
  245. continue ; // end of processing for this statement
  246. }
  247. else if(eType == TY_SPECIAL && eConstruct == SPEC_INSERTBLOCK)
  248. {
  249. if(ptkmap[dwEntry].dwFlags & TKMF_MACROREF)
  250. {
  251. if(!BResolveBlockMacroReference(ptkmap, dwEntry, pglobl))
  252. {
  253. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  254. ERR((" *InsertBlockMacro Construct ignored.\n"));
  255. VIgnoreBlock(ptkmap + dwEntry, TRUE, pglobl) ;
  256. }
  257. }
  258. else
  259. {
  260. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  261. ERR(("expected a =MacroName as the value of *InsertBlockMacro keyword.\n"));
  262. ERR((" *InsertBlockMacro Construct ignored.\n"));
  263. VIgnoreBlock(ptkmap + dwEntry, TRUE, pglobl) ;
  264. }
  265. continue ; // end of processing for this statement
  266. }
  267. else if(eType == TY_CONSTRUCT && eConstruct == CONSTRUCT_MACROS)
  268. { // *Macros definition
  269. dwEntry++; // don't copy *Macros statement
  270. while(ptkmap[dwEntry].dwKeywordID == ID_NULLENTRY)
  271. dwEntry++; // skip NULL_ENTRIES
  272. dwKeywordID = ptkmap[dwEntry].dwKeywordID ;
  273. if(dwKeywordID < ID_SPECIAL)
  274. {
  275. eType = mMainKeywordTable[dwKeywordID].eType ;
  276. eConstruct = (CONSTRUCT)(mMainKeywordTable[dwKeywordID].dwSubType) ;
  277. if(eType == TY_CONSTRUCT && eConstruct == CONSTRUCT_OPENBRACE)
  278. {
  279. // don't copy openbrace
  280. bValueMacroState = TRUE ;
  281. continue ; // end of processing for this statement
  282. }
  283. }
  284. vIdentifySource(ptkmap + dwEntry, pglobl) ;
  285. ERR(("expected openbrace to follow *Macros keyword.\n"));
  286. geErrorType = ERRTY_SYNTAX ;
  287. geErrorSev = ERRSEV_FATAL ;
  288. continue ; // end of processing for this statement
  289. }
  290. else if(eType == TY_CONSTRUCT && eConstruct == CONSTRUCT_OPENBRACE)
  291. {
  292. if(!BallocElementFromMasterTable(
  293. MTI_NEWTOKENMAP, &dwNewTKMindex, pglobl) )
  294. {
  295. geErrorSev = ERRSEV_RESTART ;
  296. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  297. gdwMasterTabIndex = MTI_NEWTOKENMAP ;
  298. }
  299. pNewtkmap[dwNewTKMindex] = ptkmap[dwEntry] ;
  300. BIncreaseMacroLevel(FALSE, pglobl) ;
  301. continue ; // end of processing for this statement
  302. }
  303. else if(eType == TY_CONSTRUCT && eConstruct == CONSTRUCT_CLOSEBRACE)
  304. {
  305. if(!BallocElementFromMasterTable(
  306. MTI_NEWTOKENMAP, &dwNewTKMindex, pglobl) )
  307. {
  308. geErrorSev = ERRSEV_RESTART ;
  309. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  310. gdwMasterTabIndex = MTI_NEWTOKENMAP ;
  311. }
  312. pNewtkmap[dwNewTKMindex] = ptkmap[dwEntry] ;
  313. BDecreaseMacroLevel(pNewtkmap, dwNewTKMindex, pglobl) ;
  314. continue ; // end of processing for this statement
  315. }
  316. }
  317. // execution path for ID_UNRECOGNIZED and ID_SYMBOL
  318. // rejoins here. This code is executed only if
  319. // keyword was not processed in the special cases above.
  320. // transfer all tokenmap fields to newTokenMap
  321. if(!BallocElementFromMasterTable(
  322. MTI_NEWTOKENMAP, &dwNewTKMindex, pglobl) )
  323. {
  324. geErrorSev = ERRSEV_RESTART ;
  325. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  326. gdwMasterTabIndex = MTI_NEWTOKENMAP ;
  327. continue ;
  328. }
  329. pNewtkmap[dwNewTKMindex] = ptkmap[dwEntry] ;
  330. if(ptkmap[dwEntry].dwFlags & TKMF_MACROREF)
  331. {
  332. if(!BResolveValueMacroReference(pNewtkmap , dwNewTKMindex, pglobl))
  333. {
  334. pNewtkmap[dwNewTKMindex].dwKeywordID = ID_NULLENTRY ;
  335. }
  336. if(gdwVerbosity >= 4)
  337. {
  338. ERR(("\nEnumerate ValueMacro Reference at:\n")) ;
  339. vIdentifySource(pNewtkmap + dwNewTKMindex, pglobl) ;
  340. ERR((" %0.*s : %0.*s\n",
  341. pNewtkmap[dwNewTKMindex].aarKeyword.dw,
  342. pNewtkmap[dwNewTKMindex].aarKeyword.pub,
  343. pNewtkmap[dwNewTKMindex].aarValue.dw,
  344. pNewtkmap[dwNewTKMindex].aarValue.pub
  345. ));
  346. }
  347. }
  348. } // end of for each tkmap entry loop
  349. if(geErrorSev >= ERRSEV_RESTART)
  350. bStatus = FALSE ;
  351. return(bStatus) ;
  352. }
  353. BOOL BDefineValueMacroName(
  354. PTKMAP pNewtkmap,
  355. DWORD dwNewTKMindex,
  356. PGLOBL pglobl)
  357. {
  358. DWORD dwValueMacroEntry, dwSymbolID ;
  359. PVALUEMACRODICTENTRY pValueMacroDictEntry ;
  360. if(!BeatSurroundingWhiteSpaces(&pNewtkmap[dwNewTKMindex].aarKeyword) )
  361. {
  362. vIdentifySource(pNewtkmap + dwNewTKMindex, pglobl) ;
  363. ERR(("syntax error in ValueMacro name.\n"));
  364. return(FALSE);
  365. }
  366. dwSymbolID = DWregisterSymbol(&pNewtkmap[dwNewTKMindex].aarKeyword,
  367. CONSTRUCT_MACROS, TRUE, INVALID_SYMBOLID, pglobl ) ;
  368. if(dwSymbolID == INVALID_SYMBOLID)
  369. return(FALSE);
  370. if(!BallocElementFromMasterTable(
  371. MTI_VALUEMACROARRAY, &dwValueMacroEntry, pglobl) )
  372. {
  373. geErrorSev = ERRSEV_RESTART ;
  374. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  375. gdwMasterTabIndex = MTI_VALUEMACROARRAY ;
  376. return(FALSE);
  377. }
  378. pValueMacroDictEntry = (PVALUEMACRODICTENTRY)gMasterTable[MTI_VALUEMACROARRAY].pubStruct ;
  379. pValueMacroDictEntry[dwValueMacroEntry].dwSymbolID = dwSymbolID ;
  380. pValueMacroDictEntry[dwValueMacroEntry].dwTKIndexValue = dwNewTKMindex ;
  381. return(TRUE);
  382. }
  383. BOOL BResolveValueMacroReference(
  384. PTKMAP ptkmap,
  385. DWORD dwTKMindex,
  386. PGLOBL pglobl)
  387. {
  388. BYTE ubChar ;
  389. PVALUEMACRODICTENTRY pValueMacroDictEntry ;
  390. ABSARRAYREF aarNewValue, aarValue, aarToken ;
  391. PBYTE pubDelimiters = "=\"%" ; // array of valid delimiters
  392. DWORD dwEntry, dwDelim ; // index to pubDelimiters
  393. // ------ original strict interpretation ------
  394. // because the value contains a =MacroRef, we assume
  395. // the value is comprised purely of =MacroRef, "substrings" and
  396. // %{params} mixed up in any order. A new value string
  397. // without the =MacroRefs will replace the original.
  398. // ------ lenient interpretation --------
  399. // if the GPD writer only uses the reserved characters
  400. // = to indicate a MacroRef and as part of a string literal
  401. // or comment,
  402. // " to delimit a string literal, or as part of a string literal
  403. // or comment,
  404. // % to begin a parameter construct , or as part of a string literal
  405. // or comment, or as the escape character within a string literal
  406. //
  407. // then the parser can allow 1 or more valuemacro references to be
  408. // embedded in any arbitrary value string subject to
  409. // these conditions:
  410. // a) "string literals" and %{param constructs} may not
  411. // contain =MacroRefs
  412. // b) the value associated with each *Macro: must be
  413. // a syntatically valid value object.
  414. // ie an INT, PAIR(,) , ENUM_CONSTANT, SUBSTRING, PARAM etc.
  415. // c) when all macro references are expanded, the resulting value
  416. // must itself satisfy b) for every keyword and macrodefinition
  417. // which contains one or more =Macroref.
  418. aarNewValue.dw = 0 ; // initialize so BCatToTmpHeap
  419. // will overwrite instead of append
  420. pValueMacroDictEntry = (PVALUEMACRODICTENTRY)gMasterTable[MTI_VALUEMACROARRAY].pubStruct ;
  421. aarValue = ptkmap[dwTKMindex].aarValue ;
  422. if(!BeatLeadingWhiteSpaces( &aarValue) )
  423. {
  424. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  425. ERR(("Internal error: =MacroRef expected, but No value found.\n"));
  426. return(FALSE) ;
  427. }
  428. ubChar = *aarValue.pub ; // first char in value string
  429. aarValue.dw-- ;
  430. aarValue.pub++ ; // clip off the first char to simulate
  431. // effect of BdelimitToken()
  432. while(1)
  433. {
  434. switch(ubChar)
  435. {
  436. case '=': // macroname indicator
  437. {
  438. DWORD dwRefSymbolID, // ID of MacroReference.
  439. dwNewTKMindex, // tokenmap index containing valueMacro.
  440. dwMaxIndex ; // one past last valMacro dictionary entry
  441. if(!BdelimitName(&aarValue, &aarToken, &ubChar ) )
  442. {
  443. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  444. ERR(("No MacroName detected after '='.\n"));
  445. return(FALSE) ;
  446. }
  447. if(aarValue.dw)
  448. {
  449. aarValue.dw-- ;
  450. aarValue.pub++ ; // clip off the first char to simulate
  451. }
  452. if(!BparseSymbol(&aarToken,
  453. &dwRefSymbolID,
  454. VALUE_SYMBOL_VALUEMACRO, pglobl) )
  455. {
  456. return(FALSE) ;
  457. }
  458. // search ValueMacro Dict starting from most recent entry
  459. dwMaxIndex = gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex ;
  460. for(dwEntry = 0 ; dwEntry < dwMaxIndex ; dwEntry++)
  461. {
  462. if(pValueMacroDictEntry[dwMaxIndex - 1 - dwEntry].dwSymbolID
  463. == dwRefSymbolID)
  464. break ;
  465. }
  466. if(dwEntry >= dwMaxIndex)
  467. {
  468. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  469. ERR(("=MacroRef not resolved. Not defined or out of scope.\n"));
  470. return(FALSE) ;
  471. }
  472. dwNewTKMindex =
  473. pValueMacroDictEntry[dwMaxIndex - 1 - dwEntry].dwTKIndexValue ;
  474. if(dwNewTKMindex >= dwTKMindex )
  475. {
  476. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  477. ERR(("ValueMacro cannot reference itself.\n"));
  478. return(FALSE) ;
  479. }
  480. // concat valuestring onto tmpHeap.
  481. if(!BCatToTmpHeap(&aarNewValue, &ptkmap[dwNewTKMindex].aarValue, pglobl) )
  482. {
  483. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  484. ERR(("Concatenation to produce expanded macro value failed.\n"));
  485. return(FALSE) ;
  486. }
  487. break ;
  488. }
  489. case '%': // command parameter
  490. {
  491. if(!BdelimitToken(&aarValue, "}", &aarToken, &dwDelim) )
  492. {
  493. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  494. ERR(("missing terminating '}' in command parameter.\n"));
  495. return(FALSE) ;
  496. }
  497. // when concatenating you must restore the delimiters
  498. // % and } that were stripped by DelimitToken.
  499. aarToken.dw += 2 ;
  500. aarToken.pub-- ;
  501. if(!BCatToTmpHeap(&aarNewValue, &aarToken, pglobl) )
  502. {
  503. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  504. ERR(("Concatenation to produce expanded macro value failed.\n"));
  505. return(FALSE) ;
  506. }
  507. if(aarValue.dw)
  508. {
  509. ubChar = *aarValue.pub;
  510. aarValue.dw-- ;
  511. aarValue.pub++ ; // clip off the first char to simulate
  512. }
  513. else
  514. ubChar = '\0' ; // no more objects
  515. break ;
  516. }
  517. case '"' : // this is a string construct
  518. {
  519. if(!BdelimitToken(&aarValue, "\"", &aarToken, &dwDelim) )
  520. {
  521. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  522. ERR(("missing terminating '\"' in substring.\n"));
  523. return(FALSE) ;
  524. }
  525. // when concatenating you must restore the delimiters
  526. // " and " that were stripped by DelimitToken.
  527. aarToken.dw += 2 ;
  528. aarToken.pub-- ;
  529. if(!BCatToTmpHeap(&aarNewValue, &aarToken, pglobl) )
  530. {
  531. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  532. ERR(("Concatenation to produce expanded macro value failed.\n"));
  533. return(FALSE) ;
  534. }
  535. if(aarValue.dw)
  536. {
  537. ubChar = *aarValue.pub;
  538. aarValue.dw-- ;
  539. aarValue.pub++ ; // clip off the first char to simulate
  540. }
  541. else
  542. ubChar = '\0' ; // no more objects
  543. break ;
  544. }
  545. case '\0': // end of value string
  546. {
  547. (VOID) BeatLeadingWhiteSpaces(&aarValue) ;
  548. if(aarValue.dw) // is stuff remaining?
  549. {
  550. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  551. ERR(("Error parsing value containing =MacroRef: %0.*s.\n",
  552. ptkmap[dwTKMindex].aarValue.dw,
  553. ptkmap[dwTKMindex].aarValue.pub));
  554. ERR((" only %{parameter} or \"substrings\" may coexist with =MacroRefs.\n"));
  555. return(FALSE);
  556. }
  557. ptkmap[dwTKMindex].aarValue = aarNewValue ;
  558. return(TRUE);
  559. }
  560. default:
  561. {
  562. aarValue.dw++ ;
  563. aarValue.pub-- ; // restore the first char
  564. if(!BdelimitToken(&aarValue, pubDelimiters,
  565. &aarToken, &dwDelim ) )
  566. {
  567. aarToken = aarValue ;
  568. ubChar = '\0' ; // no more objects
  569. aarValue.dw = 0 ;
  570. }
  571. else
  572. ubChar = pubDelimiters[dwDelim];
  573. // concat valuestring onto tmpHeap.
  574. if(!BCatToTmpHeap(&aarNewValue, &aarToken, pglobl) )
  575. {
  576. vIdentifySource(ptkmap + dwTKMindex, pglobl) ;
  577. ERR(("Concatenation to produce expanded macro value failed.\n"));
  578. return(FALSE) ;
  579. }
  580. break ;
  581. }
  582. } // end switch
  583. } // end while
  584. return(TRUE); // unreachable statement.
  585. }
  586. BOOL BdelimitName(
  587. PABSARRAYREF paarValue, // the remainder of the string without the Name
  588. PABSARRAYREF paarToken, // contains the Name
  589. PBYTE pubChar ) // first char after Name - NULL is returned if nothing
  590. // remains.
  591. {
  592. BYTE ubSrc ;
  593. DWORD dwI ;
  594. for(dwI = 0 ; dwI < paarValue->dw ; dwI++)
  595. {
  596. ubSrc = paarValue->pub[dwI] ;
  597. if( (ubSrc < 'a' || ubSrc > 'z') &&
  598. (ubSrc < 'A' || ubSrc > 'Z') &&
  599. (ubSrc < '0' || ubSrc > '9') &&
  600. (ubSrc != '_') )
  601. {
  602. break ; // end of keyword token.
  603. }
  604. }
  605. paarToken->pub = paarValue->pub ;
  606. paarToken->dw = dwI ;
  607. paarValue->pub += dwI;
  608. paarValue->dw -= dwI ;
  609. if(paarValue->dw)
  610. *pubChar = ubSrc ;
  611. else
  612. *pubChar = '\0' ;
  613. return(paarToken->dw != 0) ;
  614. }
  615. BOOL BCatToTmpHeap(
  616. PABSARRAYREF paarDest,
  617. PABSARRAYREF paarSrc,
  618. PGLOBL pglobl)
  619. /* if paarDest->dw is zero, copy paarSrc to the temp heap
  620. else append paarSrc to existing Heap.
  621. Note: assumes existing string in parrDest is the most
  622. recent item on the Heap.
  623. does not create null terminated strings! */
  624. {
  625. ABSARRAYREF aarTmpDest ;
  626. if(!BcopyToTmpHeap(&aarTmpDest, paarSrc, pglobl))
  627. return(FALSE) ;
  628. // append this run to existing string
  629. if(!paarDest->dw) // no prevs string exists
  630. {
  631. paarDest->pub = aarTmpDest.pub ;
  632. }
  633. else
  634. {
  635. // BUG_BUG paranoid: may check that string is contiguous
  636. ASSERT(paarDest->pub + paarDest->dw == aarTmpDest.pub) ;
  637. }
  638. paarDest->dw += aarTmpDest.dw ;
  639. return(TRUE);
  640. }
  641. BOOL BResolveBlockMacroReference(
  642. PTKMAP ptkmap,
  643. DWORD dwMacRefIndex,
  644. PGLOBL pglobl)
  645. {
  646. DWORD dwRefSymbolID, dwTKIndexOpen, dwTKIndexClose,
  647. dwEntry, // note used to index MacroDict and later TKmap
  648. dwNewTKMindex, dwMaxIndex;
  649. ABSARRAYREF aarValue ;
  650. PBLOCKMACRODICTENTRY pBlockMacroDictEntry ;
  651. PTKMAP pNewtkmap ;
  652. aarValue = ptkmap[dwMacRefIndex].aarValue ;
  653. if(!BeatDelimiter(&aarValue, "=") )
  654. {
  655. ERR(("expected a =MacroName as the only value of *InsertBlockMacro keyword.\n"));
  656. return(FALSE);
  657. }
  658. if(!BparseSymbol(&aarValue,
  659. &dwRefSymbolID,
  660. VALUE_SYMBOL_BLOCKMACRO, pglobl) )
  661. {
  662. return(FALSE) ;
  663. }
  664. // search BlockMacro Dict starting from most recent entry
  665. pBlockMacroDictEntry =
  666. (PBLOCKMACRODICTENTRY)gMasterTable[MTI_BLOCKMACROARRAY].pubStruct ;
  667. dwMaxIndex = gMasterTable[MTI_BLOCKMACROARRAY].dwCurIndex ;
  668. for(dwEntry = 0 ; dwEntry < dwMaxIndex ; dwEntry++)
  669. {
  670. if(pBlockMacroDictEntry[dwMaxIndex - 1 - dwEntry].dwSymbolID
  671. == dwRefSymbolID)
  672. break ;
  673. }
  674. if(dwEntry >= dwMaxIndex)
  675. {
  676. ERR(("=MacroRef not resolved. Not defined or out of scope.\n"));
  677. return(FALSE) ;
  678. }
  679. dwTKIndexOpen =
  680. pBlockMacroDictEntry[dwMaxIndex - 1 - dwEntry].dwTKIndexOpen ;
  681. dwTKIndexClose =
  682. pBlockMacroDictEntry[dwMaxIndex - 1 - dwEntry].dwTKIndexClose ;
  683. if(dwTKIndexOpen == INVALID_INDEX || dwTKIndexClose == INVALID_INDEX )
  684. {
  685. ERR(("Macro cannot be referenced until it has been fully defined.\n"));
  686. return(FALSE);
  687. }
  688. pNewtkmap = (PTKMAP)gMasterTable[MTI_NEWTOKENMAP].pubStruct ;
  689. for(dwEntry = dwTKIndexOpen + 1 ; dwEntry < dwTKIndexClose ; dwEntry++)
  690. {
  691. // transfer all tokenmap fields to newTokenMap
  692. // except NULL entries.
  693. if(pNewtkmap[dwEntry].dwKeywordID == ID_NULLENTRY)
  694. continue ;
  695. if(!BallocElementFromMasterTable(
  696. MTI_NEWTOKENMAP, &dwNewTKMindex, pglobl) )
  697. {
  698. geErrorSev = ERRSEV_RESTART ;
  699. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  700. gdwMasterTabIndex = MTI_NEWTOKENMAP ;
  701. return(FALSE);
  702. }
  703. pNewtkmap[dwNewTKMindex] = pNewtkmap[dwEntry] ;
  704. }
  705. return(TRUE);
  706. }
  707. BOOL BDefineBlockMacroName(
  708. PTKMAP pNewtkmap,
  709. DWORD dwNewTKMindex,
  710. PGLOBL pglobl)
  711. {
  712. DWORD dwBlockMacroEntry, dwSymbolID ;
  713. PBLOCKMACRODICTENTRY pBlockMacroDictEntry ;
  714. if(!BeatSurroundingWhiteSpaces(&pNewtkmap[dwNewTKMindex].aarValue) )
  715. {
  716. vIdentifySource(pNewtkmap + dwNewTKMindex, pglobl) ;
  717. ERR(("syntax error in BlockMacro name.\n"));
  718. return(FALSE);
  719. }
  720. dwSymbolID = DWregisterSymbol(&pNewtkmap[dwNewTKMindex].aarValue,
  721. CONSTRUCT_BLOCKMACRO, TRUE, INVALID_SYMBOLID, pglobl ) ;
  722. if(dwSymbolID == INVALID_SYMBOLID)
  723. return(FALSE);
  724. if(!BallocElementFromMasterTable(
  725. MTI_BLOCKMACROARRAY, &dwBlockMacroEntry, pglobl) )
  726. {
  727. geErrorSev = ERRSEV_RESTART ;
  728. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  729. gdwMasterTabIndex = MTI_BLOCKMACROARRAY ;
  730. return(FALSE);
  731. }
  732. pBlockMacroDictEntry = (PBLOCKMACRODICTENTRY)gMasterTable[MTI_BLOCKMACROARRAY].pubStruct ;
  733. pBlockMacroDictEntry[dwBlockMacroEntry].dwSymbolID = dwSymbolID ;
  734. pBlockMacroDictEntry[dwBlockMacroEntry].dwTKIndexOpen = INVALID_INDEX ;
  735. pBlockMacroDictEntry[dwBlockMacroEntry].dwTKIndexClose = INVALID_INDEX ;
  736. return(TRUE);
  737. }
  738. BOOL BIncreaseMacroLevel(
  739. BOOL bMacroInProgress,
  740. PGLOBL pglobl)
  741. // called in response to parsing open brace.
  742. {
  743. DWORD dwMacroLevel ;
  744. PMACROLEVELSTATE pMacroLevelStack ;
  745. if(!BallocElementFromMasterTable(
  746. MTI_MACROLEVELSTACK, &dwMacroLevel, pglobl) )
  747. {
  748. geErrorSev = ERRSEV_RESTART ;
  749. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  750. gdwMasterTabIndex = MTI_MACROLEVELSTACK ;
  751. return(FALSE);
  752. }
  753. pMacroLevelStack = (PMACROLEVELSTATE)gMasterTable[MTI_MACROLEVELSTACK].pubStruct ;
  754. pMacroLevelStack[dwMacroLevel].dwCurBlockMacroEntry =
  755. gMasterTable[MTI_BLOCKMACROARRAY].dwCurIndex ;
  756. pMacroLevelStack[dwMacroLevel].dwCurValueMacroEntry =
  757. gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex;
  758. pMacroLevelStack[dwMacroLevel].bMacroInProgress =
  759. bMacroInProgress ;
  760. return(TRUE);
  761. }
  762. BOOL BDecreaseMacroLevel(
  763. PTKMAP pNewtkmap,
  764. DWORD dwNewTKMindex,
  765. PGLOBL pglobl)
  766. // called in response to parsing close brace.
  767. {
  768. DWORD dwMacroLevel, dwCurBlockMacroEntry, dwCurValueMacroEntry ,
  769. dwTKIndexOpen, dwTKIndexClose,
  770. dwTKMindex, // location of expired macros.
  771. dwEntry; // index value and block macro dicts
  772. BOOL bMacroInProgress ;
  773. PMACROLEVELSTATE pMacroLevelStack ;
  774. PBLOCKMACRODICTENTRY pBlockMacroDictEntry ;
  775. PVALUEMACRODICTENTRY pValueMacroDictEntry ;
  776. if(!gMasterTable[MTI_MACROLEVELSTACK].dwCurIndex)
  777. {
  778. ERR(("Too many closing braces. Fatal syntax error.\n"));
  779. geErrorSev = ERRSEV_FATAL ;
  780. geErrorType = ERRTY_SYNTAX ;
  781. return(FALSE);
  782. }
  783. pBlockMacroDictEntry = (PBLOCKMACRODICTENTRY)gMasterTable[MTI_BLOCKMACROARRAY].pubStruct ;
  784. pValueMacroDictEntry = (PVALUEMACRODICTENTRY)gMasterTable[MTI_VALUEMACROARRAY].pubStruct ;
  785. pMacroLevelStack = (PMACROLEVELSTATE)gMasterTable[MTI_MACROLEVELSTACK].pubStruct ;
  786. dwMacroLevel = --gMasterTable[MTI_MACROLEVELSTACK].dwCurIndex;
  787. dwCurBlockMacroEntry = pMacroLevelStack[dwMacroLevel].dwCurBlockMacroEntry ;
  788. dwCurValueMacroEntry = pMacroLevelStack[dwMacroLevel].dwCurValueMacroEntry ;
  789. bMacroInProgress = pMacroLevelStack[dwMacroLevel].bMacroInProgress ;
  790. // Does this closing brace end a macro definition?
  791. if(bMacroInProgress)
  792. {
  793. if(pBlockMacroDictEntry[dwCurBlockMacroEntry - 1].dwTKIndexClose
  794. != INVALID_INDEX)
  795. {
  796. ERR(("Internal Error: macro nesting level inconsistency.\n"));
  797. geErrorSev = ERRSEV_FATAL ;
  798. geErrorType = ERRTY_CODEBUG ;
  799. return(FALSE);
  800. }
  801. pBlockMacroDictEntry[dwCurBlockMacroEntry - 1].dwTKIndexClose =
  802. dwNewTKMindex ; // location of } in newtokenArray;
  803. }
  804. // remove all traces of expired block and value macro definitions
  805. for(dwEntry = dwCurValueMacroEntry ;
  806. dwEntry < gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex ;
  807. dwEntry++)
  808. {
  809. dwTKMindex = pValueMacroDictEntry[dwEntry].dwTKIndexValue ;
  810. pNewtkmap[dwTKMindex].dwKeywordID = ID_NULLENTRY ;
  811. }
  812. for(dwEntry = dwCurBlockMacroEntry ;
  813. dwEntry < gMasterTable[MTI_BLOCKMACROARRAY].dwCurIndex ;
  814. dwEntry++)
  815. {
  816. dwTKIndexOpen = pBlockMacroDictEntry[dwEntry].dwTKIndexOpen ;
  817. dwTKIndexClose = pBlockMacroDictEntry[dwEntry].dwTKIndexClose ;
  818. for(dwTKMindex = dwTKIndexOpen ; dwTKMindex <= dwTKIndexClose ;
  819. dwTKMindex++)
  820. pNewtkmap[dwTKMindex].dwKeywordID = ID_NULLENTRY ;
  821. }
  822. if(bMacroInProgress && gdwVerbosity >= 4)
  823. {
  824. VEnumBlockMacro(pNewtkmap,
  825. pBlockMacroDictEntry + dwCurBlockMacroEntry - 1, pglobl) ;
  826. }
  827. // must ensure these values are restored even in the event
  828. // of premature return;
  829. gMasterTable[MTI_BLOCKMACROARRAY].dwCurIndex = dwCurBlockMacroEntry;
  830. gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex = dwCurValueMacroEntry;
  831. return(TRUE);
  832. }
  833. VOID VEnumBlockMacro(
  834. PTKMAP pNewtkmap,
  835. PBLOCKMACRODICTENTRY pBlockMacroDictEntry,
  836. PGLOBL pglobl )
  837. {
  838. DWORD dwTKIndexOpen, dwTKIndexClose, dwTKMindex ;
  839. dwTKIndexOpen = pBlockMacroDictEntry->dwTKIndexOpen ;
  840. dwTKIndexClose = pBlockMacroDictEntry->dwTKIndexClose ;
  841. ERR(("\nContents of Block Macro ID value: %d at:\n",
  842. pBlockMacroDictEntry->dwSymbolID)) ;
  843. vIdentifySource(pNewtkmap + dwTKIndexOpen, pglobl) ;
  844. for(dwTKMindex = dwTKIndexOpen + 1 ; dwTKMindex < dwTKIndexClose ;
  845. dwTKMindex++)
  846. {
  847. if(pNewtkmap[dwTKMindex].dwKeywordID == ID_NULLENTRY)
  848. continue ;
  849. ERR((" %0.*s : %0.*s\n",
  850. pNewtkmap[dwTKMindex].aarKeyword.dw,
  851. pNewtkmap[dwTKMindex].aarKeyword.pub,
  852. pNewtkmap[dwTKMindex].aarValue.dw,
  853. pNewtkmap[dwTKMindex].aarValue.pub
  854. ));
  855. }
  856. }
  857. // ---- scrap pile - may find some useful odds and ends here -----
  858. // gMasterTable[MTI_VALUEMACROARRAY].dwCurIndex-- ;
  859. // remove macrodef from dictionary.