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.

735 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Forms
  4. // Copyright (C) Microsoft Corporation, 1994-1997
  5. //
  6. // File: ascparse.cxx
  7. //
  8. // Contents: Tool to build .hsc files from .asc files.
  9. //
  10. // Does the work of precomputing hash tables for associative
  11. // arrays of strings.
  12. //
  13. //----------------------------------------------------------------------------
  14. #define INCMSG(x)
  15. #include "headers.hxx"
  16. #ifndef X_LIMITS_H_
  17. #define X_LIMITS_H_
  18. #include <limits.h>
  19. #endif
  20. #ifndef X_PLATFORM_H_
  21. #define X_PLATFORM_H_
  22. #include <platform.h>
  23. #endif
  24. #ifndef X_MSHTMDBG_H_
  25. #define X_MSHTMDBG_H_
  26. #undef PERFMETER
  27. #include <mshtmdbg.h>
  28. #endif
  29. #define ASCPARSE
  30. // The following macro definitions allow us to use assoc.cxx
  31. // without bringing in the whole CORE directory
  32. #ifndef X_TCHAR_H_
  33. #define X_TCHAR_H_
  34. #include "tchar.h"
  35. #endif
  36. #define THR(x) (x)
  37. #define RRETURN(x) return(x)
  38. #define _MemAlloc(cb) malloc(cb)
  39. #define _MemAllocClear(cb) calloc(1,cb)
  40. #define _MemFree(x) free(x)
  41. #define MemAlloc(mt,cb) _MemAlloc(cb)
  42. #define MemAllocClear(mt,cb) _MemAllocClear(cb)
  43. #define MemFree(x) _MemFree(x)
  44. #define MemRealloc(mt, ppv, cb) _MemRealloc(ppv, cb)
  45. #define _tcsequal(x,y) (!_tcscmp(x,y))
  46. #define Assert(x) if (!(x)) { fprintf(stderr, "%s", #x); exit(1); }
  47. #define Verify(x) if (!(x)) { fprintf(stderr, "%s", #x); exit(1); }
  48. #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
  49. HRESULT
  50. _MemRealloc(void **ppv, size_t cb)
  51. {
  52. void *pv;
  53. if (*ppv == NULL)
  54. {
  55. *ppv = _MemAlloc(cb);
  56. if (*ppv == NULL)
  57. return E_OUTOFMEMORY;
  58. }
  59. else
  60. {
  61. pv = realloc(*ppv, cb);
  62. if (pv == NULL)
  63. return E_OUTOFMEMORY;
  64. *ppv = pv;
  65. }
  66. return S_OK;
  67. };
  68. void GetSuffix(LPCSTR pAssocString, LPSTR pSuffix, int nNumber)
  69. {
  70. pSuffix[0] = '\0'; // NULL terminate the suffix
  71. // check if the First Character is a Captial letter.
  72. if ( islower(pAssocString[0]) )
  73. return;
  74. _itoa(nNumber, pSuffix, 10);
  75. }
  76. #include "assoc.cxx"
  77. // end of stubs
  78. #define MAX_WORD 64
  79. #define MAX_LINE 4096
  80. class CAscParser
  81. {
  82. public:
  83. CAscParser() { memset(this, 0, sizeof(*this)); }
  84. class CAscEntry {
  85. public:
  86. CAscEntry() { memset(this, 0, sizeof(*this)); }
  87. CAscEntry *_pEntryNext;
  88. char _achString[MAX_WORD];
  89. int _number;
  90. char _achNumber[MAX_WORD];
  91. char _achStringName[MAX_WORD];
  92. char _achAssoc[MAX_WORD];
  93. char _achEnum[MAX_WORD];
  94. BOOL _fNoassoc;
  95. BOOL _fNostring;
  96. BOOL _fNoenum;
  97. const CAssoc *_pAssoc;
  98. };
  99. HRESULT ProcessAscFile(char *pchInputFile, char *pchOutputFile);
  100. char _achAssocArray[MAX_WORD];
  101. char _achAssocPrefix[MAX_WORD];
  102. char _achEnumType[MAX_WORD];
  103. char _achEnumPrefix[MAX_WORD];
  104. char _achStringNamePrefix[MAX_WORD];
  105. BOOL _fInsensitive;
  106. BOOL _fReversible;
  107. CAscEntry *_pEntryFirst;
  108. CAscEntry *_pEntryLast;
  109. };
  110. static BOOL ReadLine(FILE *fp, char *pchBuf, int cchBuf, int *pcchRead);
  111. static void SkipSpace(char **ppch);
  112. static void SkipNonspace(char **ppch);
  113. static void ChopComment(char *pch);
  114. static void GetWord(char **ppch, char **ppchWord);
  115. int __cdecl
  116. main ( int argc, char *argv[] )
  117. {
  118. HRESULT hr = E_FAIL;
  119. CAscParser np;
  120. if (argc != 3)
  121. goto Cleanup;
  122. hr = np.ProcessAscFile(argv[1], argv[2]);
  123. Cleanup:
  124. if (hr)
  125. printf ( "Error %lx building ASC file\n", hr);
  126. exit(hr);
  127. }
  128. HRESULT
  129. CAscParser::ProcessAscFile(char *pchInputFile, char *pchOutputFile)
  130. {
  131. HRESULT hr;
  132. FILE *fpInput = NULL;
  133. FILE *fpOutput = NULL;
  134. char achBuf[MAX_LINE];
  135. char *pch;
  136. char *pchWord;
  137. CAscEntry *pEntryNew;
  138. CAscEntry *pEntry;
  139. CAssocArray nt;
  140. nt.Init();
  141. _fReversible = FALSE;
  142. // open input file
  143. fpInput = fopen(pchInputFile, "r");
  144. if (!fpInput)
  145. {
  146. hr = E_FAIL;
  147. goto Cleanup;
  148. }
  149. // open output file
  150. fpOutput = fopen(pchOutputFile, "w");
  151. if (!fpOutput)
  152. {
  153. hr = E_FAIL;
  154. goto Cleanup;
  155. }
  156. // phase 1: read the header section
  157. hr = E_FAIL;
  158. for (;;)
  159. {
  160. if (!ReadLine(fpInput, achBuf, MAX_LINE, NULL))
  161. goto Cleanup;
  162. pch = achBuf;
  163. ChopComment(pch);
  164. GetWord(&pch, &pchWord);
  165. if (!*pchWord)
  166. continue;
  167. if (!strcmp(pchWord, "assocarray"))
  168. {
  169. GetWord(&pch, &pchWord);
  170. strcpy(_achAssocArray, pchWord);
  171. GetWord(&pch, &pchWord);
  172. strcpy(_achAssocPrefix, pchWord);
  173. }
  174. else
  175. if (!strcmp(pchWord, "enum"))
  176. {
  177. GetWord(&pch, &pchWord);
  178. strcpy(_achEnumType, pchWord);
  179. GetWord(&pch, &pchWord);
  180. strcpy(_achEnumPrefix, pchWord);
  181. }
  182. else
  183. if (!strcmp(pchWord, "string"))
  184. {
  185. GetWord(&pch, &pchWord);
  186. strcpy(_achStringNamePrefix, pchWord);
  187. }
  188. else
  189. if (!strcmp(pchWord, "case-insensitive"))
  190. {
  191. _fInsensitive = TRUE;
  192. }
  193. else
  194. if (!strcmp(pchWord, "case-sensitive"))
  195. {
  196. _fInsensitive = FALSE;
  197. }
  198. else
  199. if (!strcmp(pchWord, "reversible"))
  200. {
  201. _fReversible = TRUE;
  202. }
  203. else
  204. if (!strcmp(pchWord, "start"))
  205. break;
  206. }
  207. // phase 2: read the assoc table section
  208. hr = S_OK;
  209. while (ReadLine(fpInput, achBuf, MAX_LINE, NULL))
  210. {
  211. pch = achBuf;
  212. ChopComment(pch);
  213. GetWord(&pch, &pchWord);
  214. if (!*pchWord)
  215. continue;
  216. // allocate
  217. pEntryNew = new CAscEntry;
  218. if (!pEntryNew)
  219. return E_OUTOFMEMORY;
  220. // link up
  221. if (!_pEntryLast)
  222. {
  223. pEntryNew->_number = 0;
  224. _pEntryLast = _pEntryFirst = pEntryNew;
  225. }
  226. else
  227. {
  228. pEntryNew->_number = _pEntryLast->_number+1;
  229. _pEntryLast->_pEntryNext = pEntryNew;
  230. _pEntryLast = pEntryNew;
  231. }
  232. // fill in assoc
  233. strcpy(pEntryNew->_achString, pchWord);
  234. // fill in other fields
  235. for (;;)
  236. {
  237. GetWord(&pch, &pchWord);
  238. if (!*pchWord)
  239. break;
  240. if (!strcmp(pchWord, "number"))
  241. {
  242. GetWord(&pch, &pchWord);
  243. if (*pchWord == '=')
  244. {
  245. for (pEntry = _pEntryFirst; pEntry; pEntry = pEntry->_pEntryNext)
  246. {
  247. if (!strcmp(pchWord+1, pEntry->_achString))
  248. {
  249. break;
  250. }
  251. }
  252. if (!pEntry)
  253. {
  254. hr = E_FAIL;
  255. goto Cleanup;
  256. }
  257. pEntryNew->_number = pEntry->_number;
  258. strcpy(pEntryNew->_achNumber, pEntry->_achNumber);
  259. }
  260. else if (*pchWord >= '0' && *pchWord <= '9' || *pchWord == '-')
  261. {
  262. pEntryNew->_number = atol(pchWord);
  263. *pEntryNew->_achNumber = '\0';
  264. }
  265. else
  266. {
  267. pEntryNew->_number = 0;
  268. strcpy(pEntryNew->_achNumber, pchWord);
  269. }
  270. }
  271. else
  272. if (!strcmp(pchWord, "string"))
  273. {
  274. GetWord(&pch, &pchWord);
  275. strcpy(pEntryNew->_achStringName, pchWord);
  276. }
  277. else
  278. if (!strcmp(pchWord, "enum"))
  279. {
  280. GetWord(&pch, &pchWord);
  281. strcpy(pEntryNew->_achEnum, pchWord);
  282. }
  283. else
  284. if (!strcmp(pchWord, "assoc"))
  285. {
  286. GetWord(&pch, &pchWord);
  287. strcpy(pEntryNew->_achAssoc, pchWord);
  288. }
  289. else
  290. if (!strcmp(pchWord, "noassoc"))
  291. {
  292. pEntryNew->_fNoassoc = TRUE;
  293. }
  294. else
  295. if (!strcmp(pchWord, "nostring"))
  296. {
  297. pEntryNew->_fNostring = TRUE;
  298. }
  299. else
  300. if (!strcmp(pchWord, "noenum"))
  301. {
  302. pEntryNew->_fNoenum = TRUE;
  303. }
  304. }
  305. }
  306. // compute assocs
  307. for (pEntry = _pEntryFirst; pEntry; pEntry = pEntry->_pEntryNext)
  308. {
  309. if (!pEntry->_fNoassoc)
  310. {
  311. WCHAR awch[MAX_WORD];
  312. WCHAR *pwch = awch;
  313. char *pch = pEntry->_achString;
  314. DWORD len;
  315. DWORD hash;
  316. const CAssoc *passoc;
  317. do { *pwch++ = *pch; } while (*pch++);
  318. len = _tcslen(awch);
  319. if (_fInsensitive)
  320. hash = HashStringCi(awch, len, 0);
  321. else
  322. hash = HashString(awch, len, 0);
  323. passoc = nt.AddAssoc((DWORD_PTR)pEntry, awch, len, hash);
  324. if (!passoc)
  325. {
  326. hr = E_FAIL;
  327. goto Cleanup;
  328. }
  329. pEntry->_pAssoc = passoc;
  330. }
  331. }
  332. // phase 3: output header decls enums
  333. fprintf(fpOutput, "// %s\n", pchOutputFile);
  334. fprintf(fpOutput, "// Generated by ascparse.exe from %s\n", pchInputFile);
  335. fprintf(fpOutput, "// Do not modify by hand!\n");
  336. fprintf(fpOutput, "\n#ifndef _cxx_\n\n");
  337. // assocarray and hash
  338. fprintf(fpOutput, "class CAssoc;\n");
  339. fprintf(fpOutput, "class CAssocArray;\n\n");
  340. fprintf(fpOutput, "extern const CAssoc * const %s_HashTable[%d];\n", _achAssocArray, nt._mHash);
  341. if (_fReversible)
  342. {
  343. fprintf(fpOutput, "extern const CAssoc * const %s_RevSearch[];\n", _achAssocArray);
  344. }
  345. fprintf(fpOutput, "extern const CAssocArray %s;\n\n", _achAssocArray);
  346. // enums
  347. if (*_achEnumType)
  348. {
  349. fprintf(fpOutput, "enum %s\n{\n", _achEnumType);
  350. for (pEntry = _pEntryFirst; pEntry; pEntry = pEntry->_pEntryNext)
  351. {
  352. if (!pEntry->_fNoenum)
  353. {
  354. if (*pEntry->_achEnum)
  355. {
  356. fprintf(fpOutput, " %s = %d,\n", pEntry->_achEnum, pEntry->_number);
  357. }
  358. else
  359. {
  360. fprintf(fpOutput, " %s%s = %d,\n", _achEnumPrefix, pEntry->_achString, pEntry->_number);
  361. }
  362. }
  363. }
  364. fprintf(fpOutput, " %s_FORCE_LONG = LONG_MAX\n", _achEnumType);
  365. fprintf(fpOutput, "};\n\n");
  366. }
  367. // assocs
  368. for (pEntry = _pEntryFirst; pEntry; pEntry = pEntry->_pEntryNext)
  369. {
  370. if (!pEntry->_fNoassoc)
  371. {
  372. if (!*pEntry->_achAssoc)
  373. {
  374. char suffix[32];
  375. GetSuffix(pEntry->_achString, suffix, pEntry->_number);
  376. fprintf(fpOutput, "extern const CAssoc %s%s%s;\n",
  377. _achAssocPrefix, pEntry->_achString, suffix);
  378. }
  379. else
  380. {
  381. fprintf(fpOutput, "extern const CAssoc %s;\n",
  382. pEntry->_achAssoc);
  383. }
  384. }
  385. }
  386. fprintf(fpOutput, "\n\n");
  387. // strings
  388. for (pEntry = _pEntryFirst; pEntry; pEntry = pEntry->_pEntryNext)
  389. {
  390. if (!pEntry->_fNostring)
  391. {
  392. if (!pEntry->_fNoassoc && (*_achStringNamePrefix || *pEntry->_achStringName))
  393. {
  394. if (*pEntry->_achStringName)
  395. {
  396. fprintf(fpOutput, "#define %s ",
  397. pEntry->_achStringName);
  398. }
  399. else
  400. {
  401. fprintf(fpOutput, "#define %s%s ",
  402. _achStringNamePrefix, pEntry->_achString);
  403. }
  404. if (!*pEntry->_achAssoc)
  405. {
  406. char suffix[32];
  407. GetSuffix(pEntry->_achString, suffix, pEntry->_number);
  408. fprintf(fpOutput, "(%s%s%s._ach)\n",
  409. _achAssocPrefix, pEntry->_achString, suffix);
  410. }
  411. else
  412. {
  413. fprintf(fpOutput, "(%s._ach)\n",
  414. pEntry->_achAssoc);
  415. }
  416. }
  417. else
  418. {
  419. if (*pEntry->_achStringName)
  420. {
  421. fprintf(fpOutput, "#define %s (_T(\"%s\"))\n",
  422. pEntry->_achStringName, pEntry->_achString);
  423. }
  424. else if (*_achStringNamePrefix)
  425. {
  426. fprintf(fpOutput, "#define *%s%s (_T(\"%s\"))\n",
  427. _achStringNamePrefix, pEntry->_achString, pEntry->_achString);
  428. }
  429. }
  430. }
  431. }
  432. // end of header section; start of cxx section
  433. fprintf(fpOutput, "\n#else _cxx_\n\n");
  434. fprintf(fpOutput, "\n#undef _cxx_\n\n");
  435. // phase 4: output assocs
  436. for (pEntry = _pEntryFirst; pEntry; pEntry = pEntry->_pEntryNext)
  437. {
  438. if (!pEntry->_fNoassoc)
  439. {
  440. if (!*pEntry->_achAssoc)
  441. {
  442. char suffix[32];
  443. GetSuffix(pEntry->_achString, suffix, pEntry->_number);
  444. fprintf(fpOutput, "const CAssoc %s%s%s\t\t\t= ",
  445. _achAssocPrefix, pEntry->_achString, suffix);
  446. }
  447. else
  448. {
  449. fprintf(fpOutput, "const CAssoc %s = ",
  450. pEntry->_achAssoc);
  451. }
  452. if (*pEntry->_achNumber)
  453. {
  454. fprintf(fpOutput, "{ %12s, 0x%08x, _T(\"%s\") };\n",
  455. pEntry->_achNumber, pEntry->_pAssoc->_hash, pEntry->_achString);
  456. }
  457. else
  458. {
  459. fprintf(fpOutput, "{ %5d, 0x%08x, _T(\"%s\") };\n",
  460. pEntry->_number, pEntry->_pAssoc->_hash, pEntry->_achString);
  461. }
  462. }
  463. }
  464. // phase 5: output table
  465. // output hash table
  466. fprintf(fpOutput, "\n\nconst CAssoc * const %s_HashTable[%d] =\n{\n", _achAssocArray, nt._mHash);
  467. {
  468. int i;
  469. int c;
  470. int s;
  471. int d;
  472. const CAssoc * const *ppAssoc;
  473. for (ppAssoc = nt._pHashTable, c=nt._mHash; c; ppAssoc++, c--)
  474. {
  475. if (!*ppAssoc)
  476. {
  477. fprintf(fpOutput, " NULL,\n");
  478. }
  479. else
  480. {
  481. i = (*ppAssoc)->Hash() % nt._mHash;
  482. s = ((*ppAssoc)->Hash() & nt._sHash) + 1;
  483. d = 0;
  484. while (nt._pHashTable + i != ppAssoc)
  485. {
  486. if (i < s)
  487. i += nt._mHash;
  488. i -= s;
  489. d++;
  490. }
  491. fprintf(fpOutput, "/*%2d */ ",d);
  492. pEntry = (CAscEntry*)(*ppAssoc)->Number();
  493. if (!*pEntry->_achAssoc)
  494. {
  495. char suffix[32];
  496. GetSuffix(pEntry->_achString, suffix, pEntry->_number);
  497. fprintf(fpOutput, "&%s%s%s,\n",
  498. _achAssocPrefix, pEntry->_achString, suffix);
  499. }
  500. else
  501. {
  502. char suffix[32];
  503. GetSuffix(pEntry->_achAssoc, suffix, pEntry->_number);
  504. fprintf(fpOutput, "&%s%s,\n",
  505. pEntry->_achAssoc, suffix);
  506. }
  507. }
  508. }
  509. }
  510. fprintf(fpOutput, "};\n\n");
  511. // phase 6: output table for reverse search (if requested)
  512. if (_fReversible)
  513. {
  514. CAscParser::CAscEntry * pFound;
  515. CAscParser::CAscEntry * pEntry;
  516. int nCurrMin;
  517. int nPrevMin;
  518. int nCurrVal;
  519. fprintf(fpOutput, "const CAssoc * const %s_RevSearch[] =\n{\n", _achAssocArray);
  520. // find and print the entries in order from numeric min to max
  521. nPrevMin = 0;
  522. for(;;)
  523. {
  524. // find the next entry
  525. nCurrMin = INT_MAX;
  526. pFound = NULL;
  527. for (pEntry = _pEntryFirst; pEntry; pEntry = pEntry->_pEntryNext)
  528. {
  529. if (*pEntry->_achNumber)
  530. {
  531. nCurrVal = atol(pEntry->_achNumber);
  532. }
  533. else
  534. {
  535. nCurrVal = pEntry->_number;
  536. }
  537. if (nCurrVal > nPrevMin && nCurrVal < nCurrMin)
  538. {
  539. nCurrMin = nCurrVal;
  540. pFound = pEntry;
  541. }
  542. }
  543. // break out once we've done everything
  544. if (pFound == NULL)
  545. {
  546. break;
  547. }
  548. // output a pointer to the assoc
  549. if (!*pFound->_achAssoc)
  550. {
  551. char suffix[32];
  552. GetSuffix(pFound->_achString, suffix, pFound->_number);
  553. fprintf(fpOutput, "\t&%s%s%s,\n",
  554. _achAssocPrefix, pFound->_achString, suffix);
  555. }
  556. else
  557. {
  558. fprintf(fpOutput, "\t%s,\n", pFound->_achAssoc);
  559. }
  560. nPrevMin = nCurrMin;
  561. }
  562. fprintf(fpOutput, "};\n\n");
  563. }
  564. // output assoc table struct itself
  565. fprintf(fpOutput, "const CAssocArray %s = {\n", _achAssocArray);
  566. fprintf(fpOutput, " %s_HashTable,\n", _achAssocArray);
  567. fprintf(fpOutput, " %d,\n", nt._cHash);
  568. fprintf(fpOutput, " %d,\n", nt._mHash);
  569. fprintf(fpOutput, " %d,\n", nt._sHash);
  570. fprintf(fpOutput, " %d,\n", nt._cHash);
  571. fprintf(fpOutput, " %d,\n", nt._iSize);
  572. fprintf(fpOutput, " TRUE,\n");
  573. fprintf(fpOutput, "};\n\n");
  574. fprintf(fpOutput, "\n#endif _cxx_\n\n");
  575. Cleanup:
  576. nt.Deinit();
  577. if (fpInput)
  578. fclose(fpInput);
  579. if (fpOutput)
  580. fclose(fpOutput);
  581. return hr;
  582. }
  583. static
  584. BOOL
  585. ReadLine(FILE *fp, char *pchBuf, int cchBuf, int *pcchRead)
  586. {
  587. int cchRead;
  588. if (!fgets(pchBuf, cchBuf, fp))
  589. return FALSE;
  590. cchRead = strlen(pchBuf);
  591. if (!cchRead)
  592. return FALSE;
  593. if (pcchRead)
  594. *pcchRead = cchRead;
  595. return TRUE;
  596. }
  597. static
  598. void
  599. SkipSpace(char **ppch)
  600. {
  601. char *pch = *ppch;
  602. while (*pch && (*pch == ' ' || *pch == '\t' || *pch == '\r' || *pch == '\n'))
  603. pch++;
  604. *ppch = pch;
  605. }
  606. static
  607. void
  608. SkipNonspace(char **ppch)
  609. {
  610. char *pch = *ppch;
  611. while (*pch && (*pch != ' ' && *pch != '\t' && *pch != '\r' && *pch != '\n'))
  612. pch++;
  613. *ppch = pch;
  614. }
  615. static
  616. void
  617. ChopComment(char *pch)
  618. {
  619. while (*pch)
  620. {
  621. if (*pch == '/' && *(pch+1) == '/')
  622. {
  623. *pch = '\0';
  624. return;
  625. }
  626. pch++;
  627. }
  628. }
  629. static
  630. void
  631. GetWord(char **ppch, char **ppchWord)
  632. {
  633. SkipSpace(ppch);
  634. *ppchWord = *ppch;
  635. SkipNonspace(ppch);
  636. if (**ppch)
  637. {
  638. **ppch = '\0';
  639. if (*ppch - *ppchWord > MAX_WORD)
  640. *(*ppchWord + MAX_WORD-1) = '\0';
  641. (*ppch)++;
  642. }
  643. }