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.

1125 lines
37 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. /* state2.c - create, manage the attribute tree */
  3. #include "gpdparse.h"
  4. // ---- functions defined in state2.c ---- //
  5. BOOL BprocessAttribute(
  6. PTKMAP ptkmap, // pointer to tokenmap
  7. PGLOBL pglobl
  8. ) ;
  9. BOOL BstoreFontCartAttrib(
  10. PTKMAP ptkmap, // pointer to tokenmap
  11. PGLOBL pglobl
  12. ) ;
  13. BOOL BstoreTTFontSubAttrib(
  14. PTKMAP ptkmap, // pointer to tokenmap
  15. PGLOBL pglobl
  16. ) ;
  17. BOOL BstoreCommandAttrib(
  18. PTKMAP ptkmap, // pointer to tokenmap
  19. PGLOBL pglobl
  20. ) ;
  21. BOOL BstoreFeatureOptionAttrib(
  22. PTKMAP ptkmap, // pointer to tokenmap
  23. PGLOBL pglobl
  24. ) ;
  25. BOOL BstoreGlobalAttrib(
  26. PTKMAP ptkmap, // pointer to tokenmap
  27. PGLOBL pglobl
  28. ) ;
  29. BOOL BaddBranchToTree(
  30. PTKMAP ptkmap, // pointer to tokenmap
  31. PATREEREF patrAttribRoot, // pointer to dword with index
  32. PGLOBL pglobl
  33. ) ;
  34. BOOL BcreateGlobalInitializerNode(
  35. PDWORD pdwNodeIndex,
  36. DWORD dwOffset,
  37. PGLOBL pglobl) ;
  38. BOOL BcreateEndNode(
  39. PDWORD pdwNodeIndex,
  40. DWORD dwFeature,
  41. DWORD dwOption,
  42. PGLOBL pglobl
  43. ) ;
  44. BOOL BfindOrCreateMatchingNode(
  45. IN DWORD dwRootNodeIndex , // first node in chain matching feature
  46. OUT PDWORD pdwNodeIndex, // points to node in chain also matching option
  47. DWORD dwFeatureID, //
  48. DWORD dwOptionID, // may even take on the value DEFAULT_INIT
  49. PGLOBL pglobl
  50. ) ;
  51. BOOL BfindMatchingNode(
  52. IN DWORD dwRootNodeIndex , // first node in chain matching feature
  53. OUT PDWORD pdwNodeIndex, // points to node in chain also matching option
  54. DWORD dwFeatureID,
  55. DWORD dwOptionID, // may even take on the value DEFAULT_INIT
  56. PGLOBL pglobl
  57. ) ;
  58. BOOL BallocElementFromMasterTable(
  59. MT_INDICIES eMTIndex, // select type of structure desired.
  60. PDWORD pdwNodeIndex,
  61. PGLOBL pglobl) ;
  62. BOOL BreturnElementFromMasterTable(
  63. MT_INDICIES eMTIndex, // select type of structure desired.
  64. DWORD dwNodeIndex,
  65. PGLOBL pglobl) ;
  66. BOOL BconvertSymCmdIDtoUnidrvID(
  67. IN DWORD dwCommandID , // from RegisterSymbol
  68. OUT PDWORD pdwUnidrvID,
  69. PGLOBL pglobl
  70. ) ;
  71. // ---------------------------------------------------- //
  72. BOOL BprocessAttribute(
  73. PTKMAP ptkmap, // pointer to tokenmap
  74. PGLOBL pglobl
  75. )
  76. {
  77. DWORD dwKeywordID ;
  78. CONSTRUCT eSubType ;
  79. BOOL bStatus = FALSE ;
  80. STATE stState;
  81. dwKeywordID = ptkmap->dwKeywordID ;
  82. eSubType = (ATTRIBUTE)(mMainKeywordTable[dwKeywordID].dwSubType) ;
  83. if(mdwCurStsPtr)
  84. stState = mpstsStateStack[mdwCurStsPtr - 1].stState ;
  85. else
  86. stState = STATE_ROOT ;
  87. if(!(gabAllowedAttributes[stState][eSubType]))
  88. {
  89. vIdentifySource(ptkmap, pglobl) ;
  90. ERR(("the Keyword %0.*s is not allowed within the state: %s\n",
  91. ptkmap->aarKeyword.dw, ptkmap->aarKeyword.pub,
  92. gpubStateNames[stState]));
  93. return(FALSE) ;
  94. }
  95. switch(eSubType)
  96. {
  97. case ATT_GLOBAL_ONLY:
  98. case ATT_GLOBAL_FREEFLOAT:
  99. {
  100. bStatus = BstoreGlobalAttrib(ptkmap, pglobl) ;
  101. break ;
  102. }
  103. case ATT_LOCAL_FEATURE_ONLY:
  104. case ATT_LOCAL_FEATURE_FF:
  105. case ATT_LOCAL_OPTION_ONLY:
  106. case ATT_LOCAL_OPTION_FF:
  107. {
  108. bStatus = BstoreFeatureOptionAttrib(ptkmap, pglobl) ;
  109. break ;
  110. }
  111. case ATT_LOCAL_COMMAND_ONLY:
  112. {
  113. bStatus = BstoreCommandAttrib(ptkmap, pglobl) ;
  114. break ;
  115. }
  116. case ATT_LOCAL_FONTCART_ONLY:
  117. {
  118. bStatus = BstoreFontCartAttrib(ptkmap, pglobl) ;
  119. break ;
  120. }
  121. case ATT_LOCAL_TTFONTSUBS_ONLY:
  122. {
  123. bStatus = BstoreTTFontSubAttrib(ptkmap, pglobl) ;
  124. break ;
  125. }
  126. case ATT_LOCAL_OEM_ONLY:
  127. default:
  128. {
  129. // currently there are no dedicated keywords
  130. // for these states.
  131. // see ProcessSymbolKeyword() which is called elsewhere.
  132. break ;
  133. }
  134. }
  135. return(bStatus) ;
  136. }
  137. BOOL BstoreFontCartAttrib(
  138. PTKMAP ptkmap, // pointer to tokenmap
  139. PGLOBL pglobl
  140. )
  141. /* assume the FontCartID is stored in the state stack
  142. whenever a FontCart construct is encountered.
  143. FontCart info is not multivalued. Thus all binary
  144. info is stored directly into an array of fontcart
  145. structures indexed by FontCartID.
  146. */
  147. {
  148. DWORD dwFontCartID = INVALID_SYMBOLID ;
  149. DWORD dwTstsInd, dwTstsInd2 ;
  150. STATE stState ;
  151. for(dwTstsInd = 0 ; dwTstsInd < mdwCurStsPtr ; dwTstsInd++)
  152. {
  153. dwTstsInd2 = mdwCurStsPtr - (1 + dwTstsInd) ;
  154. // this is the safe way of decrementing an unsigned index
  155. stState = mpstsStateStack[dwTstsInd2].stState ;
  156. if(stState == STATE_FONTCART)
  157. {
  158. dwFontCartID = mpstsStateStack[dwTstsInd2].dwSymbolID ;
  159. break ;
  160. // parser can't even recognize a fontcart attribute
  161. // outside of STATE_FONTCART so this path is 100% certain
  162. }
  163. }
  164. if(dwFontCartID == INVALID_SYMBOLID)
  165. {
  166. // BUG_BUG! - what does this imply? how could
  167. // this situation occur?
  168. return(FALSE) ;
  169. }
  170. if (!BaddValueToHeap(&dwFontCartID,
  171. ptkmap, TRUE, pglobl))
  172. {
  173. return(FALSE) ;
  174. }
  175. return(TRUE) ;
  176. }
  177. BOOL BstoreTTFontSubAttrib(
  178. PTKMAP ptkmap, // pointer to tokenmap
  179. PGLOBL pglobl
  180. )
  181. /* assume the TTFontSubID is stored in the state stack
  182. whenever a TTFontSub construct is encountered.
  183. TTFontSub info is not multivalued. Thus all binary
  184. info is stored directly into an array of TTFontSub
  185. structures indexed by TTFontSubID.
  186. */
  187. {
  188. DWORD dwTTFSID = INVALID_SYMBOLID ;
  189. DWORD dwTstsInd, dwTstsInd2 ;
  190. STATE stState ;
  191. for(dwTstsInd = 0 ; dwTstsInd < mdwCurStsPtr ; dwTstsInd++)
  192. {
  193. dwTstsInd2 = mdwCurStsPtr - (1 + dwTstsInd) ;
  194. // this is the safe way of decrementing an unsigned index
  195. stState = mpstsStateStack[dwTstsInd2].stState ;
  196. if(stState == STATE_TTFONTSUBS)
  197. {
  198. dwTTFSID = mpstsStateStack[dwTstsInd2].dwSymbolID ;
  199. break ;
  200. // parser can't even recognize a TTfontsub attribute
  201. // outside of STATE_TTFONTSUBS so this path is 100% certain
  202. }
  203. }
  204. if(dwTTFSID == INVALID_SYMBOLID)
  205. {
  206. // BUG_BUG! - what does this imply? how could
  207. // this situation occur?
  208. return(FALSE) ;
  209. }
  210. if (!BaddValueToHeap(&dwTTFSID,
  211. ptkmap, TRUE, pglobl))
  212. {
  213. return(FALSE) ;
  214. }
  215. return(TRUE) ;
  216. }
  217. BOOL BstoreCommandAttrib(
  218. PTKMAP ptkmap, // pointer to tokenmap
  219. PGLOBL pglobl
  220. )
  221. /* assume CreateTokenMap has parsed the CommandName
  222. (the value after the *Command keyword.) and converted
  223. it to a CommandID storing it in dwValue.
  224. further assume the CommandID is stored in the state stack
  225. whenever a COMMAND construct is encountered.
  226. */
  227. {
  228. BOOL bStatus = FALSE ;
  229. DWORD dwCommandID = INVALID_SYMBOLID, dwUnidrvID ;
  230. // remember the CommandID is issued by the parser
  231. // on a first come first served basis, the dwUnidrvID
  232. // is predefined.
  233. DWORD dwTstsInd, dwTstsInd2 ; // temp state stack index
  234. STATE stState ;
  235. PATREEREF patr ;
  236. for(dwTstsInd = 0 ; dwTstsInd < mdwCurStsPtr ; dwTstsInd++)
  237. {
  238. dwTstsInd2 = mdwCurStsPtr - (1 + dwTstsInd) ;
  239. // this is the safe way of decrementing an unsigned index
  240. stState = mpstsStateStack[dwTstsInd2].stState ;
  241. if(stState == STATE_COMMAND )
  242. {
  243. dwCommandID = mpstsStateStack[dwTstsInd2].dwSymbolID ;
  244. break ;
  245. // parser can't even recognize a command attribute
  246. // outside of STATE_COMMAND so this path is 100% certain
  247. }
  248. }
  249. if(dwCommandID == INVALID_SYMBOLID)
  250. {
  251. vIdentifySource(ptkmap, pglobl) ;
  252. ERR(("Internal error: BstoreCommandAttrib - invalid CommandID.\n"));
  253. return(FALSE) ;
  254. }
  255. if(!BconvertSymCmdIDtoUnidrvID( dwCommandID , &dwUnidrvID, pglobl) )
  256. {
  257. vIdentifySource(ptkmap, pglobl) ;
  258. ERR(("unrecognized Unidrv command name: *%0.*s.\n",
  259. ptkmap->aarValue.dw,
  260. ptkmap->aarValue.pub));
  261. return(FALSE) ;
  262. }
  263. if(dwUnidrvID == CMD_SELECT)
  264. {
  265. PDFEATURE_OPTIONS pfo ;
  266. DWORD dwFeatureID ;
  267. for(dwTstsInd = 0 ; dwTstsInd < dwTstsInd2 ; dwTstsInd++)
  268. {
  269. stState = mpstsStateStack[dwTstsInd].stState ;
  270. if(stState == STATE_FEATURE )
  271. {
  272. BOOL bInsideOpt ;
  273. dwFeatureID = mpstsStateStack[dwTstsInd].dwSymbolID ;
  274. for(bInsideOpt = FALSE , dwTstsInd++ ; dwTstsInd < dwTstsInd2 ;
  275. dwTstsInd++)
  276. {
  277. stState = mpstsStateStack[dwTstsInd].stState ;
  278. if(stState == STATE_OPTIONS )
  279. bInsideOpt = TRUE ;
  280. }
  281. if(!bInsideOpt)
  282. break ; // CmdSelect must reside within an option.
  283. pfo = (PDFEATURE_OPTIONS)
  284. gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct +
  285. dwFeatureID ;
  286. bStatus = BaddBranchToTree(ptkmap, &(pfo->atrCommandIndex), pglobl) ;
  287. return(bStatus) ;
  288. }
  289. }
  290. vIdentifySource(ptkmap, pglobl) ;
  291. ERR(("syntax err: the CmdSelect specifier can only be used inside an Option construct.\n"));
  292. return(FALSE) ;
  293. }
  294. // else CommandID refers to a predefined Unidrv command.
  295. // figure out address of command table.
  296. patr = (PATREEREF) gMasterTable[MTI_COMMANDTABLE].pubStruct ;
  297. bStatus = BaddBranchToTree(ptkmap, patr + dwUnidrvID, pglobl) ;
  298. // note: assumes commandtable is large enough.
  299. return(bStatus) ;
  300. }
  301. BOOL BstoreFeatureOptionAttrib(
  302. PTKMAP ptkmap, // pointer to tokenmap
  303. PGLOBL pglobl
  304. )
  305. /* strange but true, since feature and option attributes
  306. share the same structure, they can use the same code!
  307. In fact LOCAL_FEATURES will end up single valued, and
  308. all OPTIONs will end up multivalued as planned!
  309. */
  310. {
  311. BOOL bStatus = FALSE ;
  312. PDFEATURE_OPTIONS pfo ;
  313. DWORD dwFeatureID = 0; // to silence prefast
  314. DWORD dwTstsInd ; // temp state stack index
  315. STATE stState ;
  316. DWORD dwOffset;
  317. DWORD dwKeywordID ;
  318. for(dwTstsInd = 0 ; dwTstsInd < mdwCurStsPtr ; dwTstsInd++)
  319. {
  320. stState = mpstsStateStack[dwTstsInd].stState ;
  321. if(stState == STATE_FEATURE )
  322. {
  323. dwFeatureID = mpstsStateStack[dwTstsInd].dwSymbolID ;
  324. break ;
  325. }
  326. }
  327. if(dwTstsInd >= mdwCurStsPtr)
  328. return (FALSE) ;
  329. // Return FAILURE if we go through the entire
  330. // stack and never find a feature state. this could only
  331. // happen via a coding error. The process of creating the
  332. // token map uses the state to select the proper attribute
  333. // dictionary to be used to identify each unrecognized keyword.
  334. ASSERT(dwFeatureID < gMasterTable[MTI_DFEATURE_OPTIONS].dwArraySize);
  335. // paranoid BUG_BUG: may check to see if we allocated enough
  336. // FeatureOptions
  337. // if( dwFeatureID >= gMasterTable[MTI_DFEATURE_OPTIONS].dwArraySize )
  338. // failure. - code error.
  339. // just get address of structure holding attribute values.
  340. pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct +
  341. dwFeatureID ;
  342. dwKeywordID = ptkmap->dwKeywordID ;
  343. dwOffset = mMainKeywordTable[dwKeywordID].dwOffset ;
  344. bStatus = BaddBranchToTree(ptkmap, (PATREEREF)((PBYTE)pfo + dwOffset), pglobl) ;
  345. return(bStatus) ;
  346. }
  347. BOOL BstoreGlobalAttrib(
  348. PTKMAP ptkmap, // pointer to tokenmap
  349. PGLOBL pglobl
  350. )
  351. {
  352. BOOL bStatus = FALSE ;
  353. PBYTE pub ;
  354. DWORD dwOffset;
  355. DWORD dwKeywordID ;
  356. // BUG_BUG: may check to see if this value is equal to 1:
  357. // if( gMasterTable[MTI_GLOBALATTRIB].dwArraySize != 1)
  358. // failure. - code error.
  359. // a zero indicates no memory has yet been allocated.
  360. ASSERT( gMasterTable[MTI_GLOBALATTRIB].dwArraySize == 1) ;
  361. // just get address of structure holding attribute values.
  362. pub = gMasterTable[MTI_GLOBALATTRIB].pubStruct ;
  363. dwKeywordID = ptkmap->dwKeywordID ;
  364. dwOffset = mMainKeywordTable[dwKeywordID].dwOffset ;
  365. // the location PATREEREF contains either the values offset
  366. // in the heap or the index to the root of the attribute tree
  367. bStatus = BaddBranchToTree(ptkmap, (PATREEREF)(pub + dwOffset), pglobl) ;
  368. return(bStatus) ;
  369. }
  370. BOOL BaddBranchToTree(
  371. PTKMAP ptkmap, // pointer to tokenmap
  372. PATREEREF patrAttribRoot, // pointer to dword with index
  373. // of root to selected attribute value tree.
  374. PGLOBL pglobl
  375. )
  376. // create/expand attribute tree or overwrite node on existing tree
  377. // If new branch is not compatible
  378. // with existing tree, it is an error. You may overwrite a node
  379. // in the tree, but you may not alter the branches in the tree.
  380. // in case of failure there will be 2 outcomes:
  381. // a) the attribute tree is left unchanged.
  382. // b) a new node is added, but is left uninitialized.
  383. // (atrAttribRoot == ATTRIB_UNINITIALIZED) -or-
  384. // (patt[*pdwNodeIndex].eOffsetMeans == UNINITIALIZED)
  385. // algorithm: starting from index 0 walk up the state stack
  386. // recording symbolIDs until both a FeatureID and OptionID
  387. // has been collected. This defines one segment of the
  388. // new branch that will be added to the tree. Now walk
  389. // the tree to see if an identical branch exists. If so
  390. // go there and go collect another FeatureID/OptionID pair
  391. // so we can repeat the process. If such a segment does not
  392. // exist on the tree, create it. When the stack is empty,
  393. // parse the value and store it on the new leaf node on the
  394. // tree.
  395. // In the simplest case, there are no feature/option pairs
  396. // on the stack. This means we have a root level attribute,
  397. // which just overwrite/creates the global initializer node.
  398. // If there is a feature/option pair on the stack we
  399. // enter a loop to process each feature/option pair.
  400. // the first pass of the loop handles the boundary conditions.
  401. // Here is where we need to deal with the special
  402. // cases of patrAttribRoot referencing the heap
  403. // or the global initializer node.
  404. //
  405. // I) patrAttribRoot contains node index
  406. // A) node is global default initializer
  407. // 1) there is no sublevel.
  408. // create a new sublevel.
  409. // link global default initializer to sublevel
  410. // 2) next points to a node (new sublevel)
  411. // go into new sublevel, now handle just like
  412. // case I.B).
  413. // B) node is normal
  414. // 1) if node's Feature doesn't match FeatureID
  415. // the new branch is incompatible with the tree
  416. // abort.
  417. // 2) Feature's match, search for matching option
  418. // a) option found, drop to end of loop
  419. // b) option not found, create new node at end
  420. // i) previous node is a default initializer
  421. // copy its contents to new node.
  422. // initialize node just vacated to
  423. // FeatureID, OptionID
  424. // ii) initialize new node to
  425. // FeatureID, OptionID
  426. // II) patrAttribRoot is uninitialized
  427. // create new sublevel
  428. // link patrAttribRoot to sublevel
  429. // III) patrAttribRoot pts to heap
  430. // create global initializer node
  431. // link heap to initializer node
  432. // create new sublevel
  433. // link initializer node to new sublevel
  434. //
  435. //
  436. //
  437. // on each subsequent pass through the attribute tree/stack,
  438. // we attempt to enter the next sublevel, since
  439. // this is what corresponds to the new FeatureID/OptionID
  440. // pair retrieved from the stack.
  441. //
  442. // I) there is a sublevel from this node
  443. // enter sublevel
  444. // 1) if node's Feature doesn't match FeatureID
  445. // the new branch is incompatible with the tree
  446. // abort.
  447. // 2) Feature's match, search for matching option
  448. // a) option found, drop to end of loop
  449. // b) option not found, create new node at end
  450. // i) previous node is a default initializer
  451. // copy its contents to new node.
  452. // initialize node just vacated to
  453. // FeatureID, OptionID
  454. // ii) initialize new node to
  455. // FeatureID, OptionID
  456. // II) there is no sublevel
  457. // 1) if the current node references a VALUE
  458. // create a new sublevel node (to be the default)
  459. // initialize it with the value from the
  460. // current node.
  461. // a) if optionID is not DEFAULT_INIT
  462. // insert another node prior to
  463. // the default node just created.
  464. // 2) else current node is UNINITIALIZED.
  465. // create a new sublevel node.
  466. //
  467. //
  468. //
  469. {
  470. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  471. DWORD dwTstsInd ; // temp state stack index
  472. STATE stState ;
  473. DWORD dwFeatureID, dwOptionID ;
  474. DWORD dwNodeIndex ;
  475. DWORD dwPrevsNodeIndex ; // will keep track
  476. // of where we are as we navigate the tree.
  477. patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
  478. // determine this even though we may not use it.
  479. dwPrevsNodeIndex = END_OF_LIST ; // first pass will go
  480. // through special initialization code.
  481. for(dwTstsInd = 0 ; dwTstsInd < mdwCurStsPtr ; dwTstsInd++)
  482. {
  483. // BUG_BUG paranoid: code assumes state stack is
  484. // well behaved as it should be if code is written
  485. // correctly. No safety checks here.
  486. // any errors will cause failure further along.
  487. stState = mpstsStateStack[dwTstsInd].stState ;
  488. if(stState == STATE_FEATURE ||
  489. stState == STATE_SWITCH_ROOT ||
  490. stState == STATE_SWITCH_FEATURE ||
  491. stState == STATE_SWITCH_OPTION)
  492. {
  493. dwFeatureID = mpstsStateStack[dwTstsInd].dwSymbolID ;
  494. continue ;
  495. }
  496. if(stState == STATE_OPTIONS ||
  497. stState == STATE_CASE_ROOT ||
  498. stState == STATE_CASE_FEATURE ||
  499. stState == STATE_CASE_OPTION)
  500. {
  501. dwOptionID = mpstsStateStack[dwTstsInd].dwSymbolID ;
  502. }
  503. else if(stState == STATE_DEFAULT_ROOT ||
  504. stState == STATE_DEFAULT_FEATURE ||
  505. stState == STATE_DEFAULT_OPTION)
  506. {
  507. dwOptionID = DEFAULT_INIT ;
  508. }
  509. else
  510. {
  511. continue ; // these states have no effect on the attrib tree
  512. }
  513. if(dwPrevsNodeIndex == END_OF_LIST)
  514. {
  515. // first pass through the for loop
  516. // process all special cases first time
  517. // around.
  518. if(*patrAttribRoot == ATTRIB_UNINITIALIZED) // case II)
  519. {
  520. // create a new tree consisting of one node .
  521. if(! BcreateEndNode(&dwNodeIndex, dwFeatureID,
  522. dwOptionID, pglobl) )
  523. {
  524. return(FALSE) ;
  525. }
  526. *patrAttribRoot = dwNodeIndex ; // Make this one node
  527. // the root of the tree.
  528. dwPrevsNodeIndex = dwNodeIndex ;
  529. continue ; // ready for next level.
  530. }
  531. else if(*patrAttribRoot & ATTRIB_HEAP_VALUE) // case III)
  532. {
  533. // turn off heap flag to leave pure heap offset,
  534. // then store heap offset into new Node.
  535. if(! BcreateGlobalInitializerNode(&dwNodeIndex,
  536. *patrAttribRoot & ~ATTRIB_HEAP_VALUE, pglobl) )
  537. {
  538. return(FALSE) ;
  539. }
  540. *patrAttribRoot = dwNodeIndex ; // Make the global
  541. // initializer node the root of the new tree.
  542. dwPrevsNodeIndex = dwNodeIndex ;
  543. if(! BcreateEndNode(&dwNodeIndex, dwFeatureID,
  544. dwOptionID, pglobl) ) // new sublevel node.
  545. {
  546. return(FALSE) ;
  547. }
  548. patt[dwPrevsNodeIndex].dwNext = dwNodeIndex ;
  549. // global initializer node references sublevel node.
  550. dwPrevsNodeIndex = dwNodeIndex ;
  551. continue ; // ready for next level.
  552. }
  553. else // case I)
  554. {
  555. dwNodeIndex = *patrAttribRoot ;
  556. if(patt[dwNodeIndex].dwFeature == DEFAULT_INIT ) // I.A)
  557. {
  558. if(patt[dwNodeIndex].dwNext == END_OF_LIST) // I.A.1)
  559. {
  560. // create a new sublevel
  561. dwPrevsNodeIndex = dwNodeIndex ;
  562. // hold global initializer in PrevsNode.
  563. if(! BcreateEndNode(&dwNodeIndex, dwFeatureID,
  564. dwOptionID, pglobl) )
  565. {
  566. return(FALSE) ;
  567. }
  568. patt[dwPrevsNodeIndex].dwNext = dwNodeIndex ;
  569. // global initializer node references sublevel
  570. // node.
  571. dwPrevsNodeIndex = dwNodeIndex ;
  572. continue ; // ready for next level.
  573. }
  574. else // I.A.2)
  575. {
  576. dwNodeIndex = patt[dwNodeIndex].dwNext ;
  577. // enter new sublevel and drop into
  578. // code path for case I.B)
  579. }
  580. }
  581. // case I.B)
  582. if(!BfindOrCreateMatchingNode(dwNodeIndex, &dwNodeIndex,
  583. dwFeatureID, dwOptionID, pglobl) )
  584. {
  585. vIdentifySource(ptkmap, pglobl) ;
  586. return(FALSE) ;
  587. }
  588. dwPrevsNodeIndex = dwNodeIndex ; // goto end of loop.
  589. continue ;
  590. }
  591. }
  592. // this is the generic case: dwPrevsNodeIndex points
  593. // to a normal node and this node matched the
  594. // feature/option from the previous pass.
  595. // objective: boldly attempt to enter the sublevel
  596. // and see if there is something there that matches
  597. // what we are seeking.
  598. if(patt[dwPrevsNodeIndex].eOffsetMeans == NEXT_FEATURE)
  599. {
  600. // Down to the next level we go.
  601. dwNodeIndex = patt[dwPrevsNodeIndex].dwOffset ;
  602. if(!BfindOrCreateMatchingNode(dwNodeIndex, &dwNodeIndex, dwFeatureID,
  603. dwOptionID, pglobl) )
  604. {
  605. vIdentifySource(ptkmap, pglobl) ;
  606. return(FALSE) ;
  607. }
  608. dwPrevsNodeIndex = dwNodeIndex ; // goto end of loop.
  609. }
  610. else // must create a new sublevel now.
  611. {
  612. DWORD dwDefaultNode = END_OF_LIST;
  613. // OffsetMeans can be either VALUE or UNINITIALIZED.
  614. if(patt[dwPrevsNodeIndex].eOffsetMeans == VALUE_AT_HEAP)
  615. {
  616. // create a default initializer node for the
  617. // new sublevel. Transfer heap offset from Prevs
  618. // node into it.
  619. if(! BcreateEndNode(&dwNodeIndex, dwFeatureID,
  620. DEFAULT_INIT, pglobl) )
  621. {
  622. return(FALSE) ;
  623. }
  624. patt[dwNodeIndex].eOffsetMeans = VALUE_AT_HEAP ;
  625. patt[dwNodeIndex].dwOffset =
  626. patt[dwPrevsNodeIndex].dwOffset ;
  627. dwDefaultNode = dwNodeIndex ; // remember this node
  628. }
  629. // create first sublevel node with desired feature/option.
  630. if(dwDefaultNode == END_OF_LIST ||
  631. dwOptionID != DEFAULT_INIT)
  632. {
  633. // this means if a default initializer node
  634. // was already created to propagate the value
  635. // from the previous level AND the new branch
  636. // also specifies a default initializer node, there's
  637. // no need to create a second initializer node.
  638. // if this path is being executed, it means above
  639. // statement is FALSE.
  640. if(! BcreateEndNode(&dwNodeIndex, dwFeatureID,
  641. dwOptionID, pglobl) )
  642. {
  643. return(FALSE) ;
  644. }
  645. patt[dwNodeIndex].dwNext = dwDefaultNode ;
  646. }
  647. patt[dwPrevsNodeIndex].eOffsetMeans = NEXT_FEATURE ;
  648. patt[dwPrevsNodeIndex].dwOffset = dwNodeIndex ;
  649. dwPrevsNodeIndex = dwNodeIndex ; // goto end of loop.
  650. }
  651. } // end of for loop
  652. // we have navigated to the end of the new branch.
  653. // now parse the value, and store in binary form in the heap.
  654. // if a previous VALUE existed, overwrite it on the heap,
  655. // otherwise allocate fresh storage on the heap.
  656. if(dwPrevsNodeIndex != END_OF_LIST) // there was branch in the stack.
  657. {
  658. if (patt[dwPrevsNodeIndex].eOffsetMeans == NEXT_FEATURE)
  659. {
  660. vIdentifySource(ptkmap, pglobl) ;
  661. ERR(("syntax error: attempt to truncate existing attribute tree.\n"));
  662. return(FALSE) ;
  663. }
  664. if (!BaddValueToHeap(&patt[dwPrevsNodeIndex].dwOffset,
  665. ptkmap, (patt[dwPrevsNodeIndex].eOffsetMeans == VALUE_AT_HEAP ), pglobl))
  666. {
  667. return(FALSE) ;
  668. }
  669. patt[dwPrevsNodeIndex].eOffsetMeans = VALUE_AT_HEAP ;
  670. // if dwOffset was originally UNINITIALIZED, its not anymore.
  671. }
  672. else // attribute found at root level.
  673. { // this means we update/create
  674. // the global default initializer.
  675. if(*patrAttribRoot == ATTRIB_UNINITIALIZED)
  676. {
  677. // parse value token, add value (in binary form) into heap.
  678. if(! BaddValueToHeap((PDWORD)patrAttribRoot, ptkmap, FALSE, pglobl) )
  679. {
  680. // BUG_BUG what do we do if parsing or something happens?
  681. // for now just return failure as is. Lose one attribute.
  682. // Sanity check later will determine if this
  683. // omission is fatal.
  684. *patrAttribRoot = ATTRIB_UNINITIALIZED ;
  685. return(FALSE);
  686. }
  687. // returns offset in heap of parsed Value in patrAttribRoot
  688. *patrAttribRoot |= ATTRIB_HEAP_VALUE ;
  689. }
  690. else if(*patrAttribRoot & ATTRIB_HEAP_VALUE)
  691. {
  692. *patrAttribRoot &= ~ATTRIB_HEAP_VALUE ;
  693. // turn off flag to leave pure heap offset.
  694. if(! BaddValueToHeap((PDWORD)patrAttribRoot, ptkmap, TRUE, pglobl) )
  695. {
  696. *patrAttribRoot |= ATTRIB_HEAP_VALUE ;
  697. return(FALSE);
  698. }
  699. *patrAttribRoot |= ATTRIB_HEAP_VALUE ;
  700. }
  701. else // patrAttribRoot contains index of root of attribute tree.
  702. {
  703. // does a global default initializer node exist?
  704. if(patt[*patrAttribRoot].dwFeature == DEFAULT_INIT)
  705. {
  706. if(! BaddValueToHeap(&patt[*patrAttribRoot].dwOffset,
  707. ptkmap, TRUE, pglobl) )
  708. {
  709. return(FALSE);
  710. }
  711. }
  712. else // if not, we need to create one.
  713. {
  714. if(! BcreateGlobalInitializerNode(&dwNodeIndex, 0, pglobl) )
  715. {
  716. return(FALSE) ;
  717. }
  718. if (! BaddValueToHeap(&patt[dwNodeIndex].dwOffset,
  719. ptkmap, FALSE, pglobl) )
  720. {
  721. (VOID)BreturnElementFromMasterTable(MTI_ATTRIBTREE,
  722. dwNodeIndex, pglobl);
  723. return(FALSE) ;
  724. }
  725. patt[dwNodeIndex].dwNext = *patrAttribRoot ;
  726. *patrAttribRoot = dwNodeIndex ; // Make the default
  727. // initializer the root of the tree.
  728. }
  729. }
  730. }
  731. return(TRUE) ; // mission accomplished.
  732. }
  733. BOOL BcreateGlobalInitializerNode(
  734. PDWORD pdwNodeIndex,
  735. DWORD dwOffset, // caller can initialize this now.
  736. PGLOBL pglobl)
  737. {
  738. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  739. patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
  740. if(! BallocElementFromMasterTable(MTI_ATTRIBTREE ,
  741. pdwNodeIndex, pglobl ) )
  742. {
  743. return(FALSE) ;
  744. }
  745. patt[*pdwNodeIndex].dwFeature = DEFAULT_INIT ;
  746. // don't care what dwOption says.
  747. patt[*pdwNodeIndex].eOffsetMeans = VALUE_AT_HEAP ;
  748. patt[*pdwNodeIndex].dwNext = END_OF_LIST ;
  749. patt[*pdwNodeIndex].dwOffset = dwOffset ;
  750. return(TRUE) ;
  751. }
  752. BOOL BcreateEndNode(
  753. PDWORD pdwNodeIndex,
  754. DWORD dwFeature,
  755. DWORD dwOption,
  756. PGLOBL pglobl
  757. )
  758. {
  759. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  760. patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
  761. if(! BallocElementFromMasterTable(MTI_ATTRIBTREE ,
  762. pdwNodeIndex, pglobl) )
  763. {
  764. return(FALSE) ;
  765. }
  766. patt[*pdwNodeIndex].dwFeature = dwFeature ;
  767. patt[*pdwNodeIndex].dwOption = dwOption ;
  768. patt[*pdwNodeIndex].eOffsetMeans = UNINITIALIZED ;
  769. patt[*pdwNodeIndex].dwNext = END_OF_LIST ;
  770. // patt[*dwNodeIndex].dwOffset = not yet defined.
  771. return(TRUE) ;
  772. }
  773. BOOL BfindOrCreateMatchingNode(
  774. IN DWORD dwRootNodeIndex , // first node in chain matching feature
  775. OUT PDWORD pdwNodeIndex, // points to node in chain also matching option
  776. DWORD dwFeatureID, //
  777. DWORD dwOptionID, // may even take on the value DEFAULT_INIT
  778. PGLOBL pglobl
  779. )
  780. /* caller passes a NodeIndex that points to the first node in
  781. a horizontal (option) chain.
  782. If the feature of the Node doesn't match dwFeature, this indicates
  783. the new branch caller is attempting to add is incompatible
  784. with the existing tree and an error results. Otherwise,
  785. search horizontally along the tree searching for a matching
  786. option. If found, return the index of that node, else
  787. must create one. Make sure the default initializer node is
  788. always the last node in the chain.
  789. */
  790. {
  791. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  792. DWORD dwPrevsNodeIndex ;
  793. patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
  794. if(patt[dwRootNodeIndex].dwFeature != dwFeatureID )
  795. {
  796. ERR(("BfindOrCreateMatchingNode: this branch conflicts with the existing tree \n"));
  797. // and cannot be added.
  798. return(FALSE) ;
  799. }
  800. // Yes feature matches, search for matching option.
  801. *pdwNodeIndex = dwRootNodeIndex ; // protects rootatr from
  802. // being overwritten.
  803. for( ; FOREVER ; )
  804. {
  805. if(patt[*pdwNodeIndex].dwOption == dwOptionID )
  806. {
  807. // we found it!
  808. return(TRUE) ;
  809. }
  810. if(patt[*pdwNodeIndex].dwNext == END_OF_LIST)
  811. break ;
  812. *pdwNodeIndex = patt[*pdwNodeIndex].dwNext ;
  813. }
  814. // matching option not found
  815. // create node, attach it to the end
  816. dwPrevsNodeIndex = *pdwNodeIndex ; // last node in list.
  817. if(! BallocElementFromMasterTable(MTI_ATTRIBTREE ,
  818. pdwNodeIndex, pglobl) )
  819. {
  820. return(FALSE) ;
  821. }
  822. patt[*pdwNodeIndex].dwNext = END_OF_LIST ;
  823. patt[dwPrevsNodeIndex].dwNext = *pdwNodeIndex ;
  824. if(patt[dwPrevsNodeIndex].dwOption == DEFAULT_INIT)
  825. {
  826. // must copy default data to new node
  827. // the default initializer must remain at
  828. // the end of the list.
  829. patt[*pdwNodeIndex].dwOption =
  830. patt[dwPrevsNodeIndex].dwOption;
  831. patt[*pdwNodeIndex].dwOffset =
  832. patt[dwPrevsNodeIndex].dwOffset;
  833. patt[*pdwNodeIndex].dwFeature =
  834. patt[dwPrevsNodeIndex].dwFeature;
  835. patt[*pdwNodeIndex].eOffsetMeans =
  836. patt[dwPrevsNodeIndex].eOffsetMeans;
  837. *pdwNodeIndex = dwPrevsNodeIndex ;
  838. // want new initialization to occur in
  839. // second to last node. How do you
  840. // know dwOptionID isn't DEFAULT_INIT?
  841. // simple because since a DEFAULT_INIT
  842. // node does exist in the chain, the
  843. // search would have found it and
  844. // exited the function long before
  845. // reaching this code.
  846. }
  847. // initialize vacated or last node.
  848. patt[*pdwNodeIndex].dwOption = dwOptionID;
  849. patt[*pdwNodeIndex].dwFeature = dwFeatureID;
  850. patt[*pdwNodeIndex].eOffsetMeans = UNINITIALIZED ;
  851. // patt[*pdwNodeIndex].dwOffset = don't know yet
  852. return(TRUE) ;
  853. }
  854. BOOL BfindMatchingNode(
  855. IN DWORD dwRootNodeIndex , // first node in chain matching feature
  856. OUT PDWORD pdwNodeIndex, // points to node in chain also matching option
  857. DWORD dwFeatureID,
  858. DWORD dwOptionID, // may even take on the value DEFAULT_INIT
  859. PGLOBL pglobl
  860. )
  861. /* caller passes a NodeIndex that points to the first node in
  862. a horizontal (option) chain.
  863. If the feature of the Node doesn't match dwFeature, this indicates
  864. the new branch caller is attempting to add is incompatible
  865. with the existing tree and an error results. Otherwise,
  866. search horizontally along the tree searching for a matching
  867. option. If found, return the index of that node, else
  868. returns FALSE.
  869. */
  870. {
  871. PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
  872. DWORD dwPrevsNodeIndex ;
  873. patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
  874. *pdwNodeIndex = dwRootNodeIndex ; // protects rootatr from
  875. // being overwritten.
  876. if(patt[*pdwNodeIndex].dwFeature != dwFeatureID )
  877. {
  878. ERR(("BfindMatchingNode: this branch conflicts with the existing tree \n"));
  879. // and cannot be added.
  880. return(FALSE) ;
  881. }
  882. // Yes feature matches, search for matching option.
  883. for( ; FOREVER ; )
  884. {
  885. if(patt[*pdwNodeIndex].dwOption == dwOptionID )
  886. {
  887. // we found it!
  888. return(TRUE) ;
  889. }
  890. if(patt[*pdwNodeIndex].dwNext == END_OF_LIST)
  891. break ;
  892. *pdwNodeIndex = patt[*pdwNodeIndex].dwNext ;
  893. }
  894. return(FALSE); // matching option not found
  895. }
  896. BOOL BallocElementFromMasterTable(
  897. MT_INDICIES eMTIndex, // select type of structure desired.
  898. PDWORD pdwNodeIndex,
  899. PGLOBL pglobl)
  900. {
  901. if(gMasterTable[eMTIndex].dwCurIndex >=
  902. gMasterTable[eMTIndex].dwArraySize)
  903. {
  904. ERR(("BallocElementFromMasterTable: Out of array elements - restart.\n"));
  905. if(ERRSEV_RESTART > geErrorSev)
  906. {
  907. geErrorSev = ERRSEV_RESTART ;
  908. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  909. gdwMasterTabIndex = eMTIndex ;
  910. }
  911. return(FALSE) ;
  912. }
  913. *pdwNodeIndex = gMasterTable[eMTIndex].dwCurIndex ;
  914. gMasterTable[eMTIndex].dwCurIndex++ ; // Node now taken.
  915. return(TRUE) ;
  916. }
  917. BOOL BreturnElementFromMasterTable(
  918. MT_INDICIES eMTIndex, // select type of structure desired.
  919. DWORD dwNodeIndex,
  920. PGLOBL pglobl)
  921. {
  922. if(gMasterTable[eMTIndex].dwCurIndex == dwNodeIndex + 1)
  923. {
  924. gMasterTable[eMTIndex].dwCurIndex = dwNodeIndex ;
  925. return(TRUE) ;
  926. }
  927. // BUG_BUG: Can return only the most recently allocated node
  928. // not a concern , memory waste is at most 1% and only temporary.
  929. if(ERRSEV_CONTINUE > geErrorSev)
  930. {
  931. geErrorSev = ERRSEV_CONTINUE ;
  932. geErrorType = ERRTY_CODEBUG ;
  933. gdwMasterTabIndex = eMTIndex ;
  934. }
  935. return(FALSE) ;
  936. }
  937. BOOL BconvertSymCmdIDtoUnidrvID(
  938. IN DWORD dwCommandID , // from RegisterSymbol
  939. OUT PDWORD pdwUnidrvID,
  940. PGLOBL pglobl
  941. )
  942. { // convert dwCommandID to UnidrvID
  943. PSYMBOLNODE psn ;
  944. ABSARRAYREF aarKey ;
  945. DWORD dwNodeIndex ;
  946. BOOL bStatus ;
  947. psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
  948. dwNodeIndex = DWsearchSymbolListForID(dwCommandID,
  949. mdwCmdNameSymbols, pglobl) ;
  950. aarKey.dw = psn[dwNodeIndex].arSymbolName.dwCount ;
  951. aarKey.pub = mpubOffRef + psn[dwNodeIndex].arSymbolName.loOffset ;
  952. bStatus = BparseConstant(&aarKey, pdwUnidrvID,
  953. VALUE_CONSTANT_COMMAND_NAMES, pglobl) ;
  954. return(bStatus);
  955. }