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.

782 lines
17 KiB

  1. //
  2. //
  3. // mbRWBSC.C - Write .BSC Source Data Base file from various lists.
  4. //
  5. //
  6. #define LINT_ARGS
  7. #include <stdlib.h>
  8. #include <search.h>
  9. #include <ctype.h>
  10. #include "sbrfdef.h"
  11. #include "mbrmake.h"
  12. #include "sbrbsc.h"
  13. #include "mbrcache.h"
  14. // prototypes
  15. //
  16. static void pascal WriteBSCHeader (void);
  17. static void pascal WriteAtoms (void);
  18. static void pascal WriteMods (void);
  19. static void pascal WriteModSyms (void);
  20. static void pascal WriteSyms (void);
  21. static void pascal WriteProps (void);
  22. static void pascal WriteRefs (void);
  23. static void pascal WriteDefs (void);
  24. static void pascal WriteCals (void);
  25. static void pascal WriteCbys (void);
  26. static void pascal WriteSbrInfo (void);
  27. static void pascal IndexTree (void);
  28. static void pascal BSCWrite (LPV lpv, WORD cch);
  29. static void pascal BSCWriteLsz (LSZ lsz);
  30. //
  31. #define BSCOut(v) BSCWrite(&(v), sizeof(v))
  32. static WORD CntAtomPage; // count of Atom pages
  33. static WORD AtomCnt = 0;
  34. static WORD unknownModName; // UNKNOWN module idx
  35. static WORD ModSymCnt = 0; // count of modsyms
  36. static WORD SymCnt = 0; // count of symbols
  37. static WORD PropCnt = 0; // count of props
  38. static DWORD RefCnt = 0; // count of refs
  39. static WORD DefCnt = 0; // count of defs
  40. static WORD CbyCnt = 0; // count of use half of above
  41. static WORD CalCnt = 0; // count of used by half of above
  42. static DWORD lbModList; // offset to Module list
  43. static DWORD lbModSymList; // offset to ModSym list
  44. static DWORD lbSymList; // offset to Symbol list
  45. static DWORD lbPropList; // offset to Property list
  46. static DWORD lbRefList; // offset to Reference list
  47. static DWORD lbDefList; // offset to Definition list
  48. static DWORD lbCalList; // offset to Call/used list
  49. static DWORD lbCbyList; // offset to Call/used list
  50. static DWORD lbAtomCache; // offset to Sym Atom cache
  51. static DWORD lbSbrList; // offset to Sbr file names
  52. extern char far *GetAtomCache (WORD);
  53. void
  54. WriteBSC (char *OutputFileName)
  55. // Write .BSC Source Data Base
  56. //
  57. {
  58. OutFile = fopen(OutputFileName, "wb");
  59. if (OutFile == NULL) {
  60. Error(ERR_OPEN_FAILED, OutputFileName);
  61. }
  62. //
  63. // no backing out from here -- if we fail we must delete the database
  64. //
  65. fOutputBroken = TRUE;
  66. WriteBSCHeader(); // save space for header
  67. WriteAtoms(); // sort and write atom cache
  68. IndexTree(); // xlate pointers to indices
  69. BldModSymList(); // Build module symbol list
  70. SetVMClient(VM_EMIT_TREE);
  71. unknownModName = gSYM(vaUnknownSym).isym; // record UNKNOWN index
  72. WriteMods(); // output modules
  73. WriteModSyms(); // output module symbol lists
  74. WriteSyms(); // output all symbols
  75. WriteProps(); // output all prop headers
  76. WriteRefs(); // output all refs
  77. WriteDefs(); // output all defs
  78. WriteCals(); // output all uses/calls
  79. WriteCbys(); // output all UBY/CBY
  80. WriteSbrInfo(); // output the SBR file names
  81. if (fseek(OutFile, 0L, SEEK_SET)) // Beginning of file
  82. SeekError (OutputFileName);
  83. WriteBSCHeader (); // output .BSC header
  84. fclose(OutFile);
  85. //
  86. // we're all done --- it's a keeper!
  87. //
  88. fOutputBroken = FALSE;
  89. SetVMClient(VM_MISC);
  90. if (OptV) {
  91. printf ("%u\tModules\n", ModCnt);
  92. printf ("%u\tSymbols\n", SymCnt);
  93. printf ("%u\tDefinitions\n", DefCnt);
  94. printf ("%u\tReferences\n", RefCnt);
  95. printf ("%u\tCalls/Uses\n", CalCnt);
  96. printf ("%u\tCalled by/Used by\n", CbyCnt);
  97. #ifdef DEBUG
  98. printf ("\n");
  99. printf ("%u\tTotal ModSyms\n", ModSymCnt);
  100. printf ("%u\tTotal Properties\n", PropCnt);
  101. printf ("%u\tLast Atom page \n", AtomCnt);
  102. printf ("\n");
  103. printf ("%lu\tBase of AtomCache\n", lbAtomCache);
  104. printf ("%lu\tBase of ModList\n", lbModList);
  105. printf ("%lu\tBase of ModSymList\n", lbModSymList);
  106. printf ("%lu\tBase of SymList\n", lbSymList);
  107. printf ("%lu\tBase of PropList\n", lbPropList);
  108. printf ("%lu\tBase of RefList\n", lbRefList);
  109. printf ("%lu\tBase of DefList\n", lbDefList);
  110. printf ("%lu\tBase of CalList\n", lbCalList);
  111. printf ("%lu\tBase of CbyList\n", lbCbyList);
  112. #endif
  113. }
  114. }
  115. static void pascal
  116. WriteBSCHeader ()
  117. // Write .BSC header, counts, and table offsets.
  118. //
  119. {
  120. BYTE ver; // version num
  121. // output BSC version (major and minor)
  122. ver = BSC_MAJ;
  123. BSCOut(ver); // major ver
  124. ver = BSC_MIN;
  125. BSCOut(ver); // minor ver
  126. ver = BSC_UPD;
  127. BSCOut(ver); // update ver
  128. BSCOut(fCase); // case sensitive
  129. BSCOut(MaxSymLen); // biggest symbol allowed
  130. BSCOut(unknownModName); // UNKNOWN idx
  131. // output counts (sizes) of each data area
  132. BSCOut(ModCnt);
  133. BSCOut(ModSymCnt);
  134. BSCOut(SymCnt);
  135. BSCOut(PropCnt);
  136. BSCOut(RefCnt);
  137. BSCOut(DefCnt);
  138. BSCOut(CalCnt);
  139. BSCOut(CbyCnt);
  140. // last page #
  141. BSCOut(CntAtomPage);
  142. // last page size
  143. BSCOut(AtomCnt);
  144. // output BSC data area offsets
  145. BSCOut(lbModList);
  146. BSCOut(lbModSymList);
  147. BSCOut(lbSymList);
  148. BSCOut(lbPropList);
  149. BSCOut(lbRefList);
  150. BSCOut(lbDefList);
  151. BSCOut(lbCalList);
  152. BSCOut(lbCbyList);
  153. BSCOut(lbAtomCache);
  154. BSCOut(lbSbrList);
  155. }
  156. static void pascal
  157. WriteAtoms ()
  158. // Write a sorted version of the symbol Atom Cache to the .BSC file by walking
  159. // the sorted symbol subscript array
  160. //
  161. {
  162. WORD i;
  163. int Atomlen;
  164. LPCH lpchAtoms;
  165. LSZ lszAtom;
  166. VA vaSym;
  167. SetVMClient(VM_EMIT_ATOMS);
  168. lpchAtoms = LpvAllocCb(ATOMALLOC);
  169. lbAtomCache = ftell(OutFile); // offset to text of symbols
  170. for (i=0; i < cAtomsMac; i++) {
  171. vaSym = rgvaSymSorted[i];
  172. if (vaSym == vaNil) continue;
  173. gSYM(vaSym);
  174. lszAtom = gTEXT(cSYM.vaNameText);
  175. Atomlen = strlen(lszAtom);
  176. // write Atom page if not enough room
  177. //
  178. if (Atomlen + AtomCnt + 1 > ATOMALLOC) {
  179. if (AtomCnt < ATOMALLOC)
  180. memset(lpchAtoms + AtomCnt, 0, ATOMALLOC - AtomCnt);
  181. if ((fwrite (lpchAtoms, ATOMALLOC, 1, OutFile)) != 1)
  182. WriteError (OutputFileName);
  183. CntAtomPage++;
  184. AtomCnt = 0;
  185. }
  186. strcpy(lpchAtoms + AtomCnt, lszAtom); // copy Atom
  187. cSYM.vaNameText = (PVOID)(((long)CntAtomPage << 16) | (AtomCnt));
  188. pSYM(vaSym);
  189. AtomCnt += Atomlen + 1;
  190. // force to even value
  191. if (AtomCnt & 1) lpchAtoms[AtomCnt++] = 0;
  192. }
  193. // write last Atom page
  194. //
  195. if (AtomCnt)
  196. if ((fwrite (lpchAtoms, AtomCnt, 1, OutFile)) != 1)
  197. WriteError (OutputFileName);
  198. // free all the memory for the atom cache, we no longer need it
  199. fflush (OutFile);
  200. FreeLpv(lpchAtoms);
  201. SetVMClient(VM_MISC);
  202. }
  203. static void pascal
  204. WriteMods()
  205. // write out the list of modules
  206. //
  207. // compute the MODSYM indices as we do this
  208. //
  209. {
  210. MODLIST bmod;
  211. VA vaMod;
  212. WORD i;
  213. ModSymCnt = 0;
  214. lbModList = ftell(OutFile); // offset to Module list
  215. for (i = cSymbolsMac; i < cAtomsMac; i++) {
  216. gSYM(rgvaSymSorted[i]);
  217. vaMod = cSYM.vaFirstProp; // points back to module, honest!
  218. gMOD(vaMod);
  219. bmod.ModName = gSYM(cMOD.vaNameSym).isym; // module name idx
  220. ModSymCnt += cMOD.csyms;
  221. bmod.mSymEnd = ModSymCnt; // last ModSym idx +1
  222. BSCOut(bmod);
  223. }
  224. }
  225. static void pascal
  226. WriteModSyms()
  227. // write out the list of modsyms
  228. //
  229. {
  230. MODSYMLIST bmodsym;
  231. VA vaMod, vaModSym;
  232. WORD i;
  233. lbModSymList = ftell(OutFile); // offset to ModSym list
  234. for (i = cSymbolsMac; i < cAtomsMac; i++) {
  235. gSYM(rgvaSymSorted[i]);
  236. vaMod = cSYM.vaFirstProp; // points back to module, honest!
  237. gMOD(vaMod);
  238. vaModSym = cMOD.vaFirstModSym;
  239. while (vaModSym) {
  240. gMODSYM(vaModSym);
  241. // Symbol Property idx
  242. bmodsym.ModSymProp = gPROP(cMODSYM.vaFirstProp).iprp;
  243. BSCOut(bmodsym);
  244. vaModSym = cMODSYM.vaNextModSym;
  245. }
  246. }
  247. }
  248. static void pascal
  249. WriteSyms()
  250. // write out the list of SYMs
  251. //
  252. {
  253. SYMLIST bsym;
  254. VA vaSym;
  255. WORD i;
  256. lbSymList = ftell(OutFile); // offset to Symbol list
  257. PropCnt = 0;
  258. for (i=0; i < cAtomsMac; i++) {
  259. vaSym = rgvaSymSorted[i];
  260. if (vaSym == vaNil) continue;
  261. gSYM(vaSym);
  262. PropCnt += cSYM.cprop;
  263. bsym.PropEnd = PropCnt; // last Prop idx +1
  264. bsym.Atom = (WORD)((long)cSYM.vaNameText & 0xffff); // Atom cache offset
  265. bsym.Page = (WORD)((long)cSYM.vaNameText >> 16); // Atom cache page
  266. BSCOut(bsym);
  267. }
  268. }
  269. static void pascal
  270. WriteProps ()
  271. // write out the list of PROPS to the database
  272. //
  273. // the number of definitions (DefCnt), references (RefCnt),
  274. // calls (CalCnt) and called-by (CbyCnt) items are computed at this time
  275. //
  276. // Each PROP is assigned numbers for its associated objects
  277. //
  278. {
  279. PROPLIST bprop;
  280. VA vaSym, vaProp;
  281. WORD i;
  282. lbPropList = ftell(OutFile); // offset to Property list
  283. DefCnt = 0;
  284. RefCnt = 0L;
  285. CalCnt = 0;
  286. CbyCnt = 0;
  287. for (i=0; i < cSymbolsMac; i++) {
  288. vaSym = rgvaSymSorted[i];
  289. if (vaSym == vaNil) continue;
  290. vaProp = gSYM(vaSym).vaFirstProp;
  291. while (vaProp) {
  292. gPROP(vaProp);
  293. gSYM(cPROP.vaNameSym);
  294. bprop.PropName = cSYM.isym; // Symbol idx
  295. bprop.PropAttr = cPROP.sattr; // Property Attribute
  296. DefCnt += CItemsList(cPROP.vaDefList);
  297. bprop.DefEnd = DefCnt; // last Definition idx +1
  298. RefCnt += cPROP.cref;
  299. bprop.RefEnd = RefCnt; // last Reference idx +1
  300. CalCnt += CItemsList(cPROP.vaCalList);
  301. bprop.CalEnd = CalCnt; // last Calls/uses idx +1
  302. CbyCnt += CItemsList(cPROP.vaCbyList);
  303. bprop.CbyEnd = CbyCnt; // last Called by/used by idx +1
  304. BSCOut(bprop);
  305. vaProp = cPROP.vaNextProp;
  306. }
  307. }
  308. }
  309. static void pascal
  310. WriteRefs()
  311. // write out the list of references
  312. //
  313. {
  314. REFLIST bref;
  315. VA vaSym, vaProp, vaRef;
  316. WORD i;
  317. lbRefList = ftell(OutFile); // offset to Reference list
  318. for (i=0; i < cSymbolsMac; i++) {
  319. vaSym = rgvaSymSorted[i];
  320. if (vaSym == vaNil) continue;
  321. vaProp = gSYM(vaSym).vaFirstProp;
  322. while (vaProp) {
  323. gPROP(vaProp);
  324. vaRef = VaFrVp(cPROP.vpFirstRef);
  325. while (vaRef) {
  326. gREF(vaRef);
  327. gSYM(VaFrVp(cREF.vpFileSym));
  328. bref.RefNam = cSYM.isym; // Symbol idx
  329. bref.RefLin = cREF.reflin; // Symbol lin
  330. bref.isbr = cREF.isbr; // owner
  331. BSCOut(bref);
  332. vaRef = VaFrVp(cREF.vpNextRef);
  333. }
  334. vaProp = cPROP.vaNextProp;
  335. }
  336. }
  337. }
  338. static void pascal
  339. WriteDefs()
  340. // write out the list of defintions
  341. //
  342. {
  343. REFLIST bdef;
  344. WORD i;
  345. VA vaProp, vaSym;
  346. lbDefList = ftell(OutFile); // offset to Definition list
  347. for (i=0; i < cSymbolsMac; i++) {
  348. vaSym = rgvaSymSorted[i];
  349. if (vaSym == vaNil) continue;
  350. vaProp = gSYM(vaSym).vaFirstProp;
  351. while (vaProp) {
  352. gPROP(vaProp);
  353. ENM_LIST (cPROP.vaDefList, DEF)
  354. gSYM(cDEF.vaFileSym);
  355. bdef.RefNam = cSYM.isym; // Symbol idx
  356. bdef.RefLin = cDEF.deflin; // Symbol lin
  357. bdef.isbr = cDEF.isbr; // owner
  358. BSCOut(bdef);
  359. ENM_END
  360. vaProp = cPROP.vaNextProp;
  361. }
  362. }
  363. }
  364. static void pascal
  365. WriteCals()
  366. // write out the list of uses (CALs) items
  367. //
  368. {
  369. USELIST buse;
  370. PROP prop;
  371. VA vaSym, vaProp;
  372. WORD i;
  373. lbCalList = ftell(OutFile); // offset to CAL list
  374. for (i=0; i < cSymbolsMac; i++) {
  375. vaSym = rgvaSymSorted[i];
  376. if (vaSym == vaNil) continue;
  377. vaProp = gSYM(vaSym).vaFirstProp;
  378. while (vaProp) {
  379. prop = gPROP(vaProp);
  380. ENM_LIST(prop.vaCalList, CAL)
  381. gPROP(cCAL.vaCalProp);
  382. buse.UseProp = cPROP.iprp; // property idx
  383. buse.UseCnt = (BYTE) cCAL.calcnt; // use count
  384. buse.isbr = cCAL.isbr; // owner
  385. BSCOut(buse);
  386. ENM_END
  387. vaProp = prop.vaNextProp;
  388. }
  389. }
  390. BSCOut(buse); // Pad
  391. }
  392. static void pascal
  393. WriteCbys()
  394. // write out the list of used-by (CBY) items
  395. //
  396. {
  397. USELIST buse;
  398. PROP prop;
  399. VA vaSym, vaProp;
  400. WORD i;
  401. lbCbyList = ftell(OutFile); // offset to CBY list
  402. for (i=0; i < cSymbolsMac; i++) {
  403. vaSym = rgvaSymSorted[i];
  404. if (vaSym == vaNil) continue;
  405. vaProp = gSYM(vaSym).vaFirstProp;
  406. while (vaProp) {
  407. prop = gPROP(vaProp);
  408. ENM_LIST(prop.vaCbyList, CBY)
  409. gPROP(cCBY.vaCbyProp);
  410. buse.UseProp = cPROP.iprp; // property idx
  411. buse.UseCnt = (BYTE) cCBY.cbycnt; // use count
  412. buse.isbr = cCBY.isbr; // owner
  413. BSCOut(buse);
  414. ENM_END
  415. vaProp = prop.vaNextProp;
  416. }
  417. }
  418. BSCOut(buse); // Pad
  419. }
  420. static void pascal
  421. WriteSbrInfo()
  422. // write out the names of the .sbr files in the correct order
  423. //
  424. {
  425. VA vaSbr;
  426. WORD isbr;
  427. VA *rgVaSbr;
  428. lbSbrList = ftell(OutFile);
  429. rgVaSbr = (VA *)LpvAllocCb(SbrCnt * (WORD)sizeof(VA));
  430. for (isbr = 0; isbr < SbrCnt; isbr++)
  431. rgVaSbr[isbr] = vaNil;
  432. vaSbr = vaRootSbr;
  433. while (vaSbr) {
  434. gSBR(vaSbr);
  435. if (cSBR.isbr != -1)
  436. rgVaSbr[cSBR.isbr] = vaSbr;
  437. vaSbr = cSBR.vaNextSbr;
  438. }
  439. for (isbr = 0; isbr < SbrCnt; isbr++) {
  440. if (rgVaSbr[isbr] != vaNil) {
  441. gSBR(rgVaSbr[isbr]);
  442. BSCWriteLsz(cSBR.szName);
  443. }
  444. }
  445. BSCWriteLsz("");
  446. }
  447. static void pascal
  448. IndexTree ()
  449. // Walk all the list of all symbols and index each prop as we find it
  450. // at this point we also count the total number of defs + refs to
  451. // make sure that we can actually create this database
  452. //
  453. {
  454. VA vaSym, vaProp;
  455. DWORD cdefs = 0;
  456. DWORD crefs = 0;
  457. DWORD ccals = 0;
  458. DWORD ccbys = 0;
  459. WORD i;
  460. SetVMClient(VM_INDEX_TREE);
  461. SymCnt = 0;
  462. PropCnt = 0;
  463. for (i=0; i < cAtomsMac; i++) {
  464. vaSym = rgvaSymSorted[i];
  465. if (vaSym == vaNil) continue;
  466. gSYM(vaSym);
  467. cSYM.isym = SymCnt++; // Symbol index
  468. pSYM(vaSym);
  469. // the vaFirstProp field is used for something else in module symbols
  470. if (cSYM.cprop)
  471. vaProp = cSYM.vaFirstProp;
  472. else
  473. vaProp = vaNil;
  474. while (vaProp) {
  475. gPROP(vaProp);
  476. cPROP.iprp = PropCnt++; // Property index
  477. cdefs += CItemsList(cPROP.vaDefList);
  478. crefs += cPROP.cref;
  479. ccals += CItemsList(cPROP.vaCalList);
  480. ccbys += CItemsList(cPROP.vaCbyList);
  481. pPROP(vaProp);
  482. vaProp = cPROP.vaNextProp;
  483. }
  484. }
  485. SymCnt -= ModCnt; // Subtract module names
  486. if (cdefs > 0xffffL ||
  487. crefs > 0xffffffL ||
  488. ccals > 0xffffL ||
  489. ccbys > 0xffffL) {
  490. if (OptV) {
  491. printf ("%u\tModules\n", ModCnt);
  492. printf ("%u\tSymbols\n", SymCnt);
  493. printf ("%lu\tDefinitions\n", cdefs);
  494. printf ("%lu\tReferences\n", crefs);
  495. printf ("%lu\tCalls/Uses\n", ccals);
  496. printf ("%lu\tCalled by/Used by\n", ccbys);
  497. }
  498. Error(ERR_CAPACITY_EXCEEDED, "");
  499. }
  500. SetVMClient(VM_MISC);
  501. }
  502. static void pascal
  503. BSCWrite(LPV lpv, WORD cch)
  504. // write block to the .bsc file
  505. //
  506. {
  507. if (fwrite(lpv, cch, 1, OutFile) != 1)
  508. WriteError (OutputFileName);
  509. }
  510. static void pascal
  511. BSCWriteLsz(LSZ lsz)
  512. // write a null terminated string to the BSC file
  513. //
  514. {
  515. BSCWrite(lsz, (WORD)(strlen(lsz)+1));
  516. }
  517. #ifdef DEBUG
  518. void
  519. DebugDump()
  520. {
  521. VA vaMod, vaProp, vaSym;
  522. WORD i;
  523. vaMod = vaRootMod;
  524. printf("Modules:\n");
  525. while (vaMod) {
  526. gMOD(vaMod);
  527. printf ("\t%s\n", GetAtomStr (cMOD.vaNameSym));
  528. vaMod = cMOD.vaNextMod;
  529. }
  530. printf ("\nAll Symbols:\n");
  531. for (i=0; i < cAtomsMac; i++) {
  532. vaSym = rgvaSymSorted[i];
  533. if (vaSym == vaNil) continue;
  534. gSYM(vaSym);
  535. // the vaFirstProp field is used for something else in module symbols
  536. if (cSYM.cprop)
  537. vaProp = cSYM.vaFirstProp;
  538. else
  539. vaProp = vaNil;
  540. while (vaProp) {
  541. gPROP(vaProp);
  542. DebugDumpProp(vaProp);
  543. vaProp = gPROP(vaProp).vaNextProp;
  544. }
  545. }
  546. }
  547. void
  548. DebugDumpProp(VA vaProp)
  549. {
  550. PROP prop;
  551. VA vaRef;
  552. gPROP(vaProp);
  553. prop = cPROP;
  554. printf ("%s ", GetAtomStr (prop.vaNameSym));
  555. printf ("\t\t[%d %d %d %d]\n",
  556. CItemsList(prop.vaDefList),
  557. prop.cref,
  558. CItemsList(prop.vaCalList),
  559. CItemsList(prop.vaCbyList)
  560. );
  561. ENM_LIST(prop.vaDefList, DEF)
  562. printf ("\tdefined in %s(%d) <%d>\n",
  563. GetAtomStr (cDEF.vaFileSym),
  564. cDEF.deflin,
  565. cDEF.isbr
  566. );
  567. ENM_END
  568. vaRef = VaFrVp(prop.vpFirstRef);
  569. while (vaRef) {
  570. gREF(vaRef);
  571. printf ("\trefer'd in %s(%d) <%d>\n",
  572. GetAtomStr ( VaFrVp(cREF.vpFileSym) ),
  573. cREF.reflin,
  574. cREF.isbr
  575. );
  576. vaRef = VaFrVp(cREF.vpNextRef);
  577. }
  578. ENM_LIST(prop.vaCalList, CAL)
  579. printf ("\tcalls/uses %s[%d] <%d>\n",
  580. GetAtomStr (gPROP(cCAL.vaCalProp).vaNameSym),
  581. cCAL.calcnt,
  582. cCAL.isbr
  583. );
  584. ENM_END
  585. ENM_LIST(prop.vaCbyList, CBY)
  586. printf ("\tc-by/u-by %s[%d] <%d>\n",
  587. GetAtomStr (gPROP(cCBY.vaCbyProp).vaNameSym),
  588. cCBY.cbycnt,
  589. cCBY.isbr
  590. );
  591. ENM_END
  592. }
  593. #endif