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.

912 lines
32 KiB

  1. notes:
  2. identify functions that can be used in both
  3. user mode and km to perform
  4. memory mapped file read, write
  5. memory allocation
  6. what is memory scheme used by NT?
  7. how do you realloc memory and still retain
  8. the same starting address if all memory segments share
  9. the linear address space?
  10. use HeapAlloc? Cannot use virtualalloc()
  11. just so I can start writing code assume:
  12. base_pointer = VirtualAlloc(NULL, max_size_in_bytes, MEM_RESERVE,
  13. PAGE_NOACCESS) ;
  14. pointer = VirtualAlloc(base_pointer, size_needed_in_bytes, MEM_COMMIT,
  15. PAGE_READWRITE) ;
  16. as you need more memory, just commit more and more until
  17. max_size is reached.
  18. VirtualFree(pointer)
  19. Set up build env to create dll, make file, dependencies
  20. etc.
  21. ----
  22. typedef struct
  23. {
  24. } GPD, *PGPD; // structure containing raw GPD data
  25. /* ----
  26. * new prefixes:
  27. * gpd: a GPD structure
  28. * pgpd: ptr to GPD structure
  29. */
  30. allocate memory for all scaffold structures.
  31. Allocate more memory than the structure will need since
  32. reallocation may be impossible. All structures may be
  33. carved from one gigantic block of memory.
  34. Initialize a master table to keep track of all structures.
  35. The master table is an array of entries of the form:
  36. struct _MASTER_TABLE_ENTRY
  37. {
  38. PBYTE pubStruct ; // address of element zero of array
  39. DWORD dwArraySize ; // number of elements that can fit into memory
  40. // set to MAX_SYMBOLNODES for [SYMBOLTREE]
  41. DWORD dwCurIndex ; // points to first uninitialized element
  42. DWORD dwElementSiz ; // size of each element in array.
  43. } MASTERTABENTRY ;
  44. all offsets are to each individual array. There is no
  45. master offset.
  46. MASTERTAB_ENTRY gMasterTable[MTI_MAX_ENTRIES] ;
  47. Bufffers needed for:
  48. typedef enum
  49. {
  50. MTI_SOURCEBUFFER: Source file (GPD input stream)
  51. not sure how memory mapped files and recursive includes
  52. will alter this.
  53. MTI_STRINGHEAP: String heap
  54. MTI_TOKENMAP: tokenMap large enough to hold an old and New copy!
  55. MTI_NEWTOKENMAP: newtokenMap (not a separate buffer from TOKENMAP -
  56. just points immediately after oldTokenMap).
  57. MTI_SYMBOLTREE: symbolTree Array
  58. MTI_BLOCKMACROARRAY (one for Block and another for Value macros)
  59. MTI_DFEATURE_OPTIONS: references a whole bunch of treeroots.
  60. should be initialized to ATTRIB_UNINITIALIZED values.
  61. SymbolID pointed to by dwFeatureSymbols contains largest
  62. array index appropriated. We won't need to allocate
  63. more elements in the final array than this.
  64. MTI_TTFONTSUBTABLE: array of arrayrefs and integers.
  65. MTI_GLOBALATTRIB: structure holding value of global attributes.
  66. MTI_ATTRIBTREE: array of ATTRIB_TREE structures.
  67. MTI_COMMANDTABLE: array of PATREEREF (or DWORD indicies to COMMAND_ARRAY)
  68. // the size of this table is set by the number of
  69. // predefined Unidrv commands.
  70. MTI_COMMANDARRAY: array of COMMAND structures.
  71. // size varies depending on number of commands and variants
  72. // defined in the GPD file.
  73. MTI_FONTCART: array of FontCartridge structures - one per construct.
  74. MTI_LISTNODES: array of LISTNODEs.
  75. MTI_MAX_ENTRIES: Last entry.
  76. } MT_INDICIES ;
  77. Note: the prefix MTI_ stands for MasterTableIndex, the
  78. base portion of the name is the structure typedef.
  79. BLOCKMACROARRAY is an array of structs temporarily carved into
  80. a buffer:
  81. typedef struct
  82. {
  83. DWORD tIndexID; tokenindex where a macro ID value is stored
  84. DWORD tIndexOpen; index of open brace
  85. DWORD tIndexClose; index of closing brace
  86. } BLOCKMACROARRAY ;
  87. each dword contains the tokenIndex where a macro ID value is stored.
  88. curBlockMacroArray points to the smallest index of the macroArray currently
  89. uninitialized. (initially curBlockMacroArray = 0)
  90. VALUEMACROARRAY is an array of DWORDS holding a
  91. tokenindex where a valuemacro ID value is stored
  92. MACROLEVELSTACK: is operated as a two dword stack that saves the
  93. values of curBlockMacroArray and curValueMacroArray , each time
  94. a brace is encountered.
  95. -------
  96. increaseMacroLevel(): called in response to parsing open brace.
  97. Copy this entry to the newtokenarray .
  98. save the value of curBlockMacroArray and curValueMacroArray in the
  99. macrolevelstack. we will use this later.
  100. check if this brace begins the definition of a blockmacro,
  101. this is easy to do.
  102. if( curBlockMacroArray &&
  103. (BlockMacroArray[curBlockMacroArray - 1].tIndexOpen == -1))
  104. {
  105. yes, we are beginning a BlockMacro definition.
  106. record newtokenArray index of open brace entry in tIndexOpen.
  107. check to see tIndexOpen is one higher than tIndexID, else
  108. a syntax error needs to be flagged for this blockMacro.
  109. }
  110. decreaseMacroLevel: called in response to parsing close brace.
  111. temporarily save curBlockMacroArray and curValueMacroArray
  112. into temp vars largerBlockIndex and largerValueIndex.
  113. now pop the value of curBlockMacroArray and curValueMacroArray from the
  114. stack.
  115. locate all macros referenced in the macroarray (less than largerIndex,
  116. and greater than or equal to curMacroArray retrieved from stack)
  117. that are expired due to the change in level. Delete their entries
  118. in the tokenmap by replacing their tkKeyID by NULLKEY. This
  119. will break the endless chain resulting when a macro defines another
  120. macro.
  121. Does this closing brace end a macro definition?
  122. if(MacroArray[curMacroArray - 1].tIndexClose == -1) //yes
  123. {
  124. MacroArray[curMacroArray - 1].tIndexClose =
  125. location of } in newtokenArray;
  126. }
  127. Copy this entry to the newtokenarray .
  128. ----
  129. The symbol tree is comprised of these nodes. The symbol tree
  130. organizes the symbol space into a hierarchy. For each feature
  131. symbol, there is a set of option symbols particular to that feature.
  132. All symbol nodes are stored in one array. Multiple trees may
  133. exist in one array. When the symboltree is frozen, it can be
  134. optimized by restoring the tree as an array of (STRREFs+subSpaceIndex.
  135. Where the symbolID serves as the index to the arrayref.
  136. (+ symboltype offset) The end of each symbol list may be signified by
  137. a NULL arrayref.
  138. typedef struct
  139. {
  140. ARRAYREF arSymbolName;
  141. DWORD dwSymbolID; // has nothing to do with array of symbol structs.
  142. // value begins at zero and is incremented to obtain
  143. // next value.
  144. DWORD dwNextSymbol; // index to next element in this space.
  145. DWORD dwSubSpaceIndex ; // index to first element in new symbol space
  146. which exists within the catagory represented by this symbol.
  147. for example in the catagory represented by the
  148. symbol PAPERSIZES: we may have the subspace
  149. comprised of Letter, A4, Legal, etc.
  150. } SYMBOLNODE , * PSYMBOLNODE ;
  151. // assign this struct the type 'psn'
  152. // ---- Global and state Variables ---- //
  153. {
  154. // ---- Index in SYMBOLNODE array to each type of tree ---- //
  155. DWORD gdwFeatureSymbols ; // initially set to INVALID_INDEX
  156. DWORD gdwFontCartSymbols ;
  157. DWORD gdwTTFontSymbols ;
  158. DWORD gdwBlockMacroSymbols ;
  159. DWORD gdwValueMacroSymbols ;
  160. // ---- track value of curBlockMacroArray and curValueMacroArray ---- //
  161. DWORD gdwCurBlockMacroArray ; // initially set to zero. First
  162. DWORD gdwCurValueMacroArray ; // writable slot in MacroArray.
  163. DWORD gdwMacroLevelStackPtr ; // Push: write values into
  164. // MacroLevelStack[MacroLevelStackPtr++]
  165. // Pop: read values from
  166. // MacroLevelStack[--MacroLevelStackPtr]
  167. }
  168. typedef struct _TOKENMAP
  169. {
  170. DWORD dwKeywordID ; // index of entry in KeywordTable
  171. ABSARRAYREF aarKeyword ; // points to keyword in the source file
  172. ABSARRAYREF aarValue ; // value associated with this keyword.
  173. // an arrayref is needed if we store
  174. // the value in the heap.
  175. // It also makes copying the string
  176. // to another place easier. No need to
  177. // search for a linebreak char. Just
  178. // Copyn() will do.
  179. DWORD dwValue ; // interpretation of Value string - see flags.
  180. // maybe commandID, numerical value of constant, MacroID assigned
  181. // to MacroSymbol , SymbolID etc.
  182. DWFLAGS dwFlags ; // bitfield with the following flags
  183. // TKMF_VALUE_SAVED independently of the tokenmap.
  184. // TKMF_COMMAND_SHORTCUT only used when parsing commands.
  185. // TKMF_INLINE_BLOCKMACROREF need to know when resolving macros.
  186. // TKMF_MACROREF indicates a value macro reference that must be resolved
  187. // TKMF_SYMBOLID dwValue contains a symbolID.
  188. // TKMF_SYMBOL_REGISTERED set when the symbolID is registered.
  189. // TKMF_EXTERN: The extern Qualifier was prepended to the keyword
  190. // and has now been truncated.
  191. } TKMAP, *PTKMAP
  192. special keywordIDs:
  193. ID_NULLENTRY: ignore this, either expired code, parsing error etc.
  194. ID_UNRECOGNIZED: conforms to correct syntax, but not in my keyword table.
  195. could be a keyword defined in a newer spec or name of valuemacro.
  196. other other OEM defined stuff.
  197. ID_SYMBOL: does not begin with * , but conforms to syntax
  198. for a symbol.
  199. ID_EOF: end of file - no more tokenMap entries
  200. -----------------------------------
  201. During the parsing to create the token map we
  202. a) replace all comments with spaces
  203. b) replace consecutive linebreaks with spaces.
  204. c) parse all mainkeywords and replace with keywordIDs
  205. d) init pointers to keywords and arrayref to values
  206. e) set appropriate flags.
  207. f) register symbols.
  208. // ---- note ---- //
  209. all functions parsing the input stream may indicate
  210. reaching EOB by returning NULL. caller should check for
  211. NULL return value after calling these functions and
  212. react accordingly.
  213. // -------------- //
  214. BUG_BUG: CreateTokenMap should note if
  215. *Command is the short version. If so
  216. then 2nd pass (macroresolution) should
  217. expand it so special case code is not needed.
  218. PTKMAP CreateTokenMap(
  219. IN OUT PBYTE pubCur // location within source to start parsing
  220. )
  221. {
  222. PBYTE pubNewPos ; // transient data.
  223. // assume we are at parsing level 0 - outside of any
  224. // contexts requiring a change of parsing rules.
  225. pubCur = PubEatWhite(pubCur) ;
  226. this function will move forward until the first non-whitespace
  227. or non-linebreak character is encountered. Convert first
  228. occurances of consecutive linebreak chars to whitespace.
  229. (should this be done here?: convert linebreak+continuation
  230. to whitespace.)
  231. /* PubEatComments(pubCur) */
  232. if pubCur points to start of a valid comment, this function
  233. will advance until linebreak character is encountered.
  234. it will also completely consume the comment by replacing
  235. all the characters with spaces.
  236. while((pubNewPos = PubEatComments(pubCur)) != pubCur)
  237. {
  238. pubCur = pubNewPos ;
  239. pubCur = PubEatWhite(pubCur) ;
  240. }
  241. at this point pubCur points to first non-WHITE char that
  242. is also not a comment.
  243. we expect to see {, } (braces) or a valid keyword at this
  244. point.
  245. while(pubCur)
  246. {
  247. pubCur = dwIdentifyKeyword(pubCur, tkmap+i) ;
  248. this function does several things:
  249. 'brackets' keyword to see if it is properly terminated with :
  250. and begins with * (if it is not a brace).
  251. performs table lookup to obtain the keywordID which is written
  252. to tkmap[i].dwKeywordID .
  253. Determines based on the keyword ID if next token represents
  254. another keyword (as is the case if keyword is a brace)
  255. or if it represents a value. If its a keyword, assigns NULL
  256. to arValue, else arValue points to first nonwhite char
  257. in value after the : delimiter. This function treats
  258. the value as a black box.
  259. If the keyword happens to be a brace, dwValue
  260. will hold the nesting level of the brace.
  261. This will allow very fast identification of scope.
  262. If the state machine is used at this point we can
  263. resolve attribute names. Otherwise we scan only
  264. for non-attribute keywords and mark all other legally
  265. constructed keywords as UNRECOGNIZED. However attributes
  266. prefaced with EXTERN_FEATURE or EXTERN_GLOBAL may be
  267. identified at this time.
  268. A second pass using the state machine then applies the
  269. proper attribute namespace and resolves all UNRECOGNIZED
  270. keywords. All remaining unrecognized keywords produce
  271. a warning message.
  272. Returns pubCur, which points to first char in the value or
  273. first char of next keyword if no value exists.
  274. Error handling: calls a function WriteErrorMsg() to
  275. record any errors that it encounters. may set dwKeywordID
  276. to ERROR, and set pubValue pointing to offending keyword,
  277. and return this value in pubCur.
  278. pubCur = scanOverValue(pubCur) ;
  279. init arValue, set dwFlags.
  280. Note: lets parse the value only to reach the next
  281. keyword, not with the intent of saving the value
  282. somewhere. This is because at this point we have
  283. no clue as to where the value should be
  284. saved to. Wait for a subsequent pass to avoid
  285. cluttering the heap with data that will eventually
  286. be cubbyholed elsewhere. There are a few execptions
  287. that will cause things to happen. One is if the shortcut
  288. version of another construct is encountered, then
  289. we must expand this in the tokenMap so it looks like
  290. the full fledged version. On the other hand we may
  291. choose to defer the expansion till later, but we
  292. may flag this now.
  293. See *command for an example.
  294. Also replace any occurances of linebreak + continuation
  295. char with spaces.
  296. Eat comments and white spaces until we reach beginning of
  297. a non-Null statement.
  298. }
  299. things that need to be done at some point
  300. in this function:
  301. lazy way to guard against useage of command shortcuts:
  302. when ever encountering a command keyword, leave
  303. the following entry unused. (mark it as NULL keyword)
  304. the Command name (the value portion)
  305. needs to be parsed and converted to a unidrv ID
  306. this may be placed in tokenmap.dwValue.
  307. set the flag TKMF_SYMBOL_REGISTERED. This will
  308. prevent the value string from getting registered in a
  309. symbol table.
  310. }
  311. defineAndResolveMacros()
  312. this function scans through the tokenMap
  313. making a copy of the tokenMap without
  314. the macrodefinitions or references. All references
  315. are replaced by the definitions inserted in-line!
  316. {
  317. Can't store ValueMacro Definitions in scratch memory, they
  318. will actually be referenced directly if the value is not
  319. a string!
  320. initialize NEWTOKENMAP to refer to unused entries
  321. in TOKENMAP buffer. We will create a new copy of
  322. the tokenmap here!
  323. 1st pass:
  324. defineBlockMacroSymbols()
  325. search for all *BlockMacro keywords
  326. add macro symbol definitions
  327. to the symbol tree. assign them
  328. an ordinal ID value 1, 2, 3, ...
  329. in this case, we may use the tree
  330. as a pure array of StringRefs. with
  331. in index to the first uninitialized entry.
  332. write the macroID value into the tokenMap.dwValue.
  333. ScanForMacroReferences();
  334. walk through the old tokenMap one entry at a time.
  335. for (every entry in the tokenMap)
  336. {
  337. switch()
  338. {
  339. case (entry begins a block macrodef)
  340. copy token entry into new tokenMap
  341. record the new tokenIndex into
  342. BlockMacroArray[curBlockMacroArray]
  343. set tIndexOpen and close to -1 to indicate
  344. not yet initialized.
  345. increment curBlockMacroArray.
  346. (all lines of macrodef are automatically copied over!)
  347. case (entry contains a block macroref)
  348. convert the symbolname to a macroID via
  349. the symboltree. Search the BlockMacroArray entries
  350. from index curBlockMacroArray - 1 to zero
  351. using the first macroID that matches.
  352. copy all the valid tokenMap entries
  353. between BlockMacroArray[index].tIndexOpen
  354. and tIndexClose defined for the block macro
  355. referenced. Avoid circular reference by ensuring
  356. tIndexClose != -1 for the selected macro.
  357. case (entry begins a value macrodef: *Macros)
  358. defineValueMacros()
  359. case (entry references a valuemacro)
  360. know by checking tokenMap.dwFlags = MACROREF.
  361. dereferenceValueMacro()
  362. // sorry, cannot defer this since value macros
  363. // have a limited scope. We must access the
  364. // valueMacroArray at the time we see the reference
  365. // since valueMacroArray dynamically changes as we
  366. // encounter braces.
  367. case ({) increment macro nesting level
  368. any macro defined within a macro is undefined
  369. outside of that macro!
  370. case (}) decrease macro nesting level.
  371. default; // all other entries
  372. copy to new tokenMap
  373. }
  374. }
  375. old tokenMap is now useless, its memory now lies fallow.
  376. }
  377. ScanForMacroReferences()
  378. {
  379. may want to factor out common stuff.
  380. for (each entry in oldTokenMap)
  381. {
  382. if(entry does not define an macro nor is a brace char)
  383. {
  384. must scan all values for macroReference.
  385. if a non string value is expected, the = macroname
  386. must be the first and only entity comprising the value.
  387. If its a string, we must parse each construct!
  388. set flag in oldTokenMap.
  389. can share code used in defineValueMacros().
  390. }
  391. }
  392. }
  393. // note: all continuation chars have been replaced by spaces
  394. // previously at scanOverValue() time.
  395. defineValueMacros(old, newtokenindex)
  396. {
  397. this function is called upon encountering
  398. a *Macros: groupname construct
  399. check to see there is an opening brace
  400. while(tokenArray[tokenindex].keywordID != closingBrace)
  401. {
  402. each entry up to the closing brace defines a
  403. value macro.
  404. register macroname in ValueMacroSymbols tree
  405. Store index to tokenArray in
  406. valueMacroArray
  407. maybe also valueMacroArray should
  408. have an arrayref
  409. 1) we have no idea what value is being defined or how
  410. to properly parse for it.
  411. the value may reference another macro(s)
  412. so the only time we attempt parsing the value is
  413. if the value appears to be a string macro. If at any time
  414. the parsing fails, the entire value is treated as a black box.
  415. Copy the entire value string (everything up to but NOT including the
  416. first linebreak char ) into the heap. initialize an arrayref
  417. to access this string.
  418. the following portion is also common to dereferenceValueMacro().
  419. and partly common to ScanForMacroReferences()
  420. Attempt to determine if the value in the heap is a string.
  421. If so
  422. {
  423. parse along the string until macro reference is found
  424. then lookup macroname in the valueMacroArray,
  425. see how many bytes the macro contains and shift
  426. the remainder of the referencing macrostring to make
  427. room to insert the referenced macrostring.
  428. Copy the referenced macrostring in the space provided.
  429. Update the length of the referencing macrostring.
  430. repeat until no other macro references are found.
  431. }
  432. else
  433. do nothing special.
  434. store ref to string in heap inside tokenArray.arValue
  435. }
  436. }
  437. dereferenceValueMacro(index)
  438. {
  439. may want to factor out common stuff.
  440. there is a macro reference in this statement since
  441. it is flagged in the tokenMap.
  442. if(valuetype for keywordID in the master keyword table != VALUE_COMMAND_INVOC
  443. or VALUE_STRING)
  444. {
  445. expect macroref to be the first and only thing you
  446. encounter.
  447. convert macroref to macroID.
  448. lookup macroID in valueMacroArray.
  449. for(i = curValueMacroIndex ; i ; i--)
  450. {
  451. if(tokenMap[valueMacroArray[i - 1]].dwValue == macroID)
  452. break; // p
  453. }
  454. If found, copy arrayref to value field which references Macro.
  455. tokenMap[index].arValue = tokenMap[valueMacroArray[i - 1]].arValue
  456. }
  457. else // valueMacro occurs in a string.
  458. {
  459. Copy the entire value string (everything up to but NOT including the
  460. first linebreak char ) into the heap.
  461. parse along the string until macro reference is found
  462. then lookup macroname in the valueMacroArray,
  463. see how many bytes the macro contains and shift
  464. the remainder of the referencing macrostring to make
  465. room to insert the referenced macrostring.
  466. Copy the referenced macrostring in the space provided.
  467. Update the length of the referencing macrostring.
  468. repeat until no other macro references are found.
  469. Copy updated arrayref to value field in tokenMap.
  470. }
  471. }
  472. defineSymbols(tokenMap) ???
  473. {
  474. Note: All Macro symbols have been processed
  475. by the time this function is called.
  476. Scans down tokenMap looking for
  477. Feature:, Font: keywordIDs
  478. and adding their symbol definitions to
  479. the symbol tree. This portion may be common to
  480. register macroname in ValueMacroSymbols tree
  481. part of defineValueMacros() and defineBlockMacroSymbols()
  482. then rescans (or in the same pass)
  483. the tokenMap keeping track of
  484. which Feature we are in, so when an Option
  485. keyword is encountered, we know which Feature symbol
  486. to associate the option symbol with. If an option
  487. construct occurs outside of a Feature construct, we
  488. will know and can flag this as an error.
  489. }
  490. at this point only symbols defined by Feature:, BlockMacros:, Font:
  491. are stored in the symbol tree.
  492. processSymbolRefs(tokenMap)
  493. {
  494. exactly which circustances may symbols appear outside of
  495. a value? if they occur: keywordID should indicate
  496. exactly what catagory of symbol and the symbolID.
  497. in the high and low word.
  498. replaces ptr to symbol values in source file
  499. with SymbolID value or index to QualifiedName construct
  500. or index to List construct which contains SymbolID value
  501. or index to QualifiedName construct. tokenMap will
  502. clearly identify which of the 4 cases applies.
  503. At this point identify long or short version of command.
  504. for short version, dwKeyWordID = SHORTCMD | <COMMANDID> ;
  505. for long version : dwKeywordID = LONGCMD ;
  506. and Cmd keyword dwKeywordID = CMD
  507. dwValue = <COMMANDID> ;
  508. Find and register dwKeywordID = SYMBOL in the appropriate
  509. symbol Tree. Change dwKeywordID to (for example)
  510. TTFONTNAME | FONTNAMEID.
  511. At this point NO keywords should remain unrecognized.
  512. }
  513. main()
  514. {
  515. PTKMAP CreateTokenMap(
  516. at what point do we distinguish between
  517. shortcuts and non shortcut keywords? do this
  518. soon, before BInterpretTokens() is called.
  519. defineAndResolveMacros()
  520. defineSymbols(tokenMap) ;
  521. registers symbols for TTFontSubs?
  522. processSymbolRefs(tokenMap) ;??? not needed at this time?
  523. initStructures() with default or failsafe values ;
  524. // this is done after first pass and we know
  525. // how many DFEATURE_OPTION structures to allocate.
  526. // we will initialize all dword values to ATTRIB_UNINITIALIZED.
  527. // this is essential!
  528. // the GlobalAttribute structure.
  529. BInterpretTokens() ;
  530. checkStructures() to ensure failsafe values have
  531. been replaced - otherwise GPD file failed to
  532. initialize some mandatory field.
  533. verify that features that are referenced in switch
  534. statements are indeed PICKONE. May force it to be
  535. and warn or fail.
  536. go through all allocated data structures ensuring
  537. that they all contain at least the minimum required
  538. fields. Supply defaults for any omitted but required
  539. values. raise warnings. If a structure is fatally flawed,
  540. you may have to fatally error out.
  541. ConstructSeqCommandsArray() !
  542. }
  543. OpenIssues:
  544. How to deal with TTFontSubs
  545. *TTFontSubs: <On/Off>
  546. {
  547. symbolKeyname1: <integer>
  548. symbolKeyname2: <integer>
  549. symbolKeyname3: <integer>
  550. ...
  551. }
  552. the On/Off part is handled by
  553. VsetbTTFontSubs(ptkmap->aarValue) ;
  554. who handles the symbolKeywords? what if some are repeated?
  555. ProcessSymbolKeyword(ptkmap + wEntry) ;
  556. Both are called from within BInterpretTokens
  557. // ---- tables of static data ---- //
  558. // ---- The mainKeyword table ---- //
  559. The mainKeyword Table is an array of
  560. structures of the form:
  561. typedef struct
  562. {
  563. PSTR pstrKeyword ; // keywordID is the index of this entry.
  564. DWORD dwHashValue ; // optional - implement as time permits.
  565. VALUE eAllowedValue ;
  566. DWORD flAgs ;
  567. TYPE eType; // may replace Type/Subtype with a function
  568. DWORD dwSubType ; // if there is minimal code duplication.
  569. DWORD dwOffset ; // into appropriate struct for attributes only.
  570. // the size (num bytes to copy) of an attribute is easily determined
  571. // from the AllowedValue field.
  572. } KEYWORDTABLE_ENTRY;
  573. global KEYWORDTABLE_ENTRY gMainKeywordTable[] =
  574. {
  575. static initializers
  576. }
  577. typedef enum
  578. {
  579. TY_CONSTRUCT, TY_ATTRIBUTE, TY_SPECIAL
  580. } TYPE ;
  581. typedef enum
  582. {
  583. SPCL_MEMCONFIGKB, SPCL_MEMCONFIGMB,
  584. } SPECIAL ; // special subtypes
  585. typedef enum
  586. {
  587. ATT_GLOBAL_ONLY, ATT_GLOBAL_FREEFLOAT,
  588. ATT_LOCAL_FEATURE_ONLY, ATT_LOCAL_FEATURE_FF ,
  589. ATT_LOCAL_OPTION_ONLY, ATT_LOCAL_OPTION_FF ,
  590. ATT_LOCAL_COMMAND_ONLY, ATT_LOCAL_FONTCART_ONLY,
  591. ATT_LOCAL_TTFONTSUBS_ONLY, ATT_LOCAL_OEM_ONLY,
  592. ATT_LAST // Must be last in list.
  593. } ATTRIBUTE ; // subtype
  594. typedef enum
  595. {
  596. CONSTRUCT_UIGROUP ,
  597. CONSTRUCT_FEATURE ,
  598. CONSTRUCT_OPTION ,
  599. CONSTRUCT_SWITCH,
  600. CONSTRUCT_CASE ,
  601. CONSTRUCT_DEFAULT ,
  602. CONSTRUCT_COMMAND ,
  603. CONSTRUCT_FONTCART ,
  604. CONSTRUCT_TTFONTSUBS ,
  605. CONSTRUCT_OEM ,
  606. CONSTRUCT_LAST, // must end list of transition inducing constructs.
  607. // constructs below do not cause state transitions
  608. CONSTRUCT_BLOCKMACRO ,
  609. CONSTRUCT_MACROS,
  610. CONSTRUCT_OPENBRACE,
  611. CONSTRUCT_CLOSEBRACE,
  612. } CONSTRUCT ; // SubType if Type = CONSTRUCT
  613. typedef enum
  614. {
  615. SPEC_CONSTR, SPEC_INS_CONSTR,
  616. SPEC_NOT_INS_CONSTR, SPEC_INVALID_COMBO, SPEC_INVALID_INS_COMBO,
  617. SPEC_MEM_CONFIG_KB, SPEC_MEM_CONFIG_MB, SPEC_FONT,
  618. SPEC_, SPEC_, SPEC_,
  619. } SPECIAL ;
  620. typedef enum
  621. {
  622. NO_VALUE, VALUE_STRING, VALUE_COMMAND_INVOC,
  623. VALUE_SYMBOL_DEF,
  624. VALUE_SYMBOL_REF, VALUE_CONSTANT_catagory,
  625. VALUE_INTEGER, VALUE_POINT, VALUE_RECT,
  626. VALUE_BOOLEAN, VALUE_QUALIFIED_NAME,
  627. VALUE_MAX
  628. } VALUE ;
  629. what does the parser expect after a keyword?
  630. NO_VALUE : a linebreak OR an effective linebreak: ({) or comment
  631. VALUE_STRING: Quoted String, hexstring, string MACROREF,
  632. parameterless invocation.
  633. VALUE_COMMAND_INVOC: like VALUE_STRING but allowed to contain
  634. one or more parameter references.
  635. VALUE_SYMBOL_DEF: Symbol definition - any value allowed
  636. VALUE_SYMBOL_FIRST: base of user-defined symbol catagory
  637. VALUE_SYMBOL_FEATURES = VALUE_SYMBOL_FIRST + SCL_FEATURES :
  638. VALUE_SYMBOL_FONTCART = VALUE_SYMBOL_FIRST + SCL_FONTCART :
  639. VALUE_SYMBOL_BLOCKMACRO = VALUE_SYMBOL_FIRST + SCL_BLOCKMACRO :
  640. VALUE_SYMBOL_VALUEMACRO = VALUE_SYMBOL_FIRST + SCL_VALUEMACRO :
  641. VALUE_SYMBOL_OPTIONS = VALUE_SYMBOL_FIRST + SCL_OPTIONS :
  642. VALUE_SYMBOL_LAST = VALUE_SYMBOL_FIRST + SCL_NUMSYMCLASSES - 1 :
  643. VALUE_CONSTANT_FIRST: base of enumeration catagory.
  644. VALUE_CONSTANT_PRINTERTYPE = VALUE_CONSTANT_FIRST + CL_PRINTERTYPE ;
  645. VALUE_CONSTANT_FEATURETYPE = VALUE_CONSTANT_FIRST + CL_FEATURETYPE ;
  646. lots of class types listed here
  647. ..........
  648. VALUE_CONSTANT_LAST = VALUE_CONSTANT_FIRST + CL_NUMCLASSES - 1 ;
  649. VALUE_INTEGER: integer
  650. VALUE_POINT: point
  651. VALUE_RECT: rectangle
  652. VALUE_BOOLEAN: boolean.
  653. VALUE_QUALIFIED_NAME: Qualified name (one or more symbols separated by .)
  654. VALUE_LIST: no attribute actually is assigned this descriptor,
  655. // but used in the gValueToSize table.
  656. VALUE_LARGEST: not a real descriptor, but this position in the
  657. gValueToSize table holds the largest of the above values.
  658. VALUE_MAX: number of elements in gValueToSize table.
  659. -----
  660. allowed values for KEYWORDTABLE_ENTRY.flAgs:
  661. KWF_LIST: the value may be a LIST containing one or more
  662. items of type AllowedValue. The storage format
  663. must be of type LIST. Only certain values may qualify
  664. for list format.
  665. KWF_MACROREF_ALLOWED: since only a handful of keywords cannot accept
  666. macro references, it may be a waste of a flag, but reserve this
  667. to alert us that this special case must accounted for.
  668. KWF_COMMAND: This attribute is stored in a dedicated structure
  669. KWF_FONTCART: This attribute is stored in a dedicated structure
  670. KWF_TTFONTSUBS: This attribute is stored in a dedicated structure
  671. KWF_OEM: This attribute is stored in a dedicated structure
  672. --------- special flag constructs ----
  673. KWF_DEDICATED_FIELD = KWF_COMMAND | KWF_FONTCART |
  674. KWF_TTFONTSUBS | KWF_OEM
  675. : this indicates this attribute is stored
  676. in a dedicated structure, not in the heap. As a result,
  677. the dwOffset field is interpreted differently from attributes
  678. without this flag set.
  679. -----
  680. Notes:
  681. the KeywordTable is partitioned into sections:
  682. non-attribute Keywords
  683. GlobalAttributes
  684. FeatureAttributes
  685. OptionAttributes
  686. CommandAttributes
  687. etc.
  688. A range of indicies (min-max)
  689. may be provided or a special flag
  690. may denote the last entry in each section.
  691. The separation exists because the same keyword may
  692. exist in two different sections.
  693. -----
  694. command array:
  695. just a list of command names and #defines giving the unidrv
  696. value. Use this table to assign each commandname a value.
  697. CmdSelect is a special value -1!
  698. typedef struct
  699. {
  700. ARRAYREF CommandName ;
  701. DWORD UnidrvIndex ; // #define value assigned to command.
  702. } CMD_TABLE ;
  703. global CommandTable[NUM_UNIDRV_CMDS] ;
  704. ------
  705. Table to convert allowed values to sizes:
  706. DWORD gValueToSize[VALUE_MAX] ; // size of various values in bytes
  707. VinitValueToSize()
  708. {
  709. // BUG_BUG! assume array is zero initialized
  710. gValueToSize[VALUE_LARGEST] = 0 ;
  711. gValueToSize[NO_VALUE] = 0 ;
  712. gValueToSize[VALUE_BOOLEAN] = sizeof(BOOL) ; // etc
  713. gValueToSize[VALUE_RECT] = sizeof(RECT) ; // etc
  714. gValueToSize[VALUE_LIST] = sizeof(DWORD) ; // etc
  715. // only the index of first listnode is stored.
  716. for(i = 0 ; i < CL_NUMCLASSES ; i++)
  717. gValueToSize[VALUE_CONSTANT_FIRST + i] = sizeof(DWORD) ;
  718. for(i = 0 ; i < VALUE_MAX ; i++)
  719. {
  720. if (!gValueToSize[i])
  721. assert! ; // ensure table is fully initialized .
  722. if(gValueToSize[i] > gValueToSize[VALUE_LARGEST])
  723. gValueToSize[VALUE_LARGEST] = gValueToSize[i] ;
  724. }
  725. }
  726. -----
  727. ensure all whitespaces are stripped before allowing token
  728. to be registered, compared with etc.