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.

1590 lines
48 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. /* token1.c - functions to create the tokenmap */
  3. #include "gpdparse.h"
  4. // ---- functions defined in token1.c ---- //
  5. BOOL BcreateTokenMap(
  6. PWSTR pwstrFileName,
  7. PGLOBL pglobl ) ;
  8. PARSTATE PARSTscanForKeyword(
  9. PDWORD pdwTKMindex,
  10. PGLOBL pglobl) ;
  11. PARSTATE PARSTparseColon(
  12. PDWORD pdwTKMindex,
  13. PGLOBL pglobl) ;
  14. PARSTATE PARSTparseValue(
  15. PDWORD pdwTKMindex,
  16. PGLOBL pglobl) ;
  17. BOOL BparseKeyword(
  18. DWORD dwTKMindex,
  19. PGLOBL pglobl) ;
  20. BOOL BisExternKeyword(
  21. DWORD dwTKMindex,
  22. PGLOBL pglobl) ;
  23. BOOL BisColonNext(
  24. PGLOBL pglobl) ;
  25. BOOL BeatArbitraryWhite(
  26. PGLOBL pglobl) ;
  27. BOOL BeatComment(
  28. PGLOBL pglobl) ;
  29. BOOL BscanStringSegment(
  30. PGLOBL pglobl) ;
  31. BOOL BscanDelimitedString(
  32. BYTE ubDelimiter,
  33. PBOOL pbMacroDetected,
  34. PGLOBL pglobl) ;
  35. PARSTATE PARSTrestorePrevsFile(
  36. PDWORD pdwTKMindex,
  37. PGLOBL pglobl) ;
  38. PWSTR
  39. PwstrAnsiToUnicode(
  40. IN PSTR pstrAnsiString,
  41. PGLOBL pglobl
  42. ) ;
  43. PARSTATE PARSTloadIncludeFile(
  44. PDWORD pdwTKMindex,
  45. PWSTR pwstrFileName, // root GPD file
  46. PGLOBL pglobl);
  47. BOOL BloadFile(
  48. PWSTR pwstrFileName,
  49. PGLOBL pglobl ) ;
  50. BOOL BarchiveStrings(
  51. DWORD dwTKMindex,
  52. PGLOBL pglobl) ;
  53. DWORD DWidentifyKeyword(
  54. DWORD dwTKMindex,
  55. PGLOBL pglobl) ;
  56. BOOL BidentifyAttributeKeyword(
  57. PTKMAP ptkmap, // pointer to tokenmap
  58. PGLOBL pglobl
  59. ) ;
  60. BOOL BcopyToTmpHeap(
  61. PABSARRAYREF paarDest,
  62. PABSARRAYREF paarSrc,
  63. PGLOBL pglobl) ;
  64. DWORD dwStoreFileName(PWSTR pwstrFileName,
  65. PARRAYREF parDest,
  66. PGLOBL pglobl) ;
  67. VOID vFreeFileNames(
  68. PGLOBL pglobl ) ;
  69. VOID vIdentifySource(
  70. PTKMAP ptkmap,
  71. PGLOBL pglobl) ;
  72. // functions defined in preproc1.c //
  73. BOOL BPreProcess(
  74. PGLOBL pglobl
  75. ) ; // from current file position, use file macros to access.
  76. BOOL DefineSymbol(
  77. PBYTE symbol,
  78. PGLOBL pglobl
  79. ) ;
  80. // ---------------------------------------------------- //
  81. // define Local Macro to access info for current file:
  82. #define mprngDictionary ((PRANGE)(gMasterTable \
  83. [MTI_RNGDICTIONARY].pubStruct))
  84. // static DWORD gdwLastIndex ; // leave this in this file only!
  85. // Now is part of the GLOBL structure.
  86. BOOL BcreateTokenMap(
  87. PWSTR pwstrFileName, // root GPD file
  88. PGLOBL pglobl)
  89. /* some things that occur within this function:
  90. Open and memory map initial file and any files specified
  91. by *Include.
  92. parse keyword, init aarKeyword field, set dwFlags,
  93. set dwKeywordID, parse Value , init aarValue,
  94. ArchiveStrings to tempHeap. During parsing of Values,
  95. comments and continuation lines are replaced by whitespaces.
  96. Assume each function in switch statement increments dwTKMindex
  97. by at most by 1. Otherwise undetected TokenMap overflow may occur.
  98. */
  99. {
  100. PTKMAP ptkmap ; // start of tokenmap
  101. DWORD dwTKMindex = 0, // current tokenKeyMap index
  102. dwCnt ; // counts length of keyword or value string
  103. PBYTE pubStart ; // start address of keyword or value string
  104. PARSTATE parst = PARST_KEYWORD ;
  105. // note in the case of the SOURCEBUFFERS, dwCurIndex is initialized
  106. // to zero by loadIncludeFile(). Since we never append onto
  107. // the existing source, dwCurIndex is used to track the current
  108. // position within the file (streamptr).
  109. // mCurFile initialized to 0 at buffer allocation time.
  110. gdwLastIndex = 0 ; // ok, allow BarchiveStrings() of all entries.
  111. gmrbd.rbd.dwSrcFileChecksum32 = 0 ;
  112. {
  113. PBYTE symbol ;
  114. symbol = "WINNT_40" ; // newer OSs support older OS features unless otherwise specified.
  115. if(! DefineSymbol(symbol, pglobl))
  116. return(FALSE) ;
  117. #ifndef WINNT_40
  118. symbol = "WINNT_50" ;
  119. if(! DefineSymbol(symbol, pglobl))
  120. return(FALSE) ;
  121. symbol = "WINNT_51" ;
  122. if(! DefineSymbol(symbol, pglobl))
  123. return(FALSE) ;
  124. #endif
  125. if(! DefineSymbol("PARSER_VER_1.0", pglobl)) // support multiple versions at once.
  126. return(FALSE) ;
  127. }
  128. if(! BloadFile(pwstrFileName, pglobl) )
  129. {
  130. return(FALSE) ;
  131. }
  132. if(!BPreProcess(pglobl) )
  133. return(FALSE) ;
  134. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  135. while(parst != PARST_EXIT)
  136. {
  137. if(dwTKMindex >= gMasterTable[MTI_TOKENMAP].dwArraySize)
  138. {
  139. ERR(("Internal: no more tokenmap elements - restart.\n"));
  140. if(ERRSEV_RESTART > geErrorSev)
  141. {
  142. geErrorSev = ERRSEV_RESTART ;
  143. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  144. gdwMasterTabIndex = MTI_TOKENMAP ;
  145. }
  146. return(FALSE) ;
  147. }
  148. switch(parst)
  149. {
  150. case (PARST_KEYWORD):
  151. {
  152. parst = PARSTscanForKeyword(&dwTKMindex, pglobl) ;
  153. break ;
  154. }
  155. case (PARST_COLON):
  156. {
  157. parst = PARSTparseColon(&dwTKMindex, pglobl) ;
  158. break ;
  159. }
  160. case (PARST_VALUE):
  161. {
  162. parst = PARSTparseValue(&dwTKMindex, pglobl) ;
  163. break ;
  164. }
  165. case (PARST_INCLUDEFILE):
  166. {
  167. parst = PARSTloadIncludeFile(&dwTKMindex, pwstrFileName, pglobl) ;
  168. if(!BPreProcess(pglobl) )
  169. return(FALSE) ;
  170. break ;
  171. }
  172. case (PARST_EOF) :
  173. {
  174. parst = PARSTrestorePrevsFile(&dwTKMindex, pglobl) ;
  175. if((parst != PARST_EXIT) && !BPreProcess(pglobl) )
  176. return(FALSE) ;
  177. if(parst == PARST_EXIT && mdwNestingLevel && geErrorSev != ERRSEV_FATAL)
  178. {
  179. ERR(("EOF reached before #Endif: was parsed!\n"));
  180. geErrorType = ERRTY_SYNTAX ;
  181. geErrorSev = ERRSEV_FATAL ;
  182. return(FALSE) ;
  183. }
  184. break ;
  185. }
  186. case (PARST_ABORT) :
  187. {
  188. return(FALSE) ; // abnormal termination.
  189. break ;
  190. }
  191. default:
  192. {
  193. ERR(("Internal error: no other PARST_ states exist!\n"));
  194. if(ERRSEV_FATAL > geErrorSev)
  195. {
  196. geErrorSev = ERRSEV_FATAL ;
  197. geErrorType = ERRTY_CODEBUG ;
  198. }
  199. return(FALSE) ;
  200. }
  201. }
  202. }
  203. return(TRUE) ;
  204. }
  205. PARSTATE PARSTscanForKeyword(
  206. PDWORD pdwTKMindex,
  207. PGLOBL pglobl)
  208. /* this function exits with 2 possible codes:
  209. PARST_EOF: end of source file encountered - return to parent file
  210. PARST_COLON: a keyword or symbol keyword was parsed, now expecting
  211. a colon delimiter.
  212. */
  213. {
  214. PTKMAP ptkmap ; // start of tokenmap
  215. // these two vars are just for inspiration, they may
  216. // never be used.
  217. DWORD dwCnt ; // counts length of keyword or value string
  218. PBYTE pubStart ; // start address of keyword or value string
  219. BYTE ubSrc ; // a src byte
  220. /* assume:
  221. no field in ptkmap[*pdwTKMindex] is initialized.
  222. pass all info by saving into ptkmap.
  223. always clear flags field and consume remainder of
  224. line up to first linebreak char in the event of
  225. a parsing error.
  226. we are looking for whichever occurs first:
  227. a) arbitrary white space
  228. c) { or }
  229. d) line break chars
  230. e) *keyword
  231. f) symbol keyword (not beginning with *)
  232. g) any other chars is a fatal error.
  233. */
  234. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  235. // was the previous entry an *include ?
  236. if(*pdwTKMindex)
  237. {
  238. DWORD dwKeywordID, dwSubType;
  239. dwKeywordID = ptkmap[*pdwTKMindex - 1].dwKeywordID ;
  240. if( (dwKeywordID < ID_SPECIAL) &&
  241. (mMainKeywordTable[dwKeywordID].eType == TY_SPECIAL))
  242. {
  243. dwSubType = mMainKeywordTable[dwKeywordID].dwSubType ;
  244. if( dwSubType == SPEC_INCLUDE )
  245. {
  246. (*pdwTKMindex)-- ; // make this the current entry again
  247. return(PARST_INCLUDEFILE) ;
  248. }
  249. else if( (dwSubType == SPEC_MEM_CONFIG_KB) ||
  250. ( dwSubType == SPEC_MEM_CONFIG_MB) )
  251. {
  252. BexpandMemConfigShortcut(dwSubType) ;
  253. // checks to make sure there are
  254. // enough slots in the tokenmap before proceeding.
  255. }
  256. }
  257. if(*pdwTKMindex > gdwLastIndex &&
  258. ! BarchiveStrings(*pdwTKMindex - 1, pglobl) )
  259. return(PARST_ABORT) ;
  260. gdwLastIndex = *pdwTKMindex ;
  261. // strings from each entry will get saved only once.
  262. }
  263. ptkmap[*pdwTKMindex].dwFileNameIndex =
  264. mpSourcebuffer[mCurFile - 1].dwFileNameIndex ;
  265. while( mdwSrcInd < mdwSrcMax )
  266. {
  267. if(!BeatArbitraryWhite(pglobl) )
  268. break ;
  269. ptkmap[*pdwTKMindex].dwLineNumber =
  270. mpSourcebuffer[mCurFile - 1].dwLineNumber ;
  271. switch(ubSrc = mpubSrcRef[mdwSrcInd])
  272. {
  273. case '*':
  274. {
  275. if(mdwSrcInd + 1 >= mdwSrcMax)
  276. {
  277. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  278. ERR(("Unexpected EOF encountered parsing Keyword.\n"));
  279. mdwSrcInd++ ; // move past * this
  280. // will trigger EOF detector.
  281. break ;
  282. }
  283. // assume it must be a keyword since it wasn't
  284. // consumed by eatArbitraryWhite().
  285. mdwSrcInd++ ; // move past *
  286. if(BparseKeyword(*pdwTKMindex, pglobl) )
  287. {
  288. ptkmap[*pdwTKMindex].dwKeywordID =
  289. DWidentifyKeyword(*pdwTKMindex, pglobl) ;
  290. return(PARST_COLON) ;
  291. }
  292. else
  293. {
  294. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  295. ERR(("syntax error in Keyword: %0.*s.\n", ptkmap[*pdwTKMindex].aarKeyword.dw + 1,
  296. ptkmap[*pdwTKMindex].aarKeyword.pub - 1));
  297. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  298. // must clear the flags
  299. mdwSrcInd-- ; // go back to *
  300. BeatComment(pglobl) ; // may place cursor at EOF
  301. }
  302. break ;
  303. }
  304. case '{':
  305. case '}':
  306. {
  307. ptkmap[*pdwTKMindex].aarKeyword.pub = mpubSrcRef +
  308. mdwSrcInd ;
  309. ptkmap[*pdwTKMindex].aarKeyword.dw = 1 ;
  310. ptkmap[*pdwTKMindex].aarValue.pub = 0 ;
  311. ptkmap[*pdwTKMindex].aarValue.dw = 0 ;
  312. ptkmap[*pdwTKMindex].dwFlags |= TKMF_NOVALUE ;
  313. ptkmap[*pdwTKMindex].dwKeywordID =
  314. DWidentifyKeyword(*pdwTKMindex, pglobl) ;
  315. (*pdwTKMindex)++ ; // this is the complete entry!
  316. mdwSrcInd++ ;
  317. return(PARST_KEYWORD); // re-enter this function
  318. break ; // from the top.
  319. }
  320. case '\x1A': // ignore control Z
  321. mdwSrcInd++ ;
  322. break;
  323. case '\n':
  324. {
  325. BYTE ubTmp ;
  326. mdwSrcInd++ ;
  327. if(mdwSrcInd < mdwSrcMax)
  328. {
  329. ubTmp = mpubSrcRef[mdwSrcInd] ;
  330. if(ubTmp == '\r')
  331. {
  332. mdwSrcInd++ ;
  333. }
  334. }
  335. mpSourcebuffer[mCurFile-1].dwLineNumber++ ;
  336. break ; // eat 'em up yum!
  337. }
  338. case '\r':
  339. {
  340. BYTE ubTmp ;
  341. mdwSrcInd++ ;
  342. if(mdwSrcInd < mdwSrcMax)
  343. {
  344. ubTmp = mpubSrcRef[mdwSrcInd] ;
  345. if(ubTmp == '\n')
  346. {
  347. mdwSrcInd++ ;
  348. }
  349. }
  350. mpSourcebuffer[mCurFile-1].dwLineNumber++ ;
  351. break ; // eat 'em up yum!
  352. }
  353. default:
  354. {
  355. if(BisExternKeyword(*pdwTKMindex, pglobl) )
  356. /* if this token matches either EXTERN_GLOBAL
  357. or EXTERN_FEATURE */
  358. {
  359. if(!BisColonNext(pglobl) )
  360. {
  361. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  362. ERR(("syntax error: Colon expected but missing.\n"));
  363. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  364. // must clear the flags
  365. // if there is a syntax error.
  366. BeatComment(pglobl) ; // may place cursor at EOF
  367. }
  368. // regardless of success or failure, we
  369. // remain in this function waiting for a *keyword.
  370. break ;
  371. }
  372. // parse token as a symbolkey.
  373. if(BparseKeyword(*pdwTKMindex, pglobl) )
  374. {
  375. ptkmap[*pdwTKMindex].dwKeywordID = ID_SYMBOL ;
  376. ptkmap[*pdwTKMindex].dwFlags |= TKMF_SYMBOL_KEYWORD ;
  377. return (PARST_COLON) ;
  378. }
  379. else
  380. {
  381. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  382. ERR(("syntax error: valid keyword token expected: %0.*s.\n", ptkmap[*pdwTKMindex].aarKeyword.dw,
  383. ptkmap[*pdwTKMindex].aarKeyword.pub));
  384. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  385. BeatComment(pglobl) ; // may place cursor at EOF
  386. }
  387. break ;
  388. } // end default case
  389. } // end switch
  390. } // end while
  391. return(PARST_EOF) ; // falls out of for loop.
  392. }
  393. PARSTATE PARSTparseColon(
  394. PDWORD pdwTKMindex,
  395. PGLOBL pglobl)
  396. /* this function exits with 3 possible codes:
  397. PARST_VALUE: a colon parsed, now expecting a value.
  398. PARST_KEYWORD: a line termination, EOF or illegal char was parsed.
  399. ready to parse a new entry.
  400. what looks to be a keyword has been parsed.
  401. attempt to look for a colon or line terminator.
  402. always clear flags field and consume remainder of
  403. line up to first linebreak char in the event of
  404. a parsing error.
  405. */
  406. {
  407. PTKMAP ptkmap ; // start of tokenmap
  408. BYTE ubSrc ; // a src byte
  409. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  410. if(!BeatArbitraryWhite(pglobl) )
  411. {
  412. // encountered EOF and no value found.
  413. ptkmap[*pdwTKMindex].dwFlags |= TKMF_NOVALUE ;
  414. (*pdwTKMindex)++ ; // entry complete
  415. return(PARST_KEYWORD) ;
  416. }
  417. if((ubSrc = mpubSrcRef[mdwSrcInd]) == ':')
  418. {
  419. mdwSrcInd++ ; // now expect a value
  420. return(PARST_VALUE) ;
  421. }
  422. else if(ubSrc == '\n' || ubSrc == '\r')
  423. {
  424. // encountered linebreak and no value found.
  425. ptkmap[*pdwTKMindex].dwFlags |= TKMF_NOVALUE ;
  426. (*pdwTKMindex)++ ; // entry complete
  427. return(PARST_KEYWORD) ;
  428. }
  429. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  430. ERR(("Colon expected after keyword: *%0.*s.\n", ptkmap[*pdwTKMindex].aarKeyword.dw,
  431. ptkmap[*pdwTKMindex].aarKeyword.pub));
  432. BeatComment(pglobl) ; // may place cursor at EOF
  433. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  434. return(PARST_KEYWORD) ;
  435. }
  436. PARSTATE PARSTparseValue(
  437. PDWORD pdwTKMindex,
  438. PGLOBL pglobl)
  439. /* this function exits with 1 possible codes:
  440. PARST_KEYWORD: correctly parsed value, a line termination, EOF
  441. or illegal char was parsed. ready to parse a new entry.
  442. Cursor is initially just past the colon delimiter, the purpose of
  443. this function is to locate the end of the value construct. That
  444. is parse up to the level 0 { or } or linebreak.
  445. Replace any comments and continuation constructs that occur
  446. within this value with spaces.
  447. This function makes no assumptions about the type
  448. of value, it only assumes the value may be comprised of none, one
  449. of more tokens (separated by optional whitespace) of the form:
  450. LIST(aaa, bbb, ccc)
  451. POINT(), RECT()
  452. integer: *, + - nnnn
  453. Symbols, CONSTANTS
  454. "strings%"" %{command params}
  455. qualified.names
  456. =macroname
  457. We cannot simply stop scanning when { or } or non-continuation
  458. linebreak is encountered because the chars { and } may occur
  459. within comments, strings or command parameters. Each of these
  460. constructs are governed by different parsing rules and hence
  461. are parsed by their own specialized functions.
  462. This function assumes all comments are preceeded by a
  463. white character.
  464. */
  465. {
  466. PTKMAP ptkmap ; // start of tokenmap
  467. BYTE ubSrc ; // a src byte
  468. DWORD dwOrgInd; // holds index of start of value.
  469. ptkmap = (PTKMAP) (gMasterTable[MTI_TOKENMAP].pubStruct) ;
  470. if(!BeatArbitraryWhite(pglobl) )
  471. {
  472. ptkmap[*pdwTKMindex].dwFlags |= TKMF_NOVALUE ;
  473. (*pdwTKMindex)++ ; // entry complete
  474. return(PARST_KEYWORD) ;
  475. }
  476. ptkmap[*pdwTKMindex].aarValue.pub = mpubSrcRef +
  477. mdwSrcInd ;
  478. dwOrgInd = mdwSrcInd ;
  479. while((ubSrc = mpubSrcRef[mdwSrcInd]) != '{' && ubSrc != '}' &&
  480. ubSrc != '\n' && ubSrc != '\r')
  481. {
  482. switch(ubSrc)
  483. {
  484. case '*': // integer wildcard
  485. case '-': // integer neg sign
  486. case '+': // integer plus sign
  487. case '.': // separator for qualified name
  488. case '?': // valid char for symbolname
  489. case '_': // valid char for symbolname
  490. {
  491. mdwSrcInd++ ; // go past this
  492. break ;
  493. }
  494. case ':': // additional token in value - shortcut?
  495. {
  496. ptkmap[*pdwTKMindex].dwFlags |= TKMF_COLON ;
  497. mdwSrcInd++ ; // go past this
  498. break ;
  499. }
  500. case '=': // macroname indicator
  501. {
  502. ptkmap[*pdwTKMindex].dwFlags |= TKMF_MACROREF ;
  503. mdwSrcInd++ ; // go past this
  504. break ;
  505. }
  506. case '%': // command parameter
  507. {
  508. if(!BscanDelimitedString('}', NULL, pglobl) )
  509. {
  510. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  511. ERR(("Expected closing '}'.\n"));
  512. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  513. return(PARST_KEYWORD) ;
  514. }
  515. break ;
  516. }
  517. case '"' : // this is a string construct
  518. {
  519. mdwSrcInd++ ; // go past this
  520. if(!BscanStringSegment(pglobl) )
  521. {
  522. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  523. ERR(("Error parsing string segment: %0.*s.\n",
  524. mdwSrcInd - dwOrgInd,
  525. ptkmap[*pdwTKMindex].aarValue.pub));
  526. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  527. return(PARST_KEYWORD) ;
  528. }
  529. break ;
  530. }
  531. case '(': // arg list for LIST, POINT or RECT
  532. {
  533. BOOL bMacroDetected ;
  534. if(!BscanDelimitedString(')', &bMacroDetected, pglobl) )
  535. {
  536. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  537. ERR(("Expected closing ')'.\n"));
  538. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  539. return(PARST_KEYWORD) ;
  540. }
  541. if(bMacroDetected)
  542. ptkmap[*pdwTKMindex].dwFlags |= TKMF_MACROREF ;
  543. break ;
  544. }
  545. default:
  546. {
  547. if( (ubSrc >= 'a' && ubSrc <= 'z') ||
  548. (ubSrc >= 'A' && ubSrc <= 'Z') ||
  549. (ubSrc >= '0' && ubSrc <= '9') )
  550. {
  551. mdwSrcInd++ ; // looks legal, next char
  552. break ;
  553. }
  554. else
  555. {
  556. vIdentifySource(ptkmap + *pdwTKMindex, pglobl) ;
  557. ERR(("illegal char encountered parsing value: %0.*s.\n",
  558. mdwSrcInd - dwOrgInd,
  559. ptkmap[*pdwTKMindex].aarValue.pub));
  560. ERR((" Line ignored.\n")) ;
  561. ptkmap[*pdwTKMindex].dwFlags = 0 ;
  562. BeatComment(pglobl) ;
  563. ptkmap[*pdwTKMindex].dwKeywordID = gdwID_IgnoreBlock;
  564. (*pdwTKMindex)++ ; // entry complete
  565. return(PARST_KEYWORD) ;
  566. }
  567. }
  568. }
  569. if(!BeatArbitraryWhite(pglobl) )
  570. {
  571. ptkmap[*pdwTKMindex].aarValue.dw =
  572. mdwSrcInd - dwOrgInd ;
  573. if(!(mdwSrcInd - dwOrgInd))
  574. ptkmap[*pdwTKMindex].dwFlags |= TKMF_NOVALUE ;
  575. (*pdwTKMindex)++ ; // entry complete
  576. return(PARST_KEYWORD) ; // end of file encountered.
  577. }
  578. }
  579. ptkmap[*pdwTKMindex].aarValue.dw = mdwSrcInd - dwOrgInd ;
  580. if(!(mdwSrcInd - dwOrgInd))
  581. ptkmap[*pdwTKMindex].dwFlags |= TKMF_NOVALUE ;
  582. (*pdwTKMindex)++ ; // entry complete
  583. return(PARST_KEYWORD) ;
  584. }
  585. /* all of the following helper functions
  586. leaves the cursor after the object being parsed
  587. if successful, otherwise cursor is unchanged
  588. except for consuming leading whitespace.
  589. Return value means sucess in parsing or
  590. simply that EOF was not encountered, see
  591. specific function. */
  592. BOOL BparseKeyword(
  593. DWORD dwTKMindex,
  594. PGLOBL pglobl)
  595. /* assumes mdwSrcInd points to start of keyword (char
  596. just after *). Determine end of keyword. mdwSrcInd advanced
  597. past end of keyword. Initializes tokenmap entry aarKeyword.
  598. */
  599. {
  600. PTKMAP ptkmap ; // start of tokenmap
  601. DWORD dwCnt ; // counts length of keyword or value string
  602. BYTE ubSrc ; // a src byte
  603. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  604. ptkmap[dwTKMindex].aarKeyword.pub = mpubSrcRef +
  605. mdwSrcInd ;
  606. for(dwCnt = 0 ; mdwSrcInd < mdwSrcMax ; mdwSrcInd++, dwCnt++)
  607. {
  608. ubSrc = mpubSrcRef[mdwSrcInd] ;
  609. if(ubSrc == '?')
  610. {
  611. mdwSrcInd++ ;
  612. dwCnt++ ;
  613. break; // the ? char is permitted as a terminator only.
  614. }
  615. if( (ubSrc < 'a' || ubSrc > 'z') &&
  616. (ubSrc < 'A' || ubSrc > 'Z') &&
  617. (ubSrc < '0' || ubSrc > '9') &&
  618. (ubSrc != '_') )
  619. {
  620. break ; // end of keyword token.
  621. }
  622. }
  623. ptkmap[dwTKMindex].aarKeyword.dw = dwCnt ;
  624. return(dwCnt != 0);
  625. }
  626. BOOL BisExternKeyword(
  627. DWORD dwTKMindex,
  628. PGLOBL pglobl)
  629. /* if this token matches either EXTERN_GLOBAL
  630. or EXTERN_FEATURE, this function sets the approp
  631. flag in the tokenentry, advances mdwSrcInd past
  632. qualifier and returns true. Else it leaves everything
  633. undisturbed and returns false.
  634. */
  635. {
  636. PTKMAP ptkmap ; // start of tokenmap
  637. DWORD dwCnt ; // counts length of keyword or value string
  638. BYTE ubSrc ; // a src byte
  639. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  640. if((dwCnt = strlen("EXTERN_GLOBAL"))
  641. && (mdwSrcInd + dwCnt <= mdwSrcMax)
  642. && !strncmp(mpubSrcRef + mdwSrcInd , "EXTERN_GLOBAL", dwCnt ))
  643. {
  644. ptkmap[dwTKMindex].dwFlags |= TKMF_EXTERN_GLOBAL ;
  645. }
  646. else if(dwCnt = strlen("EXTERN_FEATURE") &&
  647. mdwSrcInd + dwCnt <= mdwSrcMax &&
  648. !strncmp(mpubSrcRef + mdwSrcInd , "EXTERN_FEATURE", dwCnt ))
  649. {
  650. ptkmap[dwTKMindex].dwFlags |= TKMF_EXTERN_FEATURE ;
  651. }
  652. else
  653. return(FALSE);
  654. mdwSrcInd += dwCnt ; // skip past qualifier
  655. return(TRUE);
  656. }
  657. BOOL BisColonNext(
  658. PGLOBL pglobl)
  659. {
  660. if(BeatArbitraryWhite(pglobl) && mpubSrcRef[mdwSrcInd] == ':')
  661. {
  662. mdwSrcInd++ ; // advance past colon.
  663. return(TRUE) ;
  664. }
  665. return(FALSE); // leave pointing to non-colon object.
  666. }
  667. BOOL BeatArbitraryWhite(
  668. PGLOBL pglobl)
  669. /* does nothing if not positioned
  670. at arbitrary whitespace, returns FALSE
  671. only if EOF is encountered.
  672. Will replace comments and continuation constructs
  673. with spaces.
  674. */
  675. {
  676. BYTE ubSrc ; // a src byte
  677. while( mdwSrcInd < mdwSrcMax )
  678. {
  679. switch(ubSrc = mpubSrcRef[mdwSrcInd])
  680. {
  681. case '*': // a comment?
  682. {
  683. if(mdwSrcInd + 1 < mdwSrcMax &&
  684. mpubSrcRef[mdwSrcInd + 1] == '%')
  685. {
  686. if(!BeatComment(pglobl) ) // leave pointing at linebreak.
  687. return(FALSE) ; // reached EOF.
  688. }
  689. else
  690. return(TRUE) ; // reached non-white.
  691. break ;
  692. }
  693. case ' ':
  694. case '\t':
  695. {
  696. mdwSrcInd++ ; // go to next char
  697. break ;
  698. }
  699. case '\r': // eat continuation constructs
  700. case '\n': // do not process normal EOL chars.
  701. {
  702. BYTE ubTmp ;
  703. if(mdwSrcInd + 1 < mdwSrcMax)
  704. {
  705. ubTmp = mpubSrcRef[mdwSrcInd + 1] ;
  706. if(ubTmp == '+')
  707. {
  708. mpubSrcRef[mdwSrcInd] = ' ' ;
  709. mpubSrcRef[mdwSrcInd + 1] = ' ' ;
  710. mdwSrcInd += 2 ; // skip past '+'
  711. mpSourcebuffer[mCurFile-1].dwLineNumber++ ;
  712. break ;
  713. }
  714. else if( ((ubTmp == '\n') || (ubTmp == '\r'))
  715. && (ubTmp != ubSrc)
  716. && (mdwSrcInd + 2 < mdwSrcMax)
  717. && (mpubSrcRef[mdwSrcInd + 2] == '+') )
  718. {
  719. mpubSrcRef[mdwSrcInd] = ' ' ;
  720. mpubSrcRef[mdwSrcInd + 1] = ' ' ;
  721. mpubSrcRef[mdwSrcInd + 2] = ' ' ;
  722. mdwSrcInd += 3 ; // skip past '+'
  723. mpSourcebuffer[mCurFile-1].dwLineNumber++ ;
  724. break ;
  725. }
  726. }
  727. return(TRUE) ; // reached logical linebreak.
  728. }
  729. default:
  730. return(TRUE) ; // reached non-white.
  731. }
  732. }
  733. return(FALSE) ; // reached EOF.
  734. }
  735. BOOL BeatComment(
  736. PGLOBL pglobl)
  737. // replaces entire comment with spaces until
  738. // linebreak char or EOF is encountered.
  739. {
  740. BYTE ubSrc ; // a src byte
  741. for( ; mdwSrcInd < mdwSrcMax ; mdwSrcInd++)
  742. {
  743. ubSrc = mpubSrcRef[mdwSrcInd] ;
  744. if(ubSrc == '\n' || ubSrc == '\r' )
  745. return(TRUE) ; // reached linebreak char.
  746. mpubSrcRef[mdwSrcInd] = ' ' ; // replace with space.
  747. }
  748. return(FALSE) ; // reached EOF.
  749. }
  750. BOOL BscanStringSegment(
  751. PGLOBL pglobl)
  752. // cursor set just after first "
  753. {
  754. BYTE ubSrc = '\0', // a src byte
  755. ubPrevs ;
  756. while( mdwSrcInd < mdwSrcMax )
  757. {
  758. ubPrevs = ubSrc ;
  759. ubSrc = mpubSrcRef[mdwSrcInd] ;
  760. if(ubSrc == '<' && ubPrevs != '%')
  761. {
  762. mdwSrcInd++ ; // skip <
  763. if(!BscanDelimitedString('>', NULL, pglobl) )
  764. {
  765. ERR(("\nMissing closing > in string segment.\n"));
  766. return(FALSE) ;
  767. }
  768. continue ; // leaves cursor pointing after '>'
  769. }
  770. else if(ubSrc == '"' && ubPrevs != '%')
  771. {
  772. mdwSrcInd++ ; // end of literal string
  773. return(TRUE) ;
  774. }
  775. else if(ubSrc == '\n' || ubSrc == '\r')
  776. break ;
  777. else
  778. mdwSrcInd++ ; // scan through string
  779. }
  780. ERR(("\nLinebreak or EOF was encountered while parsing string segment.\n"));
  781. return(FALSE) ;
  782. }
  783. BOOL BscanDelimitedString(
  784. BYTE ubDelimiter, // the byte that signifies the end.
  785. PBOOL pbMacroDetected, // set true if '=' was encountered.
  786. PGLOBL pglobl)
  787. // cursor set just after first <
  788. {
  789. BYTE ubSrc ; // a src byte
  790. if(pbMacroDetected)
  791. *pbMacroDetected = FALSE;
  792. while( mdwSrcInd < mdwSrcMax )
  793. {
  794. ubSrc = mpubSrcRef[mdwSrcInd] ;
  795. if(ubSrc == ubDelimiter)
  796. { // end of hex substring construct
  797. mdwSrcInd++ ;
  798. return(TRUE) ;
  799. }
  800. else if(ubSrc == ' ' || ubSrc == '\t' ||
  801. ubSrc == '\n' || ubSrc == '\r')
  802. {
  803. if(!BeatArbitraryWhite(pglobl) )
  804. break ;
  805. ubSrc = mpubSrcRef[mdwSrcInd] ;
  806. if(ubSrc == '\n' || ubSrc == '\r')
  807. break ;
  808. }
  809. else
  810. {
  811. mdwSrcInd++ ; // keep parsing
  812. if(ubSrc == '=' && pbMacroDetected)
  813. *pbMacroDetected = TRUE ;
  814. }
  815. }
  816. ERR(("unexpected linebreak or EOF.\n"));
  817. return(FALSE) ; // BUG_BUG! unexpected linebreak or EOF
  818. // in hex substring if delimiter was >
  819. // LIST, POINT, etc if delimiter was ).
  820. // command parameter if delimiter was }
  821. }
  822. PARSTATE PARSTrestorePrevsFile(
  823. PDWORD pdwTKMindex,
  824. PGLOBL pglobl)
  825. /* this function exits with 2 possible codes:
  826. PARST_EXIT: no more files left in stack !
  827. PARST_KEYWORD: returned to prevs file. Ready to
  828. resume parsing of new tokenmap entry.
  829. The only function that issues PARST_EOF is parseKeyword().
  830. It handles all processing for the previous keyword.
  831. */
  832. {
  833. PTKMAP ptkmap ; // start of tokenmap
  834. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  835. mCurFile-- ; // pop stack
  836. MemFree(mpSourcebuffer[mCurFile].pubSrcBuf) ;
  837. if(mCurFile)
  838. return(PARST_KEYWORD) ;
  839. ptkmap[*pdwTKMindex].dwKeywordID = ID_EOF ;
  840. (*pdwTKMindex)++ ;
  841. // this is the last entry in the tokenmap.
  842. return(PARST_EXIT) ; // reached end of rootfile.
  843. }
  844. PWSTR
  845. PwstrAnsiToUnicode(
  846. IN PSTR pstrAnsiString,
  847. PGLOBL pglobl
  848. )
  849. /*++
  850. Routine Description:
  851. Make a Unicode copy of the input ANSI string
  852. Warning: caller must delete Unicode copy when finished
  853. Arguments:
  854. pstrAnsiString - Pointer to the input ANSI string
  855. Return Value:
  856. Pointer to the resulting Unicode string
  857. NULL if there is an error
  858. --*/
  859. {
  860. PWSTR pwstr; // holds Unicode string
  861. DWORD dwLen ;
  862. ASSERT(pstrAnsiString != NULL);
  863. dwLen = strlen(pstrAnsiString) + 1;
  864. if (pwstr = (PWSTR)MemAlloc(dwLen * sizeof(WCHAR)))
  865. {
  866. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pstrAnsiString, dwLen,
  867. pwstr, dwLen);
  868. //
  869. // Make sure the Unicode string is null-terminated
  870. //
  871. pwstr[dwLen - 1] = NUL;
  872. }
  873. else
  874. {
  875. ERR(("Fatal: unable to alloc requested memory: %d bytes.\n",
  876. dwLen * sizeof(WCHAR)));
  877. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  878. geErrorSev = ERRSEV_FATAL ;
  879. }
  880. return pwstr;
  881. }
  882. PARSTATE PARSTloadIncludeFile(
  883. PDWORD pdwTKMindex,
  884. PWSTR pwstrRootFileName, // root GPD file
  885. PGLOBL pglobl)
  886. /* this function exits with 2 possible codes:
  887. PARST_ABORT: unable to read included file, force termination.
  888. PARST_KEYWORD: opened file, updated SOURCEBUFFER stack,
  889. ready to parse a new tokenmap entry which will overwrite the
  890. *Include entry.
  891. pdwTKMindex points to tokenmap entry containing the
  892. *include keyword.
  893. Each Memory Mapped file is referenced by a SOURCEBUFFER
  894. structure.
  895. typedef struct
  896. {
  897. PBYTE pubSrcBuf ; // start of file bytes.
  898. DWORD dwCurIndex ; // stream ptr
  899. DWORD dwArraySize ; // filesize
  900. PWSTR pwstrFileName ;
  901. HFILEMAP hFile ; // used to access/close file.
  902. } SOURCEBUFFER, * PSOURCEBUFFER ;
  903. // the tagname is 'sb'
  904. */
  905. {
  906. PTKMAP ptkmap ; // start of tokenmap
  907. ARRAYREF arStrValue ; // dest for BparseString.
  908. PWSTR pwstrFileName ; // , pwstrFullyQualifiedName = NULL;
  909. WCHAR * pwDLLQualifiedName = NULL ;
  910. PBYTE pubFileName ;
  911. PARSTATE parst = PARST_KEYWORD;
  912. PWSTR pwstrLastBackSlash ;
  913. DWORD pathlen = 0 ;
  914. DWORD namelen = 0 ;
  915. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  916. // does a value exist?
  917. if(ptkmap[*pdwTKMindex].dwFlags & TKMF_NOVALUE ||
  918. !BparseString(&(ptkmap[*pdwTKMindex].aarValue), &arStrValue, pglobl) )
  919. {
  920. ERR(("syntax error in filename for *Include keyword.\n"));
  921. // fatal error. override initial error code.
  922. return(PARST_ABORT) ;
  923. }
  924. #if !defined(DEVSTUDIO)
  925. // nothing here !
  926. #endif
  927. pubFileName = mpubOffRef + arStrValue.loOffset ;
  928. pwstrFileName = PwstrAnsiToUnicode(pubFileName, pglobl) ;
  929. if(!pwstrFileName)
  930. {
  931. parst = PARST_ABORT ;
  932. goto FREE_MEM ;
  933. }
  934. #if !defined(DEVSTUDIO)
  935. // how large should pwDLLQualifiedName be???
  936. pathlen = wcslen(pwstrRootFileName) ;
  937. namelen = pathlen + wcslen(pwstrFileName) + 1;
  938. if (!(pwDLLQualifiedName =
  939. (PWSTR)MemAlloc(namelen * sizeof(WCHAR)) ))
  940. {
  941. ERR(("Fatal: unable to alloc requested memory: %d WCHARs.\n",
  942. namelen));
  943. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  944. geErrorSev = ERRSEV_FATAL ;
  945. return(PARST_ABORT) ;
  946. }
  947. wcsncpy(pwDLLQualifiedName, pwstrRootFileName , namelen);
  948. if (pwstrLastBackSlash = wcsrchr(pwDLLQualifiedName,TEXT('\\')))
  949. {
  950. *(pwstrLastBackSlash + 1) = NUL;
  951. // wcscat(pwDLLQualifiedName, pwstrFileName) ;
  952. StringCchCatW(pwDLLQualifiedName, namelen, pwstrFileName);
  953. }
  954. else
  955. {
  956. ERR(("Internal Error: Must specify fully qualified path to Root GPD file.\n"));
  957. // fatal error. override initial error code.
  958. parst = PARST_ABORT ;
  959. goto FREE_MEM ;
  960. }
  961. if(! BloadFile(pwDLLQualifiedName, pglobl) )
  962. #else
  963. if(! BloadFile(pwstrFileName, pglobl) )
  964. #endif
  965. parst = PARST_ABORT ;
  966. else
  967. parst = PARST_KEYWORD ;
  968. FREE_MEM:
  969. if(pwstrFileName)
  970. MemFree(pwstrFileName) ;
  971. if(pwDLLQualifiedName)
  972. MemFree(pwDLLQualifiedName) ;
  973. return(parst) ;
  974. }
  975. BOOL BloadFile(
  976. PWSTR pwstrFileName,
  977. PGLOBL pglobl)
  978. {
  979. PBYTE pub ;
  980. PGPDFILEDATEINFO pfdi ;
  981. DWORD dwNodeIndex ;
  982. HANDLE hFile;
  983. // mCurFile points to first uninitialized SOURCEBUFFER element
  984. if(mCurFile >= mMaxFiles)
  985. {
  986. // nesting level too deep.
  987. if(ERRSEV_RESTART > geErrorSev)
  988. {
  989. geErrorSev = ERRSEV_RESTART ;
  990. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  991. gdwMasterTabIndex = MTI_SOURCEBUFFER ;
  992. }
  993. return(FALSE) ;
  994. }
  995. pfdi = (PGPDFILEDATEINFO) gMasterTable[MTI_GPDFILEDATEINFO].pubStruct ;
  996. // address of first GPDFILEDATEINFO struct
  997. if(! BallocElementFromMasterTable(MTI_GPDFILEDATEINFO , &dwNodeIndex, pglobl) )
  998. {
  999. return(FALSE) ;
  1000. }
  1001. mpSourcebuffer[mCurFile].dwFileNameIndex =
  1002. dwStoreFileName(pwstrFileName, &pfdi[dwNodeIndex].arFileName, pglobl) ;
  1003. // store Unicode representation of filename for diagnostic purposes.
  1004. if(mpSourcebuffer[mCurFile].dwFileNameIndex == INVALID_INDEX)
  1005. {
  1006. return(FALSE) ; // something failed
  1007. }
  1008. mpSourcebuffer[mCurFile].dwLineNumber = 1 ; // new rule: line 0 does not exist.
  1009. mpSourcebuffer[mCurFile].hFile = MapFileIntoMemory(
  1010. pwstrFileName, (PVOID *)&(pub),
  1011. &(mpSourcebuffer[mCurFile].dwArraySize)) ;
  1012. if(!mpSourcebuffer[mCurFile].hFile || !pub)
  1013. {
  1014. ERR(("unable to open GPD file: %S\n", pwstrFileName));
  1015. // set fatal error
  1016. geErrorSev = ERRSEV_FATAL ;
  1017. geErrorType = ERRTY_FILE_OPEN ;
  1018. return(FALSE) ;
  1019. }
  1020. // mapping successful. allocate writable buffer.
  1021. mpSourcebuffer[mCurFile].pubSrcBuf =
  1022. MemAlloc(mpSourcebuffer[mCurFile].dwArraySize) ;
  1023. if(!(mpSourcebuffer[mCurFile].pubSrcBuf))
  1024. {
  1025. ERR(("Fatal: unable to alloc requested memory: %d bytes.\n",
  1026. mpSourcebuffer[mCurFile].dwArraySize));
  1027. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  1028. geErrorSev = ERRSEV_FATAL ;
  1029. gdwMasterTabIndex = MTI_SOURCEBUFFER ;
  1030. UnmapFileFromMemory(mpSourcebuffer[mCurFile].hFile) ;
  1031. return(FALSE) ; // This is unrecoverable
  1032. }
  1033. memcpy(mpSourcebuffer[mCurFile].pubSrcBuf,
  1034. pub, mpSourcebuffer[mCurFile].dwArraySize) ;
  1035. UnmapFileFromMemory(mpSourcebuffer[mCurFile].hFile) ;
  1036. // reopen to determine timestamp.
  1037. hFile = CreateFile(pwstrFileName,
  1038. GENERIC_READ,
  1039. FILE_SHARE_READ,
  1040. NULL,
  1041. OPEN_EXISTING,
  1042. FILE_ATTRIBUTE_NORMAL | SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS,
  1043. NULL);
  1044. if (hFile != INVALID_HANDLE_VALUE)
  1045. {
  1046. if(!GetFileTime(hFile, NULL, NULL,
  1047. &pfdi[dwNodeIndex].FileTime) )
  1048. {
  1049. ERR(("GetFileTime '%S' failed.\n", pwstrFileName));
  1050. }
  1051. CloseHandle(hFile);
  1052. }
  1053. else
  1054. {
  1055. geErrorSev = ERRSEV_FATAL;
  1056. geErrorType = ERRTY_FILE_OPEN;
  1057. ERR(("CreateFile '%S' failed.\n", pwstrFileName));
  1058. }
  1059. gmrbd.rbd.dwSrcFileChecksum32 =
  1060. ComputeCrc32Checksum(
  1061. mpSourcebuffer[mCurFile].pubSrcBuf,
  1062. mpSourcebuffer[mCurFile].dwArraySize,
  1063. gmrbd.rbd.dwSrcFileChecksum32 ) ;
  1064. mCurFile++ ; // we now have an open file on the stack
  1065. mdwSrcInd = 0 ; // initialize stream ptr to start of file.
  1066. return(TRUE) ;
  1067. }
  1068. BOOL BarchiveStrings(
  1069. DWORD dwTKMindex,
  1070. PGLOBL pglobl)
  1071. /*
  1072. you see the Memory Mapped file only exists until
  1073. parsing reaches EOF. At that time its closed.
  1074. And all the aars stored in the tokenmap become useless.
  1075. So to extend their lifetime, we copy the strings to
  1076. a temporary heap. A heap that isn't going to be
  1077. saved as part of the GPD binary file.
  1078. */
  1079. {
  1080. PTKMAP ptkmap ; // start of tokenmap
  1081. DWORD dwKeywordID ;
  1082. ABSARRAYREF aarDest ;
  1083. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  1084. dwKeywordID = ptkmap[dwTKMindex].dwKeywordID ;
  1085. if((dwKeywordID != ID_NULLENTRY) && (dwKeywordID != ID_EOF) )
  1086. {
  1087. // copy keyword string over
  1088. if(!BcopyToTmpHeap(&aarDest, &(ptkmap[dwTKMindex].aarKeyword), pglobl))
  1089. return(FALSE) ;
  1090. ptkmap[dwTKMindex].aarKeyword.pub = aarDest.pub ;
  1091. ptkmap[dwTKMindex].aarKeyword.dw = aarDest.dw ;
  1092. if(!(ptkmap[dwTKMindex].dwFlags & TKMF_NOVALUE))
  1093. {
  1094. // copy value string over.
  1095. if(!BcopyToTmpHeap(&aarDest, &(ptkmap[dwTKMindex].aarValue), pglobl))
  1096. return(FALSE) ;
  1097. ptkmap[dwTKMindex].aarValue.pub = aarDest.pub ;
  1098. ptkmap[dwTKMindex].aarValue.dw = aarDest.dw ;
  1099. }
  1100. }
  1101. return(TRUE) ;
  1102. }
  1103. DWORD DWidentifyKeyword(
  1104. DWORD dwTKMindex,
  1105. PGLOBL pglobl)
  1106. /* assumes keywords are not symbol keywords.
  1107. if they are attribute keywords they will be labeled
  1108. as ID_UNRECOGNIZED.
  1109. returns (KeywordID) */
  1110. {
  1111. PTKMAP ptkmap ; // start of tokenmap
  1112. DWORD dwCnt ; // counts length of keyword or value string
  1113. DWORD dwKeyID ; // array index of MainKeywordTable
  1114. // also serves as the keywordID
  1115. PBYTE pubKey ;
  1116. DWORD dwStart, dwEnd ;
  1117. ptkmap = (PTKMAP) gMasterTable[MTI_TOKENMAP].pubStruct ;
  1118. if(ptkmap[dwTKMindex].dwFlags & TKMF_SYMBOL_KEYWORD)
  1119. {
  1120. return(ID_SYMBOL) ; // safety net.
  1121. }
  1122. dwStart = mprngDictionary[NON_ATTR].dwStart ;
  1123. dwEnd = mprngDictionary[NON_ATTR].dwEnd ;
  1124. for(dwKeyID = dwStart ; dwKeyID < dwEnd ; dwKeyID++ )
  1125. {
  1126. pubKey = mMainKeywordTable[dwKeyID].pstrKeyword ;
  1127. dwCnt = strlen(pubKey) ;
  1128. if(dwCnt != ptkmap[dwTKMindex].aarKeyword.dw)
  1129. continue ;
  1130. if(strncmp(ptkmap[dwTKMindex].aarKeyword.pub, pubKey, dwCnt))
  1131. continue ;
  1132. return(dwKeyID);
  1133. }
  1134. return(ID_UNRECOGNIZED) ; // does not attempt to identify
  1135. // attributes, this is done in BInterpretTokens().
  1136. }
  1137. BOOL BidentifyAttributeKeyword(
  1138. PTKMAP ptkmap, // pointer to tokenmap
  1139. PGLOBL pglobl
  1140. )
  1141. /*
  1142. // Assume this is an attribute keyword.
  1143. // If the flags TKMF_EXTERN_GLOBAL or _FEATURE
  1144. // the GPD author is explicitly identifying
  1145. // this as an attribute. Else look at the current
  1146. // state as an indication of which attribute dictionary
  1147. // to look at.
  1148. */
  1149. {
  1150. DWORD dwKeywordID ;
  1151. STATE stOldState;
  1152. KEYWORD_SECTS eSection ;
  1153. DWORD dwStart, dwEnd , dwKeyID,
  1154. dwCnt ; // counts length of keyword or value string
  1155. PBYTE pubKey ;
  1156. if(ptkmap->dwFlags & TKMF_EXTERN_GLOBAL )
  1157. eSection = GLOBAL_ATTR ;
  1158. else if(ptkmap->dwFlags & TKMF_EXTERN_FEATURE )
  1159. eSection = FEATURE_ATTR ;
  1160. else
  1161. {
  1162. if(mdwCurStsPtr)
  1163. stOldState = mpstsStateStack[mdwCurStsPtr - 1].stState ;
  1164. else
  1165. stOldState = STATE_ROOT ;
  1166. switch(stOldState)
  1167. {
  1168. case (STATE_ROOT):
  1169. case (STATE_CASE_ROOT):
  1170. case (STATE_DEFAULT_ROOT):
  1171. {
  1172. eSection = GLOBAL_ATTR;
  1173. break ;
  1174. }
  1175. case (STATE_FEATURE):
  1176. case (STATE_CASE_FEATURE):
  1177. case (STATE_DEFAULT_FEATURE):
  1178. {
  1179. eSection = FEATURE_ATTR;
  1180. break ;
  1181. }
  1182. case (STATE_OPTIONS):
  1183. case (STATE_CASE_OPTION):
  1184. case (STATE_DEFAULT_OPTION):
  1185. {
  1186. eSection = OPTION_ATTR;
  1187. break ;
  1188. }
  1189. case (STATE_COMMAND):
  1190. {
  1191. eSection = COMMAND_ATTR;
  1192. break ;
  1193. }
  1194. case (STATE_FONTCART):
  1195. {
  1196. eSection = FONTCART_ATTR ;
  1197. break ;
  1198. }
  1199. case (STATE_TTFONTSUBS):
  1200. {
  1201. eSection = TTFONTSUBS_ATTR ;
  1202. break ;
  1203. }
  1204. case (STATE_OEM):
  1205. {
  1206. eSection = OEM_ATTR ;
  1207. break ;
  1208. }
  1209. default: // STATE_UIGROUP, STATE_SWITCH_anything etc.
  1210. {
  1211. return(FALSE); // no attributes allowed in this state.
  1212. }
  1213. }
  1214. }
  1215. dwStart = mprngDictionary[eSection].dwStart ;
  1216. dwEnd = mprngDictionary[eSection].dwEnd ;
  1217. for(dwKeyID = dwStart ; dwKeyID < dwEnd ; dwKeyID++ )
  1218. {
  1219. pubKey = mMainKeywordTable[dwKeyID].pstrKeyword ;
  1220. dwCnt = strlen(pubKey) ;
  1221. if(dwCnt != ptkmap->aarKeyword.dw)
  1222. continue ;
  1223. if(strncmp(ptkmap->aarKeyword.pub, pubKey, dwCnt))
  1224. continue ;
  1225. ptkmap->dwKeywordID = dwKeyID;
  1226. return(TRUE);
  1227. }
  1228. return(FALSE); // keyword not found in dictionary.
  1229. }
  1230. BOOL BcopyToTmpHeap(
  1231. PABSARRAYREF paarDest,
  1232. PABSARRAYREF paarSrc,
  1233. PGLOBL pglobl)
  1234. /* copy aarstring to the temp heap
  1235. does not create null terminated strings! */
  1236. {
  1237. #define mpubOffReft (gMasterTable[MTI_TMPHEAP].pubStruct)
  1238. #define mloCurHeapt (gMasterTable[MTI_TMPHEAP].dwCurIndex)
  1239. #define mdwMaxHeapt (gMasterTable[MTI_TMPHEAP].dwArraySize)
  1240. if(mloCurHeapt + paarSrc->dw >= mdwMaxHeapt)
  1241. {
  1242. ERR(("Out of heap space, restart.\n"));
  1243. if(ERRSEV_RESTART > geErrorSev)
  1244. {
  1245. geErrorSev = ERRSEV_RESTART ;
  1246. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  1247. gdwMasterTabIndex = MTI_TMPHEAP ;
  1248. }
  1249. return(FALSE) ;
  1250. }
  1251. paarDest->dw = paarSrc->dw ;
  1252. paarDest->pub = mpubOffReft + mloCurHeapt ;
  1253. memcpy(paarDest->pub, paarSrc->pub, paarSrc->dw ) ;
  1254. mloCurHeapt += paarSrc->dw ;
  1255. return(TRUE) ;
  1256. #undef mpubOffReft
  1257. #undef mloCurHeapt
  1258. #undef mdwMaxHeapt
  1259. }
  1260. #define mCurFileName (gMasterTable[MTI_FILENAMES].dwCurIndex)
  1261. #define mpFileNamesArray ((PWSTR *)(gMasterTable \
  1262. [MTI_FILENAMES].pubStruct))
  1263. DWORD dwStoreFileName(PWSTR pwstrFileName,
  1264. PARRAYREF parDest,
  1265. PGLOBL pglobl)
  1266. // goes into a permanent
  1267. // stack of filenames - to be deleted at return buffers
  1268. // time. Returns index in array where name has been
  1269. // stored.
  1270. // also saves filename into heap. So we can access the GPD file
  1271. // and check its timestamp whenever we load the BUD file.
  1272. {
  1273. DWORD dwNodeIndex, dwLen ;
  1274. if(!BallocElementFromMasterTable(MTI_FILENAMES, &dwNodeIndex, pglobl))
  1275. return(INVALID_INDEX) ;
  1276. dwLen = wcslen(pwstrFileName) + 1 ; // need room for terminating null.
  1277. mpFileNamesArray[dwNodeIndex] = MemAlloc(dwLen * 2) ;
  1278. if(!mpFileNamesArray[dwNodeIndex])
  1279. {
  1280. ERR(("Fatal: unable to alloc requested memory: %d bytes.\n",
  1281. dwLen * 2));
  1282. geErrorType = ERRTY_MEMORY_ALLOCATION ;
  1283. geErrorSev = ERRSEV_FATAL ;
  1284. return(INVALID_INDEX) ;
  1285. }
  1286. // wcscpy(mpFileNamesArray[dwNodeIndex], pwstrFileName) ;
  1287. StringCchCopyW(mpFileNamesArray[dwNodeIndex], dwLen, pwstrFileName) ;
  1288. parDest->dwCount = (dwLen - 1) * 2 ; // doesn't include the NUL term.
  1289. if(!BwriteToHeap(&parDest->loOffset, (PBYTE)pwstrFileName, dwLen * 2, 2, pglobl) ) // includes Null termination
  1290. return(INVALID_INDEX) ;
  1291. return(dwNodeIndex) ;
  1292. }
  1293. VOID vFreeFileNames(
  1294. PGLOBL pglobl )
  1295. {
  1296. // free all buffers holding the filenames.
  1297. while(mCurFileName)
  1298. {
  1299. mCurFileName-- ; // pop stack
  1300. MemFree(mpFileNamesArray[mCurFileName]) ;
  1301. }
  1302. }
  1303. VOID vIdentifySource(
  1304. PTKMAP ptkmap,
  1305. PGLOBL pglobl )
  1306. {
  1307. PWSTR pwstrFileName ;
  1308. if(ptkmap->dwKeywordID == ID_EOF)
  1309. {
  1310. ERR(("\nEnd of File reached.\n")) ;
  1311. return;
  1312. }
  1313. pwstrFileName = mpFileNamesArray[ptkmap->dwFileNameIndex] ;
  1314. if(pwstrFileName)
  1315. #if defined(DEVSTUDIO) // Emit compiler-style line messages
  1316. ERR(("\n%S(%d): ", pwstrFileName, ptkmap->dwLineNumber)) ;
  1317. #else
  1318. ERR(("\n%S: line: %d ...\n", pwstrFileName, ptkmap->dwLineNumber)) ;
  1319. #endif
  1320. }
  1321. #undef mCurFileName
  1322. #undef mpFileNamesArray