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.

2101 lines
66 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. /* value1.c - functions to parse value field
  3. and to convert the information into the proper
  4. binary format. */
  5. #include "gpdparse.h"
  6. // ---- functions defined in value1.c ---- //
  7. BOOL BaddValueToHeap(
  8. IN OUT PDWORD ploHeap, // dest offset to value in binary form
  9. IN PTKMAP ptkmap, // pointer to tokenmap
  10. IN BOOL bOverWrite, // assume ploHeap contains a valid offset
  11. // to a reserved region of the heap of the proper size
  12. // and write binary value into this location instead of
  13. // growing heap. Note: defer overwriting lpHeap
  14. // until we are certain of success.
  15. IN OUT PGLOBL pglobl
  16. ) ;
  17. BOOL BparseAndWrite(
  18. IN PBYTE pubDest, // write binary data or link to this address.
  19. IN PTKMAP ptkmap, // pointer to tokenmap
  20. IN BOOL bAddToHeap, // if true, write to curHeap not pubDest
  21. OUT PDWORD pdwHeapOffset, // if (bAddToHeap) heap offset where
  22. IN OUT PGLOBL pglobl
  23. ) ;
  24. BOOL BparseInteger(
  25. IN PABSARRAYREF paarValue,
  26. IN PDWORD pdwDest, // write dword value here.
  27. IN VALUE eAllowedValue, // dummy
  28. IN PGLOBL pglobl
  29. ) ;
  30. BOOL BparseList(
  31. IN PABSARRAYREF paarValue,
  32. IN PDWORD pdwDest, // location where index to start of list
  33. // is saved
  34. IN BOOL (*fnBparseValue)(PABSARRAYREF, PDWORD, VALUE, PGLOBL), // callback
  35. IN VALUE eAllowedValue, // dummy
  36. IN OUT PGLOBL pglobl
  37. ) ;
  38. BOOL BeatLeadingWhiteSpaces(
  39. IN OUT PABSARRAYREF paarSrc
  40. ) ;
  41. BOOL BeatDelimiter(
  42. IN OUT PABSARRAYREF paarSrc,
  43. IN PBYTE pubDelStr // points to a string which paarSrc must match
  44. ) ;
  45. BOOL BdelimitToken(
  46. IN OUT PABSARRAYREF paarSrc, // source string
  47. IN PBYTE pubDelimiters, // array of valid delimiters
  48. OUT PABSARRAYREF paarToken, // token defined by delimiter
  49. OUT PDWORD pdwDel // which delimiter was first encountered?
  50. ) ;
  51. BOOL BeatSurroundingWhiteSpaces(
  52. IN PABSARRAYREF paarSrc
  53. ) ;
  54. BOOL BparseSymbol(
  55. IN PABSARRAYREF paarValue,
  56. IN PDWORD pdwDest, // write dword value here.
  57. IN VALUE eAllowedValue, // which class of symbol is this?
  58. IN PGLOBL pglobl
  59. ) ;
  60. BOOL BparseQualifiedName
  61. (
  62. IN PABSARRAYREF paarValue,
  63. IN PDWORD pdwDest, // write dword value here.
  64. IN VALUE eAllowedValue, // which class of symbol is this?
  65. IN PGLOBL pglobl
  66. ) ;
  67. BOOL BparseQualifiedNameEx
  68. (
  69. IN PABSARRAYREF paarValue,
  70. IN PDWORD pdwDest, // write dword value here.
  71. IN VALUE eAllowedValue, // which class of symbol is this?
  72. IN PGLOBL pglobl
  73. ) ;
  74. BOOL BparsePartiallyQualifiedName
  75. (
  76. IN PABSARRAYREF paarValue,
  77. IN PDWORD pdwDest, // write dword value here.
  78. IN VALUE eAllowedValue, // which class of symbol is this?
  79. IN PGLOBL pglobl
  80. ) ;
  81. BOOL BparseOptionSymbol(
  82. IN PABSARRAYREF paarValue,
  83. IN PDWORD pdwDest, // write dword value here.
  84. IN VALUE eAllowedValue, // which class of symbol is this?
  85. IN PGLOBL pglobl
  86. ) ;
  87. BOOL BparseConstant(
  88. IN OUT PABSARRAYREF paarValue,
  89. OUT PDWORD pdwDest, // write dword value here.
  90. IN VALUE eAllowedValue, // which class of constant is this?
  91. IN PGLOBL pglobl
  92. ) ;
  93. BOOL BinitClassIndexTable(
  94. IN OUT PGLOBL pglobl) ;
  95. BOOL BparseRect(
  96. IN PABSARRAYREF paarValue,
  97. IN PRECT prcDest,
  98. PGLOBL pglobl
  99. ) ;
  100. BOOL BparsePoint(
  101. IN PABSARRAYREF paarValue,
  102. IN PPOINT pptDest,
  103. PGLOBL pglobl
  104. ) ;
  105. BOOL BparseString(
  106. IN PABSARRAYREF paarValue,
  107. IN PARRAYREF parStrValue,
  108. IN OUT PGLOBL pglobl
  109. ) ;
  110. BOOL BparseAndTerminateString(
  111. IN PABSARRAYREF paarValue,
  112. IN PARRAYREF parStrValue,
  113. IN VALUE eAllowedValue,
  114. IN OUT PGLOBL pglobl
  115. ) ;
  116. BOOL BwriteUnicodeToHeap(
  117. IN PARRAYREF parSrcString,
  118. OUT PARRAYREF parUnicodeString,
  119. IN INT iCodepage,
  120. IN OUT PGLOBL pglobl
  121. ) ;
  122. BOOL BparseStrSegment(
  123. IN PABSARRAYREF paarStrSeg, // source str segment
  124. IN PARRAYREF parStrLiteral, // dest for result
  125. IN OUT PGLOBL pglobl
  126. ) ;
  127. BOOL BparseStrLiteral(
  128. IN PABSARRAYREF paarStrSeg, // points to literal substring segment.
  129. IN PARRAYREF parStrLiteral, // dest for result
  130. IN OUT PGLOBL pglobl
  131. ) ;
  132. BOOL BparseHexStr(
  133. IN PABSARRAYREF paarStrSeg, // points to hex substring segment.
  134. IN PARRAYREF parStrLiteral, // dest for result
  135. IN OUT PGLOBL pglobl
  136. ) ;
  137. BOOL BparseOrderDep(
  138. IN PABSARRAYREF paarValue,
  139. IN PORDERDEPENDENCY pordDest,
  140. PGLOBL pglobl
  141. ) ;
  142. PDWORD pdwEndOfList(
  143. PDWORD pdwNodeIndex,
  144. PGLOBL pglobl) ;
  145. #ifdef GMACROS
  146. PBYTE ExtendChain(
  147. PBYTE pubDest,
  148. IN BOOL bOverWrite,
  149. IN OUT PGLOBL pglobl) ;
  150. #endif
  151. // ---------------------------------------------------- //
  152. BOOL BaddValueToHeap(
  153. IN OUT PDWORD ploHeap, // dest offset to value in binary form
  154. IN PTKMAP ptkmap, // pointer to tokenmap
  155. IN BOOL bOverWrite, // assume ploHeap contains a valid offset
  156. // to a reserved region of the heap of the proper size
  157. // and write binary value into this location instead of
  158. // growing heap. Note: defer overwriting lpHeap
  159. // until we are certain of success.
  160. IN OUT PGLOBL pglobl
  161. )
  162. {
  163. DWORD dwKeywordID ;
  164. PBYTE pubDest ;
  165. dwKeywordID = ptkmap->dwKeywordID ;
  166. // BUG_BUG !!!!! what if dwKeywordID is a special value?
  167. if(dwKeywordID >= ID_SPECIAL)
  168. return FALSE ;
  169. // note: different attributes are stored in different places
  170. // using different branching techniques. See the
  171. // Bstore_XXX_Attrib() functions for the different
  172. // setups. This function works in concert with those
  173. // functions.
  174. switch(mMainKeywordTable[dwKeywordID].flAgs & KWF_DEDICATED_FIELD)
  175. { // extract just the flags describing the attribute storage type.
  176. case KWF_TTFONTSUBS:
  177. {
  178. // since ploHeap always points to the index
  179. // of the appropriate FontSub structure,
  180. // we ignore bOverWrite
  181. DWORD dwOffset ;
  182. PTTFONTSUBTABLE pttft ;
  183. dwOffset = mMainKeywordTable[dwKeywordID].dwOffset ;
  184. pttft = (PTTFONTSUBTABLE)
  185. gMasterTable[MTI_TTFONTSUBTABLE].pubStruct + *ploHeap;
  186. // write binary data into (PBYTE)pttft + dwOffset ;
  187. pubDest = (PBYTE)pttft + dwOffset ;
  188. if(bOverWrite &&
  189. mMainKeywordTable[dwKeywordID].flAgs & KWF_ADDITIVE &&
  190. mMainKeywordTable[dwKeywordID].flAgs & KWF_LIST)
  191. {
  192. pubDest = (PBYTE)pdwEndOfList((PDWORD)pubDest, pglobl); // walks the list and returns pointer
  193. // to the actual END_OF_LIST value so it can be overwritten to
  194. // extend the list.
  195. }
  196. #ifdef GMACROS
  197. // call this from every place that supports KWF_ADDITIVE.
  198. else if( mMainKeywordTable[dwKeywordID].flAgs & KWF_CHAIN)
  199. {
  200. if(!(pubDest = ExtendChain(pubDest, bOverWrite, pglobl)))
  201. return(FALSE) ;
  202. }
  203. #endif
  204. if(!BparseAndWrite(pubDest, ptkmap, FALSE, NULL, pglobl ) )
  205. {
  206. return(FALSE) ;
  207. }
  208. break;
  209. }
  210. case KWF_FONTCART:
  211. {
  212. // since ploHeap always points to the index
  213. // of the appropriate FontCart structure,
  214. // we ignore bOverWrite
  215. DWORD dwOffset ;
  216. PFONTCART pfc ;
  217. dwOffset = mMainKeywordTable[dwKeywordID].dwOffset ;
  218. pfc = (PFONTCART)
  219. gMasterTable[MTI_FONTCART].pubStruct + *ploHeap;
  220. // write binary data into (PBYTE)pfc + dwOffset ;
  221. pubDest = (PBYTE)pfc + dwOffset ;
  222. if(bOverWrite &&
  223. mMainKeywordTable[dwKeywordID].flAgs & KWF_ADDITIVE &&
  224. mMainKeywordTable[dwKeywordID].flAgs & KWF_LIST)
  225. {
  226. pubDest = (PBYTE)pdwEndOfList((PDWORD)pubDest, pglobl); // walks the list and returns pointer
  227. // to the actual END_OF_LIST value so it can be overwritten to
  228. // extend the list.
  229. }
  230. #ifdef GMACROS
  231. else if( mMainKeywordTable[dwKeywordID].flAgs & KWF_CHAIN)
  232. {
  233. if(!(pubDest = ExtendChain(pubDest, bOverWrite, pglobl )))
  234. return(FALSE) ;
  235. }
  236. #endif
  237. if(!BparseAndWrite(pubDest, ptkmap, FALSE, NULL , pglobl) )
  238. {
  239. return(FALSE) ;
  240. }
  241. break;
  242. }
  243. case KWF_COMMAND:
  244. {
  245. // ploHeap actually points to the variable
  246. // that will receive (or already contains) the CommandArray
  247. // index . This is most likely stored in the leaf node
  248. // of the attribute tree or maybe the CommandTable
  249. // itself if the command is single-valued.
  250. PCOMMAND pcmd ;
  251. DWORD dwOffset ;
  252. if(!bOverWrite) // ploHeap is uninitialized.
  253. {
  254. // obtain first free command element
  255. // and initialize ploHeap.
  256. if(! BallocElementFromMasterTable(MTI_COMMANDARRAY ,
  257. ploHeap, pglobl) )
  258. {
  259. return(FALSE) ;
  260. }
  261. }
  262. // this path now shared by both cases of (bOverWrite)
  263. pcmd = (PCOMMAND)
  264. gMasterTable[MTI_COMMANDARRAY].pubStruct + *ploHeap;
  265. dwOffset = mMainKeywordTable[dwKeywordID].dwOffset ;
  266. // write binary data into CmdArray[*ploHeap] + dwOffset;
  267. // since we write into reserved memory
  268. pubDest = (PBYTE)pcmd + dwOffset ;
  269. if(bOverWrite &&
  270. mMainKeywordTable[dwKeywordID].flAgs & KWF_ADDITIVE &&
  271. mMainKeywordTable[dwKeywordID].flAgs & KWF_LIST)
  272. {
  273. pubDest = (PBYTE)pdwEndOfList((PDWORD)pubDest, pglobl); // walks the list and returns pointer
  274. // to the actual END_OF_LIST value so it can be overwritten to
  275. // extend the list.
  276. }
  277. #ifdef GMACROS
  278. else if( mMainKeywordTable[dwKeywordID].flAgs & KWF_CHAIN)
  279. {
  280. if(!(pubDest = ExtendChain(pubDest, bOverWrite, pglobl )))
  281. return(FALSE) ;
  282. }
  283. #endif
  284. if(!BparseAndWrite(pubDest, ptkmap, FALSE, NULL, pglobl ) )
  285. {
  286. return(FALSE) ;
  287. }
  288. break ;
  289. }
  290. default: // no dedicated structures, save data on heap.
  291. {
  292. if(bOverWrite) // ploHeap really does contain
  293. { // an offset to the heap.
  294. pubDest = mpubOffRef + *ploHeap ;
  295. if(mMainKeywordTable[dwKeywordID].flAgs & KWF_ADDITIVE &&
  296. mMainKeywordTable[dwKeywordID].flAgs & KWF_LIST)
  297. {
  298. pubDest = (PBYTE)pdwEndOfList((PDWORD)pubDest, pglobl); // walks the list and returns pointer
  299. // to the actual END_OF_LIST value so it can be overwritten to
  300. // extend the list.
  301. }
  302. #ifdef GMACROS
  303. else if( mMainKeywordTable[dwKeywordID].flAgs & KWF_CHAIN)
  304. {
  305. if(!(pubDest = ExtendChain(pubDest, bOverWrite, pglobl )))
  306. return(FALSE) ;
  307. }
  308. #endif
  309. if(!BparseAndWrite(pubDest, ptkmap, FALSE, NULL, pglobl ) )
  310. {
  311. return(FALSE) ;
  312. }
  313. }
  314. else
  315. {
  316. // write at cur heap ptr, tell me where
  317. // this is, and advance CurHeap.
  318. if(!BparseAndWrite(NULL, ptkmap,
  319. TRUE, ploHeap, pglobl) )
  320. {
  321. return(FALSE) ;
  322. }
  323. }
  324. break ;
  325. }
  326. }
  327. return(TRUE) ;
  328. }
  329. BOOL BparseAndWrite(
  330. IN PBYTE pubDest, // write binary data or link to this address.
  331. IN PTKMAP ptkmap, // pointer to tokenmap
  332. IN BOOL bAddToHeap, // if true, write to curHeap not pubDest
  333. OUT PDWORD pdwHeapOffset, // if (bAddToHeap) heap offset where
  334. // binary data or link to data was written to.
  335. IN OUT PGLOBL pglobl
  336. )
  337. /* parses value according to its expected type and writes
  338. the appropriate data into the appropriate structures
  339. (if the value is a composite object) and places an
  340. appropriate link in pubDest or simply writes the binary
  341. data directly to pubDest (if simple object).
  342. If (bAddToHeap == TRUE) ignore pubDest and write
  343. data or link to curHeap location and return that offset
  344. in pdwHeapOffset.
  345. Warning! this function allocates a tmp buffer (pubBuf)
  346. which is freed at the very end.
  347. So do not add extra returns() in this function
  348. without freeing this buffer.
  349. */
  350. {
  351. DWORD dwKeywordID ;
  352. VALUE eAllowedValue ; // how should token be parsed?
  353. ABSARRAYREF aarValue ; // location of value token
  354. BOOL bList ;
  355. BOOL bStatus = FALSE ;
  356. PBYTE pubBuf = NULL ;
  357. // temp Dest if needed.
  358. PBYTE pubTmp ; // points to dest for parsing function.
  359. dwKeywordID = ptkmap->dwKeywordID ;
  360. eAllowedValue = mMainKeywordTable[dwKeywordID].eAllowedValue ;
  361. aarValue = ptkmap->aarValue ;
  362. bList = (mMainKeywordTable[dwKeywordID].flAgs & KWF_LIST) ?
  363. (TRUE) : (FALSE);
  364. if(bAddToHeap) // PARANOID checks.
  365. {
  366. if(!pdwHeapOffset)
  367. {
  368. vIdentifySource(ptkmap, pglobl);
  369. ERR(("internal consistency error. heap ptr not supplied.\n"));
  370. return(FALSE) ;
  371. }
  372. }
  373. else
  374. {
  375. if(!pubDest)
  376. return(FALSE) ;
  377. }
  378. if(bAddToHeap)
  379. {
  380. DWORD dwSize ; // for debugging purposes.
  381. dwSize = gValueToSize[VALUE_LARGEST] ;
  382. if(!(pubBuf = MemAlloc(dwSize) ))
  383. {
  384. geErrorSev = ERRSEV_FATAL ;
  385. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  386. return(FALSE) ;
  387. }
  388. }
  389. #ifdef GMACROS
  390. if(bAddToHeap && (mMainKeywordTable[dwKeywordID].flAgs & KWF_CHAIN))
  391. {
  392. if(!(pubTmp = ExtendChain(pubBuf, /* bOverWrite = */ FALSE, pglobl )))
  393. return(FALSE) ;
  394. }
  395. else
  396. #endif
  397. pubTmp = (bAddToHeap) ? (pubBuf) : (pubDest) ;
  398. // all parsing functions write links to a specified
  399. // memory location. If the link is to be saved to
  400. // the heap, the link is first created in a temp
  401. // buffer pubBuf[] which is subseqently copied to
  402. // the heap outside of the function.
  403. switch(eAllowedValue)
  404. {
  405. case VALUE_STRING_NO_CONVERT:
  406. case VALUE_STRING_DEF_CONVERT:
  407. case VALUE_STRING_CP_CONVERT:
  408. {
  409. bStatus = BparseAndTerminateString(&aarValue, (PARRAYREF)pubTmp,
  410. eAllowedValue, pglobl) ;
  411. break ;
  412. }
  413. case VALUE_COMMAND_INVOC:
  414. {
  415. bStatus = BparseCommandString(&aarValue, (PARRAYREF)pubTmp, pglobl) ;
  416. break ;
  417. }
  418. case VALUE_PARAMETER:
  419. {
  420. ((PARRAYREF)pubTmp)->dwCount = 0 ;
  421. bStatus = BprocessParam(&aarValue, (PARRAYREF)pubTmp, pglobl) ;
  422. break ;
  423. }
  424. case VALUE_POINT:
  425. {
  426. bStatus = BparsePoint(&aarValue, (PPOINT)pubTmp, pglobl) ;
  427. break ;
  428. }
  429. case VALUE_RECT:
  430. {
  431. bStatus = BparseRect(&aarValue, (PRECT)pubTmp, pglobl) ;
  432. break ;
  433. }
  434. case VALUE_ORDERDEPENDENCY:
  435. {
  436. bStatus = BparseOrderDep(&aarValue, (PORDERDEPENDENCY)pubTmp, pglobl) ;
  437. break ;
  438. }
  439. // case VALUE_BOOLEAN: this is one class of CONSTANT.
  440. case VALUE_SYMBOL_DEF: // what is this??
  441. {
  442. break ;
  443. }
  444. case VALUE_INTEGER:
  445. {
  446. if(bList)
  447. bStatus = BparseList(&aarValue, (PDWORD)pubTmp,
  448. BparseInteger, eAllowedValue, pglobl) ;
  449. else
  450. bStatus = BparseInteger(&aarValue, (PDWORD)pubTmp,
  451. eAllowedValue, pglobl) ;
  452. break ;
  453. }
  454. case VALUE_CONSTRAINT:
  455. {
  456. bStatus = BparseConstraint(&aarValue, (PDWORD)pubTmp,
  457. bAddToHeap, pglobl) ; // create list vs append to existing
  458. break ;
  459. }
  460. case VALUE_QUALIFIED_NAME:
  461. {
  462. if(bList)
  463. bStatus = BparseList(&aarValue, (PDWORD)pubTmp, BparseQualifiedName, eAllowedValue, pglobl) ;
  464. else
  465. bStatus = BparseQualifiedName(&aarValue, (PDWORD)pubTmp, eAllowedValue, pglobl) ;
  466. break ;
  467. }
  468. case VALUE_QUALIFIED_NAME_EX:
  469. {
  470. if(bList)
  471. bStatus = BparseList(&aarValue, (PDWORD)pubTmp, BparseQualifiedNameEx, eAllowedValue, pglobl) ;
  472. else
  473. bStatus = BparseQualifiedNameEx(&aarValue, (PDWORD)pubTmp, eAllowedValue, pglobl) ;
  474. break ;
  475. }
  476. case VALUE_PARTIALLY_QUALIFIED_NAME:
  477. {
  478. if(bList)
  479. bStatus = BparseList(&aarValue, (PDWORD)pubTmp, BparsePartiallyQualifiedName, eAllowedValue, pglobl) ;
  480. else
  481. bStatus = BparsePartiallyQualifiedName(&aarValue, (PDWORD)pubTmp, eAllowedValue, pglobl) ;
  482. break ;
  483. }
  484. case NO_VALUE : // how can an attribute not have a value?
  485. {
  486. bStatus = TRUE ;
  487. break ;
  488. }
  489. default:
  490. {
  491. if( eAllowedValue >= VALUE_CONSTANT_FIRST &&
  492. eAllowedValue <= VALUE_CONSTANT_LAST )
  493. {
  494. if(bList)
  495. bStatus = BparseList(&aarValue, (PDWORD)pubTmp, BparseConstant, eAllowedValue, pglobl) ;
  496. else
  497. bStatus = BparseConstant(&aarValue, (PDWORD)pubTmp, eAllowedValue, pglobl) ;
  498. }
  499. else if( eAllowedValue == VALUE_SYMBOL_OPTIONS ) // check
  500. // this case before the other symbols.
  501. {
  502. if(bList)
  503. bStatus = BparseList(&aarValue, (PDWORD)pubTmp, BparseOptionSymbol, eAllowedValue, pglobl) ;
  504. else
  505. bStatus = BparseOptionSymbol(&aarValue, (PDWORD)pubTmp, eAllowedValue, pglobl) ;
  506. }
  507. else if( eAllowedValue >= VALUE_SYMBOL_FIRST &&
  508. eAllowedValue <= VALUE_SYMBOL_LAST )
  509. {
  510. if(bList)
  511. bStatus = BparseList(&aarValue, (PDWORD)pubTmp, BparseSymbol, eAllowedValue, pglobl) ;
  512. else
  513. bStatus = BparseSymbol(&aarValue, (PDWORD)pubTmp, eAllowedValue, pglobl) ;
  514. }
  515. else
  516. {
  517. ERR(("internal consistency error - unrecognized VALUE type!\n"));
  518. // don't know how to parse unrecognized value type!
  519. }
  520. break ;
  521. }
  522. }
  523. if(!bStatus)
  524. vIdentifySource(ptkmap, pglobl);
  525. if(bStatus && (eAllowedValue != NO_VALUE) )
  526. {
  527. if(bAddToHeap)
  528. {
  529. #ifdef GMACROS
  530. if(mMainKeywordTable[dwKeywordID].flAgs & KWF_CHAIN)
  531. {
  532. if(!BwriteToHeap(pdwHeapOffset, pubBuf,
  533. gValueToSize[VALUE_LIST], 4, pglobl) ) // chains are LISTS of VALUES.
  534. {
  535. bStatus = FALSE ; // heap overflow start over.
  536. }
  537. }
  538. else
  539. #endif
  540. if(!BwriteToHeap(pdwHeapOffset, pubTmp,
  541. gValueToSize[(bList) ? (VALUE_LIST) : (eAllowedValue)], 4, pglobl) )
  542. {
  543. bStatus = FALSE ; // heap overflow start over.
  544. }
  545. }
  546. }
  547. if(pubBuf)
  548. MemFree(pubBuf) ;
  549. return(bStatus) ;
  550. }
  551. BOOL BparseInteger(
  552. IN PABSARRAYREF paarValue,
  553. IN PDWORD pdwDest, // write dword value here.
  554. IN VALUE eAllowedValue, // dummy
  555. IN PGLOBL pglobl
  556. )
  557. /* the GPD spec defines an integer as a sequence
  558. of numbers preceeded by an optional + or - OR
  559. simply the symbol '*' which means 'don't care'.
  560. NEW: also permit a leading 0x to indicate a number in
  561. hexadecimal format. ie 0x01fE . No + or - allowed
  562. in hex format.
  563. */
  564. {
  565. #define pubM (paarValue->pub)
  566. #define dwM (paarValue->dw)
  567. BOOL bNeg = FALSE ;
  568. DWORD dwNumber ;
  569. BOOL bStatus = FALSE ;
  570. ABSARRAYREF aarValue ;
  571. if(eAllowedValue != VALUE_INTEGER)
  572. return(FALSE); // paranoid check just to use variable
  573. // and thereby avoid compiler warning.
  574. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  575. aarValue.pub = pubM ; // used only to emit error message.
  576. aarValue.dw = dwM ;
  577. if(!dwM)
  578. {
  579. ERR(("BparseInteger: no integer found - empty list?\n"));
  580. // ERR(("\t%0.40s\n", aarValue.pub )) ;
  581. // danger of over shooting EOF
  582. return(FALSE);
  583. }
  584. if(*pubM == '*')
  585. {
  586. dwNumber = WILDCARD_VALUE ;
  587. pubM++ ;
  588. dwM-- ;
  589. bStatus = TRUE ;
  590. }
  591. else if(*pubM == '0') // leading zero indicates hexadecimal format
  592. {
  593. pubM++ ;
  594. dwM-- ;
  595. if(dwM && (*pubM == 'x' || *pubM == 'X'))
  596. {
  597. pubM++ ;
  598. dwM-- ;
  599. }
  600. else
  601. {
  602. dwNumber = 0 ;
  603. bStatus = TRUE ;
  604. goto EndNumber ;
  605. }
  606. if(!dwM)
  607. {
  608. ERR(("BparseInteger: no digits found in Hex value.\n"));
  609. return(FALSE);
  610. }
  611. for(dwNumber = 0 ; dwM ; pubM++, dwM-- )
  612. {
  613. if(*pubM >= '0' && *pubM <= '9')
  614. {
  615. dwNumber *= 0x10 ;
  616. dwNumber += (*pubM - '0') ;
  617. }
  618. else if(*pubM >= 'a' && *pubM <= 'f')
  619. {
  620. dwNumber *= 0x10 ;
  621. dwNumber += (*pubM - 'a' + 0x0a) ;
  622. }
  623. else if(*pubM >= 'A' && *pubM <= 'F')
  624. {
  625. dwNumber *= 0x10 ;
  626. dwNumber += (*pubM - 'A' + 0x0a) ;
  627. }
  628. else
  629. break;
  630. bStatus = TRUE ;
  631. }
  632. }
  633. else
  634. {
  635. if(*pubM == '-')
  636. {
  637. bNeg = TRUE ;
  638. pubM++ ;
  639. dwM-- ;
  640. }
  641. else if(*pubM == '+')
  642. {
  643. pubM++ ;
  644. dwM-- ;
  645. }
  646. // is there anything else after the sign?
  647. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  648. if(!dwM)
  649. {
  650. ERR(("BparseInteger: no digits found.\n"));
  651. return(FALSE);
  652. }
  653. for(dwNumber = 0 ; dwM && *pubM >= '0' && *pubM <= '9' ; )
  654. {
  655. dwNumber *= 10 ;
  656. dwNumber += (*pubM - '0') ;
  657. pubM++ ;
  658. dwM-- ;
  659. bStatus = TRUE ;
  660. }
  661. }
  662. EndNumber:
  663. if(! bStatus)
  664. {
  665. ERR(("error parsing integer value: %0.*s\n", aarValue.dw, aarValue.pub));
  666. return(FALSE);
  667. }
  668. // is there anything else after the digit string?
  669. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  670. if(dwM)
  671. {
  672. ERR(("unexpected characters after digits in integer value: %0.*s\n", aarValue.dw, aarValue.pub));
  673. return(FALSE);
  674. }
  675. *pdwDest = (bNeg) ? ((unsigned)(-(signed)dwNumber)) : (dwNumber) ;
  676. return(TRUE);
  677. #undef pubM
  678. #undef dwM
  679. }
  680. BOOL BparseList(
  681. IN PABSARRAYREF paarValue,
  682. IN PDWORD pdwDest, // location where index to start of list
  683. // is saved
  684. IN BOOL (*fnBparseValue)(PABSARRAYREF, PDWORD, VALUE, PGLOBL), // callback
  685. IN VALUE eAllowedValue, // dummy
  686. IN OUT PGLOBL pglobl
  687. )
  688. /* non-destructively parse this list using
  689. callback function to parse the actual values
  690. in between the LIST structure.
  691. LIST ( <value> , <value> , ... )
  692. Notes:
  693. 1) all continuation line delimiters have been replaced by
  694. spaces at TokenMap creation time. No need to worry
  695. about this here
  696. 2) The List construct must begin with the reserved token
  697. 'LIST' which must be followed by the token '('.
  698. 3) The list of values is enclosed by parenthesis,
  699. adjacent values are delimited by comma.
  700. 4) This function assumes <value> does not contain any
  701. reserved characters ',' comma or ')' close parenthesis
  702. 5) whitespaces may appear between syntactic elements (tokens).
  703. 6) Even if a LIST is not detected, we will still save
  704. the single value in a LIST construct.
  705. 7) Must check string count to see if we have reached the
  706. end of value statement.
  707. */
  708. {
  709. ABSARRAYREF aarToken ; // points to individual value.
  710. PLISTNODE plstRoot ; // start of LIST array
  711. DWORD dwNodeIndex , dwPrevsNode, dwFirstNode;
  712. // index of list node.
  713. DWORD dwDelIndex ; // if BdelimitToken
  714. // found a delimiter, this contains the index to pubDelimiters
  715. // of the delimiter that was found.
  716. BOOL bSyntaxErr = FALSE ;
  717. plstRoot = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
  718. if(! BeatDelimiter(paarValue, "LIST"))
  719. {
  720. // this keyword LIST was not found, assume just
  721. // one value exists.
  722. if(! BallocElementFromMasterTable(MTI_LISTNODES ,
  723. &dwNodeIndex, pglobl) )
  724. {
  725. return(FALSE) ;
  726. }
  727. // shove parsed integer into data field of new listnode.
  728. if(!fnBparseValue(paarValue, &(plstRoot[dwNodeIndex].dwData),
  729. eAllowedValue, pglobl))
  730. {
  731. (VOID)BreturnElementFromMasterTable(MTI_LISTNODES, dwNodeIndex, pglobl) ;
  732. return(FALSE) ;
  733. }
  734. plstRoot[dwNodeIndex].dwNextItem = END_OF_LIST ;
  735. *pdwDest = dwNodeIndex ;
  736. return(TRUE) ;
  737. }
  738. if(! BeatDelimiter(paarValue, "("))
  739. {
  740. ERR(("syntax error: missing '(' after LIST.\n"));
  741. return(FALSE) ;
  742. }
  743. dwPrevsNode = END_OF_LIST ;
  744. // prepare to process an entire list of items.
  745. for(dwDelIndex = 0 ; dwDelIndex != 1 ; )
  746. {
  747. if(!BdelimitToken(paarValue, ",)", &aarToken, &dwDelIndex) )
  748. {
  749. bSyntaxErr = TRUE ;
  750. ERR(("missing terminating ) in LIST construct.\n"));
  751. // emit message for user.
  752. break ; // attempt to return the list we have so far.
  753. }
  754. if(dwDelIndex == 1 && !aarToken.dw)
  755. break ; // empty item.
  756. if(! BallocElementFromMasterTable(MTI_LISTNODES ,
  757. &dwNodeIndex, pglobl) )
  758. {
  759. return(FALSE) ;
  760. }
  761. // shove parsed integer into data field of new listnode.
  762. if(!fnBparseValue(&aarToken, &(plstRoot[dwNodeIndex].dwData),
  763. eAllowedValue, pglobl))
  764. {
  765. (VOID)BreturnElementFromMasterTable(MTI_LISTNODES, dwNodeIndex, pglobl) ;
  766. continue ; // just skip to the next value in list.
  767. }
  768. plstRoot[dwNodeIndex].dwNextItem = END_OF_LIST ;
  769. if(dwPrevsNode == END_OF_LIST)
  770. {
  771. // Therefore, this is the first node in the list.
  772. dwFirstNode = dwNodeIndex ;
  773. }
  774. else // cause prevs node to point to this node.
  775. {
  776. plstRoot[dwPrevsNode].dwNextItem = dwNodeIndex ;
  777. }
  778. dwPrevsNode = dwNodeIndex ; // place here instead
  779. // of part of for( ; ; ) statement so 'continue' will
  780. // bypass this statement.
  781. }
  782. if(dwPrevsNode == END_OF_LIST)
  783. dwFirstNode = END_OF_LIST ;
  784. // empty list is now acceptable.
  785. if(!bSyntaxErr)
  786. {
  787. // verify there is nothing else in statement.
  788. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  789. if(paarValue->dw)
  790. {
  791. ERR(("extraneous characters found after the end of the LIST construct.\n"));
  792. // may want to print them out.
  793. // not a fatal condition, continue.
  794. }
  795. }
  796. *pdwDest = dwFirstNode ;
  797. return(TRUE) ;
  798. }
  799. BOOL BeatLeadingWhiteSpaces(
  800. IN OUT PABSARRAYREF paarSrc
  801. )
  802. /* as name suggests, advance paarSrc to
  803. first nonwhite or set dw = 0 if src string
  804. is exhausted.
  805. */
  806. {
  807. PBYTE pub ;
  808. DWORD dw ;
  809. pub = paarSrc->pub ;
  810. dw = paarSrc->dw ;
  811. while(dw && (*pub == ' ' || *pub == '\t') )
  812. {
  813. pub++ ;
  814. dw-- ;
  815. }
  816. paarSrc->pub = pub ;
  817. paarSrc->dw = dw ;
  818. return(TRUE); // always return true now,
  819. // but can add more robust error checking in the future.
  820. }
  821. BOOL BeatDelimiter(
  822. IN OUT PABSARRAYREF paarSrc,
  823. IN PBYTE pubDelStr // points to a string which paarSrc must match
  824. )
  825. // expects to encounter only
  826. // whitespaces before reaching the specified delimiter string.
  827. // if delimiter doesn't match or src string is exhausted, returns
  828. // FALSE. parrSrc not updated. Otherwise parrSrc
  829. // is updated to point to char which follows delimiter.
  830. {
  831. PBYTE pub ;
  832. DWORD dw, dwLen ;
  833. (VOID) BeatLeadingWhiteSpaces(paarSrc) ;
  834. pub = paarSrc->pub ;
  835. dw = paarSrc->dw ;
  836. dwLen = strlen(pubDelStr) ;
  837. if(dw < dwLen)
  838. return(FALSE);
  839. if(strncmp(pub, pubDelStr, dwLen))
  840. return(FALSE);
  841. pub += dwLen;
  842. dw -= dwLen; // 'Eat' delimiter string
  843. paarSrc->pub = pub ;
  844. paarSrc->dw = dw ;
  845. return(TRUE);
  846. }
  847. BOOL BdelimitToken(
  848. IN OUT PABSARRAYREF paarSrc, // source string
  849. IN PBYTE pubDelimiters, // array of valid delimiters
  850. OUT PABSARRAYREF paarToken, // token defined by delimiter
  851. OUT PDWORD pdwDel // which delimiter was first encountered?
  852. )
  853. // searchs paarSrc for the first occurence of one of the
  854. // characters in the string pubDelimiters. Once found
  855. // all characters up to that delimiter are considered a
  856. // token and an abs string ref to this token is returned
  857. // in paarToken. paarSrc is updated to point to first char
  858. // after the delimiter. If delimiter is not found within paarSrc,
  859. // returns FALSE and neither paarSrc or paarToken is updated.
  860. // pdwDel will contain the zero based index of the delimiter
  861. // that was first encountered: pubDelimiters[pdwDel] .
  862. // Note this function ignores the " and < delimiters if they
  863. // are preceeded by the % character. See ParseString for
  864. // more info.
  865. {
  866. PBYTE pub ;
  867. DWORD dw, dwLen, dwI ;
  868. pub = paarSrc->pub ;
  869. dw = paarSrc->dw ;
  870. dwLen = strlen(pubDelimiters) ;
  871. while( dw )
  872. {
  873. for(dwI = 0 ; dwI < dwLen ; dwI++)
  874. {
  875. if(*pub == pubDelimiters[dwI])
  876. {
  877. if((*pub == '"' || *pub == '<') &&
  878. (dw < paarSrc->dw) && *(pub - 1) == '%')
  879. {
  880. continue ;
  881. }
  882. paarToken->pub = paarSrc->pub ;
  883. paarToken->dw = paarSrc->dw - dw ;
  884. *pdwDel = dwI ; // this was the delimiter
  885. paarSrc->pub = ++pub ; // position after delimiter.
  886. paarSrc->dw = --dw ; // may go to zero.
  887. return(TRUE);
  888. }
  889. }
  890. pub++ ;
  891. dw-- ;
  892. }
  893. return(FALSE); // string exhausted, no delimiters found.
  894. }
  895. BOOL BeatSurroundingWhiteSpaces(
  896. IN PABSARRAYREF paarSrc
  897. )
  898. /* as name suggests, advance paarSrc to
  899. first nonwhite and adjust count to exclude
  900. trailing whitespaces or set dw = 0 if src string
  901. is exhausted. Note: this routine expects
  902. only leading and trailing whitespaces.
  903. The presence of whitespaces within the token
  904. is a user error. (or maybe an internal error).
  905. */
  906. {
  907. PBYTE pub ;
  908. DWORD dw , dwLen ;
  909. pub = paarSrc->pub ;
  910. dw = paarSrc->dw ;
  911. while(dw && (*pub == ' ' || *pub == '\t') )
  912. {
  913. pub++ ;
  914. dw-- ;
  915. }
  916. paarSrc->pub = pub ;
  917. for(dwLen = 0 ; dw && (*pub != ' ') && (*pub != '\t') ; dwLen++ )
  918. {
  919. pub++ ;
  920. dw-- ;
  921. }
  922. paarSrc->dw = dwLen ;
  923. // make sure the rest is white
  924. while(dw && (*pub == ' ' || *pub == '\t') )
  925. {
  926. pub++ ;
  927. dw-- ;
  928. }
  929. if(dw)
  930. {
  931. ERR(("more than one token found where only one was expected: %0.*s\n",
  932. paarSrc->dw, paarSrc->pub));
  933. return(FALSE);
  934. }
  935. return(TRUE);
  936. }
  937. BOOL BparseSymbol(
  938. IN PABSARRAYREF paarValue,
  939. IN PDWORD pdwDest, // write dword value here.
  940. IN VALUE eAllowedValue, // which class of symbol is this?
  941. IN PGLOBL pglobl
  942. )
  943. {
  944. DWORD dwSymbolTree ;
  945. dwSymbolTree = ((PDWORD)gMasterTable[MTI_SYMBOLROOT].pubStruct)
  946. [eAllowedValue - VALUE_SYMBOL_FIRST] ;
  947. if(! BeatSurroundingWhiteSpaces(paarValue) )
  948. return(FALSE);
  949. *pdwDest = DWsearchSymbolListForAAR(paarValue, dwSymbolTree, pglobl) ;
  950. if(*pdwDest == INVALID_SYMBOLID)
  951. {
  952. ERR(("user supplied a non-existent symbol: %0.*s in class: %d\n",
  953. paarValue->dw, paarValue->pub, (eAllowedValue - VALUE_SYMBOL_FIRST) ));
  954. return(FALSE);
  955. }
  956. return(TRUE);
  957. }
  958. BOOL BparseQualifiedName
  959. (
  960. IN PABSARRAYREF paarValue,
  961. IN PDWORD pdwDest, // write dword value here.
  962. IN VALUE eAllowedValue, // which class of symbol is this?
  963. IN PGLOBL pglobl
  964. )
  965. /* A QualifiedName shall be stored in one DWord, if more
  966. storage is required, things get more complex.
  967. A QualifiedName shall consist of 2 parts, Attributes
  968. requiring more qualifiers may specify a LIST of
  969. qualified names.
  970. note: cramming DWORD into WORD, assumes all ID values
  971. are WORD sized.
  972. */
  973. {
  974. ABSARRAYREF aarFeature ; // points to FeatureName.
  975. DWORD dwDelIndex ; // serves no purpose here.
  976. DWORD dwFeatureID, dwFeatureIndex , dwRootOptions, dwOptionID;
  977. PSYMBOLNODE psn ;
  978. if(!BdelimitToken(paarValue, ".", &aarFeature, &dwDelIndex) )
  979. {
  980. ERR(("required delimiter '.' missing in qualified value: %0.*s\n",
  981. paarValue->dw, paarValue->pub));
  982. return(FALSE);
  983. }
  984. if(! BeatSurroundingWhiteSpaces(&aarFeature) ) // holds feature
  985. {
  986. ERR(("no feature found in qualified value: %0.*s\n",
  987. paarValue->dw, paarValue->pub));
  988. return(FALSE);
  989. }
  990. if(! BeatSurroundingWhiteSpaces(paarValue) ) // holds option
  991. {
  992. ERR(("no option found in qualified value: %0.*s\n",
  993. aarFeature.dw, aarFeature.pub));
  994. return(FALSE);
  995. }
  996. dwFeatureID = DWsearchSymbolListForAAR(&aarFeature, mdwFeatureSymbols, pglobl) ;
  997. if(dwFeatureID == INVALID_SYMBOLID)
  998. {
  999. ERR(("qualified name references a non-existent Feature symbol: %0.*s\n",
  1000. aarFeature.dw, aarFeature.pub));
  1001. // for qualified value.
  1002. return(FALSE);
  1003. }
  1004. dwFeatureIndex = DWsearchSymbolListForID(dwFeatureID,
  1005. mdwFeatureSymbols, pglobl);
  1006. psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
  1007. dwRootOptions = psn[dwFeatureIndex].dwSubSpaceIndex ;
  1008. dwOptionID = DWsearchSymbolListForAAR(paarValue, dwRootOptions, pglobl) ;
  1009. if(dwOptionID == INVALID_SYMBOLID)
  1010. {
  1011. ERR(("qualified name references a non-existent Option symbol: %0.*s\n",
  1012. paarValue->dw, paarValue->pub));
  1013. return(FALSE);
  1014. }
  1015. ((PQUALNAME)pdwDest)->wFeatureID = (WORD)dwFeatureID ;
  1016. ((PQUALNAME)pdwDest)->wOptionID = (WORD)dwOptionID ;
  1017. return(TRUE);
  1018. }
  1019. BOOL BparseQualifiedNameEx
  1020. (
  1021. IN PABSARRAYREF paarValue,
  1022. IN PDWORD pdwDest, // write dword value here.
  1023. IN VALUE eAllowedValue, // which class of symbol is this?
  1024. IN PGLOBL pglobl
  1025. )
  1026. /* A QualifiedNameEx is a QualifiedName followed
  1027. by an unsigned integer with a . delimiter.
  1028. Optionally it may just be an integer!
  1029. This type shall be used to store resource references.
  1030. This shall be stored in one DWord in the following format:
  1031. { // arranged in order of increasing memory addresses
  1032. WORD intValue ;
  1033. BYTE OptionIndex ;
  1034. BYTE FeatureIndex ; // note high byte may be cleared
  1035. } // since this is intended for use only
  1036. // as a resource reference.
  1037. */
  1038. {
  1039. ABSARRAYREF aarFeature, // points to FeatureName.
  1040. aarOption ; // points to OptionName.
  1041. DWORD dwDelIndex ; // serves no purpose here.
  1042. DWORD dwFeatureID, dwFeatureIndex , dwRootOptions, dwOptionID;
  1043. PSYMBOLNODE psn ;
  1044. if(!BdelimitToken(paarValue, ".", &aarFeature, &dwDelIndex) )
  1045. {
  1046. // assume this is an integer form.
  1047. return(BparseInteger( paarValue, pdwDest, VALUE_INTEGER, pglobl) );
  1048. }
  1049. if(! BeatSurroundingWhiteSpaces(&aarFeature) ) // holds feature
  1050. {
  1051. ERR(("no feature found in qualified valueEx: %0.*s\n",
  1052. paarValue->dw, paarValue->pub));
  1053. return(FALSE);
  1054. }
  1055. if(!BdelimitToken(paarValue, ".", &aarOption, &dwDelIndex) )
  1056. {
  1057. ERR(("required 2nd delimiter '.' missing in qualified valueEx: %0.*s\n",
  1058. paarValue->dw, paarValue->pub));
  1059. return(FALSE);
  1060. }
  1061. if(! BeatSurroundingWhiteSpaces(&aarOption) ) // holds option
  1062. {
  1063. ERR(("no option found in qualified valueEx: %0.*s\n",
  1064. aarFeature.dw, aarFeature.pub));
  1065. return(FALSE);
  1066. }
  1067. if(!BparseInteger( paarValue, pdwDest, VALUE_INTEGER, pglobl) )
  1068. {
  1069. ERR(("Err parsing integer portion of qualified valueEx: %0.*s\n",
  1070. paarValue->dw, paarValue->pub));
  1071. return(FALSE);
  1072. }
  1073. dwFeatureID = DWsearchSymbolListForAAR(&aarFeature, mdwFeatureSymbols, pglobl) ;
  1074. if(dwFeatureID == INVALID_SYMBOLID)
  1075. {
  1076. ERR(("qualified name references a non-existent Feature symbol: %0.*s\n",
  1077. aarFeature.dw, aarFeature.pub));
  1078. // for qualified value.
  1079. return(FALSE);
  1080. }
  1081. dwFeatureIndex = DWsearchSymbolListForID(dwFeatureID,
  1082. mdwFeatureSymbols, pglobl) ;
  1083. psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
  1084. dwRootOptions = psn[dwFeatureIndex].dwSubSpaceIndex ;
  1085. dwOptionID = DWsearchSymbolListForAAR(&aarOption, dwRootOptions, pglobl) ;
  1086. if(dwOptionID == INVALID_SYMBOLID)
  1087. {
  1088. ERR(("qualified name references a non-existent Option symbol: %0.*s\n",
  1089. aarOption.dw, aarOption.pub));
  1090. return(FALSE);
  1091. }
  1092. if(gdwResDLL_ID) // has already been initialized
  1093. {
  1094. if(gdwResDLL_ID != dwFeatureID)
  1095. {
  1096. ERR(("References to ResourceDLLs must be placed in the feature with symbolname: RESDLL.\n"));
  1097. return(FALSE);
  1098. }
  1099. }
  1100. else
  1101. gdwResDLL_ID = dwFeatureID ;
  1102. if(dwOptionID >= 0x80 )
  1103. {
  1104. ERR(("GPD may not reference more than 127 resource files.\n"));
  1105. return(FALSE);
  1106. }
  1107. // integer portion already set.
  1108. ((PQUALNAMEEX)pdwDest)->bFeatureID = (BYTE)dwFeatureID ;
  1109. ((PQUALNAMEEX)pdwDest)->bOptionID = (BYTE)dwOptionID ;
  1110. // if needed, clear high bit here!
  1111. ((PQUALNAMEEX)pdwDest)->bOptionID &= ~0x80 ;
  1112. return(TRUE);
  1113. }
  1114. BOOL BparsePartiallyQualifiedName
  1115. (
  1116. IN PABSARRAYREF paarValue,
  1117. IN PDWORD pdwDest, // write dword value here.
  1118. IN VALUE eAllowedValue, // which class of symbol is this?
  1119. IN PGLOBL pglobl
  1120. )
  1121. /* Similar to parseQualifiedName but will tolerate
  1122. a Featurename by itself.
  1123. in this case the optionID will be set to INVALID_SYMBOLID.
  1124. */
  1125. {
  1126. ABSARRAYREF aarFeature ; // points to FeatureName.
  1127. DWORD dwDelIndex ; // serves no purpose here.
  1128. DWORD dwFeatureID, dwFeatureIndex , dwRootOptions,
  1129. dwOptionID = 0;
  1130. PSYMBOLNODE psn ;
  1131. if(!BdelimitToken(paarValue, ".", &aarFeature, &dwDelIndex) )
  1132. {
  1133. aarFeature = *paarValue ; // initialize since BdelimitToken doesn't
  1134. dwOptionID = INVALID_SYMBOLID ;
  1135. }
  1136. if(! BeatSurroundingWhiteSpaces(&aarFeature) ) // holds feature
  1137. {
  1138. ERR(("no feature found in partially qualified value: %0.*s\n", paarValue->dw, paarValue->pub));
  1139. return(FALSE);
  1140. }
  1141. if(!dwOptionID &&
  1142. ! BeatSurroundingWhiteSpaces(paarValue) ) // holds option
  1143. {
  1144. ERR(("no option found after . in partially qualified value: %0.*s\n", paarValue->dw, paarValue->pub));
  1145. return(FALSE);
  1146. }
  1147. dwFeatureID = DWsearchSymbolListForAAR(&aarFeature, mdwFeatureSymbols, pglobl) ;
  1148. if(dwFeatureID == INVALID_SYMBOLID)
  1149. {
  1150. ERR(("qualified name references a non-existent Feature symbol: %0.*s\n", paarValue->dw, paarValue->pub));
  1151. return(FALSE);
  1152. }
  1153. dwFeatureIndex = DWsearchSymbolListForID(dwFeatureID,
  1154. mdwFeatureSymbols, pglobl);
  1155. psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
  1156. if(!dwOptionID)
  1157. {
  1158. dwRootOptions = psn[dwFeatureIndex].dwSubSpaceIndex ;
  1159. dwOptionID = DWsearchSymbolListForAAR(paarValue, dwRootOptions, pglobl) ;
  1160. if(dwOptionID == INVALID_SYMBOLID)
  1161. {
  1162. ERR(("qualified name references a non-existent Option symbol: %0.*s\n", paarValue->dw, paarValue->pub));
  1163. return(FALSE);
  1164. }
  1165. }
  1166. ((PQUALNAME)pdwDest)->wFeatureID = (WORD)dwFeatureID ;
  1167. ((PQUALNAME)pdwDest)->wOptionID = (WORD)dwOptionID ;
  1168. return(TRUE);
  1169. }
  1170. BOOL BparseOptionSymbol(
  1171. IN PABSARRAYREF paarValue,
  1172. IN PDWORD pdwDest, // write dword value here.
  1173. IN VALUE eAllowedValue, // which class of symbol is this?
  1174. IN PGLOBL pglobl
  1175. )
  1176. /* Note we assume any attribute expecting an OptionSymbol
  1177. must reside within a Feature Construct.
  1178. */
  1179. {
  1180. WORD wTstsInd ; // temp state stack index
  1181. STATE stState ;
  1182. DWORD dwFeatureID = 0, dwFeatureIndex , dwRootOptions;
  1183. PSYMBOLNODE psn ;
  1184. if( eAllowedValue != VALUE_SYMBOL_OPTIONS )
  1185. return(FALSE);
  1186. if(! BeatSurroundingWhiteSpaces(paarValue) )
  1187. return(FALSE);
  1188. for(wTstsInd = 0 ; wTstsInd < mdwCurStsPtr ; wTstsInd++)
  1189. {
  1190. stState = mpstsStateStack[wTstsInd].stState ;
  1191. if(stState == STATE_FEATURE )
  1192. {
  1193. dwFeatureID = mpstsStateStack[wTstsInd].dwSymbolID ;
  1194. break ;
  1195. }
  1196. }
  1197. if(wTstsInd >= mdwCurStsPtr)
  1198. return (FALSE) ;
  1199. dwFeatureIndex = DWsearchSymbolListForID(dwFeatureID,
  1200. mdwFeatureSymbols, pglobl) ;
  1201. psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
  1202. dwRootOptions = psn[dwFeatureIndex].dwSubSpaceIndex ;
  1203. *pdwDest = DWsearchSymbolListForAAR(paarValue, dwRootOptions, pglobl) ;
  1204. if(*pdwDest == INVALID_SYMBOLID)
  1205. {
  1206. ERR(("qualified name references a non-existent Option symbol: %0.*s\n", paarValue->dw, paarValue->pub));
  1207. return(FALSE);
  1208. }
  1209. return(TRUE);
  1210. }
  1211. BOOL BparseConstant(
  1212. IN OUT PABSARRAYREF paarValue,
  1213. OUT PDWORD pdwDest, // write dword value here.
  1214. IN VALUE eAllowedValue, // which class of constant is this?
  1215. IN PGLOBL pglobl
  1216. )
  1217. /* note: this function will destroy/modify paarValue, it will
  1218. only reference the constant name when done. */
  1219. {
  1220. DWORD dwClassIndex = eAllowedValue - VALUE_CONSTANT_FIRST ;
  1221. DWORD dwI, dwCount, dwStart , dwLen;
  1222. dwStart = gcieTable[dwClassIndex].dwStart ;
  1223. dwCount = gcieTable[dwClassIndex].dwCount ;
  1224. if(! BeatSurroundingWhiteSpaces(paarValue) )
  1225. return(FALSE);
  1226. for(dwI = 0 ; dwI < dwCount ; dwI++)
  1227. {
  1228. dwLen = strlen(gConstantsTable[dwStart + dwI].pubName);
  1229. if((dwLen == paarValue->dw) &&
  1230. !strncmp(paarValue->pub, gConstantsTable[dwStart + dwI].pubName,
  1231. paarValue->dw) )
  1232. {
  1233. *pdwDest = gConstantsTable[dwStart + dwI].dwValue ;
  1234. return(TRUE);
  1235. }
  1236. }
  1237. #if defined(DEVSTUDIO) // Keep messages to one line, where possible
  1238. ERR(("Error: constant value '%0.*s' is not a member of enumeration class: %s\n",
  1239. paarValue->dw , paarValue->pub, gConstantsTable[dwStart - 1].pubName));
  1240. #else
  1241. ERR(("Error: constant value not a member of enumeration class: %s\n", gConstantsTable[dwStart - 1].pubName));
  1242. ERR(("\t%0.*s\n", paarValue->dw , paarValue->pub )) ;
  1243. #endif
  1244. return(FALSE);
  1245. }
  1246. BOOL BinitClassIndexTable(
  1247. IN OUT PGLOBL pglobl)
  1248. {
  1249. DWORD dwOldClass, dwCTIndex ;
  1250. for(dwCTIndex = 0 ; dwCTIndex < CL_NUMCLASSES ; dwCTIndex++ )
  1251. {
  1252. gcieTable[dwCTIndex].dwStart = 0 ;
  1253. gcieTable[dwCTIndex].dwCount = 0 ; // set to known state.
  1254. }
  1255. dwOldClass = gConstantsTable[0].dwValue ;
  1256. gcieTable[dwOldClass].dwStart = 2 ; // index of first entry
  1257. for(dwCTIndex = 2 ; 1 ; dwCTIndex++ )
  1258. {
  1259. if(!gConstantsTable[dwCTIndex].pubName)
  1260. {
  1261. gcieTable[dwOldClass].dwCount =
  1262. dwCTIndex - gcieTable[dwOldClass].dwStart ;
  1263. dwOldClass = gConstantsTable[dwCTIndex].dwValue ;
  1264. if(dwOldClass == CL_NUMCLASSES)
  1265. break ; // reached end of table.
  1266. gcieTable[dwOldClass].dwStart = dwCTIndex + 2 ;
  1267. }
  1268. }
  1269. for(dwCTIndex = 0 ; dwCTIndex < CL_NUMCLASSES ; dwCTIndex++ )
  1270. {
  1271. if(!gcieTable[dwCTIndex].dwCount)
  1272. {
  1273. geErrorSev = ERRSEV_FATAL ;
  1274. geErrorType = ERRTY_CODEBUG ;
  1275. return(FALSE) ; // paranoid - some classes not
  1276. }
  1277. } // listed in gConstantsTable[] .
  1278. return(TRUE) ;
  1279. }
  1280. BOOL BparseRect(
  1281. IN PABSARRAYREF paarValue,
  1282. IN PRECT prcDest,
  1283. PGLOBL pglobl
  1284. )
  1285. /* note: integers initialize the rect structure in memory
  1286. in the order in which they appear. First int initializes
  1287. the lowest memory location and so on.
  1288. */
  1289. {
  1290. ABSARRAYREF aarToken ; // points to individual value.
  1291. DWORD dwDelIndex ; // if BdelimitToken
  1292. // found a delimiter, this contains the index to pubDelimiters
  1293. // of the delimiter that was found.
  1294. DWORD dwI ; // number integers in RECT
  1295. if(! BeatDelimiter(paarValue, "RECT"))
  1296. {
  1297. ERR(("expected token 'RECT'.\n"));
  1298. return(FALSE) ;
  1299. }
  1300. if(! BeatDelimiter(paarValue, "("))
  1301. {
  1302. ERR(("syntax error: missing '(' after RECT.\n"));
  1303. return(FALSE) ;
  1304. }
  1305. for(dwI = dwDelIndex = 0 ; dwI < 4 && dwDelIndex != 1 ; dwI++)
  1306. {
  1307. if(!BdelimitToken(paarValue, ",)", &aarToken, &dwDelIndex) )
  1308. {
  1309. ERR(("missing terminating ) in RECT construct.\n"));
  1310. // emit message for user.
  1311. return(FALSE) ;
  1312. }
  1313. if(!BparseInteger(&aarToken, (PDWORD)prcDest + dwI, VALUE_INTEGER, pglobl))
  1314. {
  1315. ERR(("syntax error in %d th integer of RECT.\n", dwI));
  1316. ERR(("\t%0.*s\n", aarToken.dw, aarToken.pub));
  1317. return(FALSE) ;
  1318. }
  1319. }
  1320. if(dwI != 4 || dwDelIndex != 1)
  1321. {
  1322. ERR(("incorrect number of integers for RECT.\n"));
  1323. return(FALSE) ;
  1324. }
  1325. // verify there is nothing else in statement.
  1326. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  1327. if(paarValue->dw)
  1328. {
  1329. ERR(("extraneous characters found after the end of the RECT construct: %0.*s\n", paarValue->dw, paarValue->pub));
  1330. // may want to print them out.
  1331. // not a fatal condition, continue.
  1332. }
  1333. return(TRUE) ;
  1334. }
  1335. BOOL BparsePoint(
  1336. IN PABSARRAYREF paarValue,
  1337. IN PPOINT pptDest,
  1338. PGLOBL pglobl
  1339. )
  1340. {
  1341. ABSARRAYREF aarToken ; // points to individual value.
  1342. DWORD dwDelIndex ; // if BdelimitToken
  1343. // found a delimiter, this contains the index to pubDelimiters
  1344. // of the delimiter that was found.
  1345. DWORD dwI ; // number integers in POINT
  1346. if(! BeatDelimiter(paarValue, "PAIR"))
  1347. {
  1348. ERR(("expected token 'PAIR'.\n"));
  1349. return(FALSE) ;
  1350. }
  1351. if(! BeatDelimiter(paarValue, "("))
  1352. {
  1353. ERR(("syntax error: missing '(' after PAIR.\n"));
  1354. return(FALSE) ;
  1355. }
  1356. for(dwI = dwDelIndex = 0 ; dwI < 2 && dwDelIndex != 1 ; dwI++)
  1357. {
  1358. if(!BdelimitToken(paarValue, ",)", &aarToken, &dwDelIndex) )
  1359. {
  1360. ERR(("missing terminating ) in PAIR construct.\n"));
  1361. // emit message for user.
  1362. return(FALSE) ;
  1363. }
  1364. if(!BparseInteger(&aarToken, (PDWORD)pptDest + dwI, VALUE_INTEGER, pglobl))
  1365. {
  1366. ERR(("syntax error in %d th integer of PAIR.\n", dwI));
  1367. ERR(("\t%0.*s\n", aarToken.dw, aarToken.pub));
  1368. return(FALSE) ;
  1369. }
  1370. }
  1371. if(dwI != 2 || dwDelIndex != 1)
  1372. {
  1373. ERR(("incorrect number of integers for PAIR.\n"));
  1374. return(FALSE) ;
  1375. }
  1376. // verify there is nothing else in statement.
  1377. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  1378. if(paarValue->dw)
  1379. {
  1380. ERR(("extraneous characters found after the end of the PAIR construct: %0.*s\n", paarValue->dw, paarValue->pub));
  1381. }
  1382. return(TRUE) ;
  1383. }
  1384. BOOL BparseString(
  1385. IN PABSARRAYREF paarValue,
  1386. IN PARRAYREF parStrValue,
  1387. IN OUT PGLOBL pglobl
  1388. )
  1389. /* strings are comprised of one or more string segments separated
  1390. by optional arbitrary whitespace,
  1391. each string segment is surrounded by double quotes.
  1392. string segments may contain a mixture of literal sections
  1393. and hexsubstrings. Hexsubstrings are delimited by angle brackets.
  1394. WhiteSpaces (but not linebreak chars) are permitted in the
  1395. literal portion of the string, they part of the string.
  1396. Otherwise only printable chars are allowed.
  1397. Valid hexchars and Arbitrary whitespace is permitted
  1398. within the hexsubstrings. Parsing of a string value ends
  1399. when a statement terminator is encountered.
  1400. The escape char %
  1401. Within the literal portion of a string segment
  1402. the following combinations are reinterpreted:
  1403. %< maps to literal <
  1404. %" maps to literal "
  1405. > only has a special meaning within a hexsubstring.
  1406. Assumption: assumes the only heap usage that occurs
  1407. within this function (and any called functions) is
  1408. to assemble all string segments contiguously on the heap.
  1409. Any hidden use of the heap will corrupt the continuity.
  1410. the string may be terminated by : if a second value field is expected.
  1411. */
  1412. {
  1413. ABSARRAYREF aarToken ; // points to individual string segment.
  1414. DWORD dwDelIndex ; // dummy
  1415. DWORD dwI ; // number of string segments parsed.
  1416. if(! BeatDelimiter(paarValue, "\""))
  1417. {
  1418. ERR(("syntax error: string must begin with '\"' .\n"));
  1419. return(FALSE) ;
  1420. }
  1421. parStrValue->dwCount = 0 ; // initialize so BparseStrSegment
  1422. // will overwrite instead of append
  1423. for(dwI = dwDelIndex = 0 ; 1 ; dwI++)
  1424. {
  1425. if(!BdelimitToken(paarValue, "\"", &aarToken, &dwDelIndex) )
  1426. {
  1427. ERR(("missing terminating '\"' in string.\n"));
  1428. // emit message for user.
  1429. return(FALSE) ;
  1430. }
  1431. if(!BparseStrSegment(&aarToken, parStrValue, pglobl))
  1432. {
  1433. return(FALSE) ;
  1434. }
  1435. if(! BeatDelimiter(paarValue, "\"")) // find start of next
  1436. // string segment, if one exists.
  1437. break ;
  1438. }
  1439. // verify there is either a specially recognized character
  1440. // or nothing else in Value string.
  1441. if(paarValue->dw)
  1442. {
  1443. if(*paarValue->pub == ':')
  1444. {
  1445. // a keyword with a composite value
  1446. (VOID)BeatDelimiter(paarValue, ":") ;
  1447. // I know this will succeed!
  1448. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  1449. return(TRUE) ;
  1450. }
  1451. else
  1452. {
  1453. ERR(("extraneous characters found after end quote, in string construct: %0.*s\n", paarValue->dw, paarValue->pub));
  1454. // may want to print them out.
  1455. return(FALSE) ;
  1456. }
  1457. }
  1458. return(TRUE) ;
  1459. }
  1460. BOOL BparseAndTerminateString(
  1461. IN PABSARRAYREF paarValue,
  1462. IN PARRAYREF parStrValue,
  1463. IN VALUE eAllowedValue,
  1464. IN OUT PGLOBL pglobl
  1465. )
  1466. {
  1467. ARRAYREF arSrcString ;
  1468. INT iCodepage ; // unused for now.
  1469. if(!BparseString(paarValue, parStrValue, pglobl) )
  1470. return(FALSE) ;
  1471. // We don't want null terminations to occur between parameter
  1472. // portion of a string. We just want to blindly add the NULL
  1473. // when parsing is really finished.
  1474. {
  1475. DWORD dwDummy ; // holds offset in heap, but we don't care.
  1476. if(!BwriteToHeap(&dwDummy, "\0", 1, 1, pglobl) ) // add Null termination
  1477. return(FALSE) ;
  1478. }
  1479. if(eAllowedValue == VALUE_STRING_NO_CONVERT)
  1480. return(TRUE) ;
  1481. if(eAllowedValue == VALUE_STRING_CP_CONVERT)
  1482. {
  1483. // we need to determine the value set by *CodePage
  1484. PGLOBALATTRIB pga ;
  1485. DWORD dwHeapOffset;
  1486. pga = (PGLOBALATTRIB)gMasterTable[
  1487. MTI_GLOBALATTRIB].pubStruct ;
  1488. if(!BReadDataInGlobalNode(&pga->atrCodePage,
  1489. &dwHeapOffset, pglobl) )
  1490. return(TRUE);
  1491. // if no codepage is defined, we will not perform
  1492. // any xlation since we assume all strings are already
  1493. // expressed in unicode.
  1494. iCodepage = *(PDWORD)(mpubOffRef + dwHeapOffset) ;
  1495. }
  1496. else // eAllowedValue == VALUE_STRING_DEF_CONVERT
  1497. iCodepage = CP_ACP ; // use system default codepage.
  1498. arSrcString = *parStrValue ;
  1499. if(!BwriteUnicodeToHeap(&arSrcString, parStrValue,
  1500. iCodepage, pglobl))
  1501. return(FALSE) ;
  1502. return(TRUE) ;
  1503. }
  1504. BOOL BwriteUnicodeToHeap(
  1505. IN PARRAYREF parSrcString,
  1506. OUT PARRAYREF parUnicodeString,
  1507. IN INT iCodepage,
  1508. IN OUT PGLOBL pglobl
  1509. )
  1510. // this function copies dwCnt bytes from pubSrc to
  1511. // top of heap and writes the offset of the destination string
  1512. // to pdwDestOff. Nothing is changed if FAILS.
  1513. // Warning! Double Null termination is added to string.
  1514. {
  1515. PBYTE pubDest ; // destination location
  1516. PBYTE pubSrc ; // points to src string
  1517. DWORD dwAlign = sizeof(WCHAR) ; // align Unicode string at WORD boundaries.
  1518. DWORD dwMaxDestSize , dwActDestSize, dwDummy ;
  1519. mloCurHeap = (mloCurHeap + dwAlign - 1) / dwAlign ;
  1520. mloCurHeap *= dwAlign ;
  1521. pubDest = mpubOffRef + mloCurHeap ;
  1522. pubSrc = mpubOffRef + parSrcString->loOffset ;
  1523. parUnicodeString->loOffset = mloCurHeap ;
  1524. dwMaxDestSize = sizeof(WCHAR) * (parSrcString->dwCount + 1) ;
  1525. // is there enough room in the heap ?
  1526. if(mloCurHeap + dwMaxDestSize > mdwMaxHeap)
  1527. {
  1528. ERR(("Heap exhausted - restart.\n"));
  1529. if(ERRSEV_RESTART > geErrorSev)
  1530. {
  1531. geErrorSev = ERRSEV_RESTART ;
  1532. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  1533. gdwMasterTabIndex = MTI_STRINGHEAP ;
  1534. }
  1535. return(FALSE);
  1536. }
  1537. dwActDestSize = sizeof(WCHAR) * MultiByteToWideChar(iCodepage,
  1538. MB_PRECOMPOSED, pubSrc, parSrcString->dwCount, (PWORD)pubDest,
  1539. dwMaxDestSize);
  1540. mloCurHeap += dwActDestSize ; // update heap ptr.
  1541. parUnicodeString->dwCount = dwActDestSize ;
  1542. (VOID)BwriteToHeap(&dwDummy, "\0\0", 2, 1, pglobl) ;
  1543. // add DoubleNull termination
  1544. // this cannot fail since we already took the NULs into account
  1545. return(TRUE) ;
  1546. }
  1547. BOOL BparseStrSegment(
  1548. IN PABSARRAYREF paarStrSeg, // source str segment
  1549. IN PARRAYREF parStrLiteral, // dest for result
  1550. IN OUT PGLOBL pglobl
  1551. )
  1552. {
  1553. ABSARRAYREF aarToken ; // points to literal or hex substring segment.
  1554. DWORD dwDelIndex ; // dummy
  1555. DWORD dwI ; // number of string segments parsed.
  1556. for(dwI = dwDelIndex = 0 ; 1 ; dwI++)
  1557. {
  1558. if(!BdelimitToken(paarStrSeg, "<", &aarToken, &dwDelIndex) )
  1559. {
  1560. // no more hex substrings.
  1561. return(BparseStrLiteral(paarStrSeg, parStrLiteral, pglobl) ) ;
  1562. }
  1563. if(!BparseStrLiteral(&aarToken, parStrLiteral, pglobl))
  1564. {
  1565. return(FALSE) ;
  1566. }
  1567. if(!BdelimitToken(paarStrSeg, ">", &aarToken, &dwDelIndex) )
  1568. {
  1569. ERR(("Missing '>' terminator in hexsubstring.\n"));
  1570. return(FALSE) ;
  1571. }
  1572. if(!(BparseHexStr(&aarToken, parStrLiteral, pglobl) ) )
  1573. return(FALSE) ;
  1574. }
  1575. return TRUE;
  1576. }
  1577. BOOL BparseStrLiteral(
  1578. IN PABSARRAYREF paarStrSeg, // points to literal substring segment.
  1579. IN PARRAYREF parStrLiteral, // dest for result
  1580. IN OUT PGLOBL pglobl
  1581. )
  1582. /* in this function all delimiters have been parsed out.
  1583. only special character sequence is %" and %<
  1584. Does not Null terminate heap string
  1585. */
  1586. {
  1587. ARRAYREF arTmpDest ; // write result here first.
  1588. DWORD dwI ; // byte index along literal substring
  1589. PBYTE pubStartRun ;
  1590. while(paarStrSeg->dw)
  1591. {
  1592. pubStartRun = paarStrSeg->pub ;
  1593. for(dwI = 0 ; paarStrSeg->dw ; dwI++)
  1594. {
  1595. if(*paarStrSeg->pub == '%' && paarStrSeg->dw > 1 &&
  1596. (paarStrSeg->pub[1] == '"' || paarStrSeg->pub[1] == '<'))
  1597. {
  1598. paarStrSeg->dw-- ; // skip the escape char.
  1599. paarStrSeg->pub++ ;
  1600. break ;
  1601. }
  1602. paarStrSeg->dw-- ;
  1603. paarStrSeg->pub++ ;
  1604. }
  1605. if(!BwriteToHeap(&arTmpDest.loOffset, pubStartRun, dwI, 1, pglobl))
  1606. return(FALSE) ;
  1607. // append this run to existing string
  1608. if(!parStrLiteral->dwCount) // no prevs string exists
  1609. {
  1610. parStrLiteral->loOffset = arTmpDest.loOffset ;
  1611. }
  1612. else
  1613. {
  1614. // BUG_BUG paranoid: may check that string is contiguous
  1615. // parStrLiteral->loOffset + parStrLiteral->dwCount
  1616. // should equal arTmpDest.loOffset
  1617. ASSERT(parStrLiteral->loOffset + parStrLiteral->dwCount == arTmpDest.loOffset );
  1618. }
  1619. parStrLiteral->dwCount += dwI ;
  1620. }
  1621. return(TRUE) ;
  1622. }
  1623. BOOL BparseHexStr(
  1624. IN PABSARRAYREF paarStrSeg, // points to hex substring segment.
  1625. IN PARRAYREF parStrLiteral, // dest for result
  1626. IN OUT PGLOBL pglobl
  1627. )
  1628. /* in this function all delimiters have been parsed out.
  1629. only Whitespace and hex chars should exist.
  1630. Does not Null terminate heap string
  1631. */
  1632. {
  1633. ARRAYREF arTmpDest ; // write result here first.
  1634. DWORD dwI ; // num dest bytes
  1635. BYTE ubHex, ubSrc, aub[40] ; // accumulate hexbytes here
  1636. BOOL bHigh = TRUE ;
  1637. while(paarStrSeg->dw)
  1638. {
  1639. for(dwI = 0 ; paarStrSeg->dw ; )
  1640. {
  1641. ubSrc = *paarStrSeg->pub ;
  1642. paarStrSeg->dw-- ;
  1643. paarStrSeg->pub++ ;
  1644. if(ubSrc >= '0' && ubSrc <= '9')
  1645. {
  1646. ubHex = ubSrc - '0' ;
  1647. }
  1648. else if(ubSrc >= 'a' && ubSrc <= 'f')
  1649. {
  1650. ubHex = ubSrc - 'a' + 10 ;
  1651. }
  1652. else if(ubSrc >= 'A' && ubSrc <= 'F')
  1653. {
  1654. ubHex = ubSrc - 'A' + 10 ;
  1655. }
  1656. else if(ubSrc == ' ' || ubSrc == '\t')
  1657. continue; // safe to ignore whitespace chars
  1658. else
  1659. {
  1660. ERR(("syntax error: illegal char found within hexsubstring: %c\n", ubSrc));
  1661. return(FALSE) ;
  1662. }
  1663. if(bHigh)
  1664. {
  1665. aub[dwI] = ubHex << 4 ; // store in high nibble.
  1666. bHigh = FALSE ;
  1667. }
  1668. else
  1669. {
  1670. aub[dwI] |= ubHex ; // store in low nibble.
  1671. bHigh = TRUE ;
  1672. dwI++ ; // advance to next dest byte
  1673. }
  1674. if(dwI >= 40)
  1675. break ; // buffer full -- must flush aub
  1676. }
  1677. if(!BwriteToHeap(&arTmpDest.loOffset, aub, dwI, 1, pglobl))
  1678. return(FALSE) ;
  1679. // append this run to existing string
  1680. if(!parStrLiteral->dwCount) // no prevs string exists
  1681. {
  1682. parStrLiteral->loOffset = arTmpDest.loOffset ;
  1683. }
  1684. else
  1685. {
  1686. // BUG_BUG paranoid: may check that string is contiguous
  1687. // parStrLiteral->loOffset + parStrLiteral->dwCount
  1688. // should equal arTmpDest.loOffset
  1689. ASSERT(parStrLiteral->loOffset + parStrLiteral->dwCount == arTmpDest.loOffset );
  1690. }
  1691. parStrLiteral->dwCount += dwI ;
  1692. }
  1693. if(!bHigh)
  1694. {
  1695. ERR(("hex string contains odd number of hex digits.\n"));
  1696. }
  1697. return(bHigh) ;
  1698. }
  1699. BOOL BparseOrderDep(
  1700. IN PABSARRAYREF paarValue,
  1701. IN PORDERDEPENDENCY pordDest,
  1702. PGLOBL pglobl
  1703. )
  1704. // an order dependency value has the syntax:
  1705. // SECTION.integer
  1706. {
  1707. ABSARRAYREF aarSection ; // points to SECTION token
  1708. DWORD dwDelIndex ; // if BdelimitToken
  1709. // found a delimiter, this contains the index to pubDelimiters
  1710. // of the delimiter that was found.
  1711. DWORD dwI ; // number integers in RECT
  1712. if(!BdelimitToken(paarValue, ".", &aarSection, &dwDelIndex) )
  1713. {
  1714. ERR(("required delimiter '.' missing in order dependency value.\n"));
  1715. return(FALSE);
  1716. }
  1717. if(!BparseConstant(&aarSection, (PDWORD)&(pordDest->eSection),
  1718. VALUE_CONSTANT_SEQSECTION , pglobl))
  1719. {
  1720. ERR(("A valid orderdep SECTION name was not supplied: %0.*s\n", aarSection.dw, aarSection.pub));
  1721. return(FALSE);
  1722. }
  1723. // now interpret remainder of paarValue as an integer.
  1724. if(!BparseInteger(paarValue, &(pordDest->dwOrder), VALUE_INTEGER, pglobl))
  1725. {
  1726. ERR(("syntax error in integer portion of order dependency.\n"));
  1727. return(FALSE) ;
  1728. }
  1729. // verify there is nothing else in statement.
  1730. (VOID) BeatLeadingWhiteSpaces(paarValue) ;
  1731. if(paarValue->dw)
  1732. {
  1733. ERR(("extraneous characters found after the end of the orderDependency value: %0.*s\n",
  1734. paarValue->dw, paarValue->pub));
  1735. // may want to print them out.
  1736. // not a fatal condition, continue.
  1737. }
  1738. return(TRUE) ;
  1739. }
  1740. PDWORD pdwEndOfList(
  1741. PDWORD pdwNodeIndex, // index of first node in the list
  1742. PGLOBL pglobl)
  1743. // walks the list and returns pointer to field containing the
  1744. // actual END_OF_LIST value so it can be overwritten to
  1745. // extend the list.
  1746. {
  1747. PLISTNODE plstRoot ; // start of LIST array
  1748. DWORD dwNodeIndex , dwPrevsNode, dwFirstNode;
  1749. plstRoot = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
  1750. dwNodeIndex = *pdwNodeIndex ;
  1751. if(dwNodeIndex == END_OF_LIST )
  1752. return(pdwNodeIndex); // no actual node referenced.
  1753. while(plstRoot[dwNodeIndex].dwNextItem != END_OF_LIST )
  1754. dwNodeIndex = plstRoot[dwNodeIndex].dwNextItem ;
  1755. return(&plstRoot[dwNodeIndex].dwNextItem);
  1756. }
  1757. #ifdef GMACROS
  1758. PBYTE ExtendChain(PBYTE pubDest,
  1759. IN BOOL bOverWrite,
  1760. IN OUT PGLOBL pglobl)
  1761. // Links together values from separate entries into one LIST
  1762. // the values may be of any type. If the values are LISTS, this
  1763. // modifier creates LISTS of LISTS.
  1764. // returns new value of pubDest
  1765. {
  1766. DWORD dwNodeIndex;
  1767. PLISTNODE plstRoot ; // start of LIST array
  1768. plstRoot = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
  1769. if(bOverWrite)
  1770. pubDest = (PBYTE)pdwEndOfList((PDWORD)pubDest, pglobl); // walks the list and returns pointer
  1771. // to the actual END_OF_LIST value so it can be overwritten to
  1772. // extend the list.
  1773. // Add one list node and write its index to pubDest.
  1774. // set nextnode field of node just added to END_OF_LIST.
  1775. if(! BallocElementFromMasterTable(MTI_LISTNODES ,
  1776. &dwNodeIndex, pglobl) )
  1777. {
  1778. return(NULL) ;
  1779. }
  1780. plstRoot[dwNodeIndex].dwNextItem = END_OF_LIST ;
  1781. *(PDWORD)pubDest = dwNodeIndex ;
  1782. // update pubDest to point to value field of of the node just added.
  1783. // now the LIST() we will now proceed to parse will grow from this
  1784. // value field.
  1785. pubDest = (PBYTE)&(plstRoot[dwNodeIndex].dwData) ;
  1786. return(pubDest) ;
  1787. }
  1788. #endif