|
|
//
//
// mbRWBSC.C - Write .BSC Source Data Base file from various lists.
//
//
#define LINT_ARGS
#include <stdlib.h>
#include <search.h>
#include <ctype.h>
#include "sbrfdef.h"
#include "mbrmake.h"
#include "sbrbsc.h"
#include "mbrcache.h"
// prototypes
//
static void pascal WriteBSCHeader (void); static void pascal WriteAtoms (void); static void pascal WriteMods (void); static void pascal WriteModSyms (void); static void pascal WriteSyms (void); static void pascal WriteProps (void); static void pascal WriteRefs (void); static void pascal WriteDefs (void); static void pascal WriteCals (void); static void pascal WriteCbys (void); static void pascal WriteSbrInfo (void); static void pascal IndexTree (void); static void pascal BSCWrite (LPV lpv, WORD cch); static void pascal BSCWriteLsz (LSZ lsz);
//
#define BSCOut(v) BSCWrite(&(v), sizeof(v))
static WORD CntAtomPage; // count of Atom pages
static WORD AtomCnt = 0;
static WORD unknownModName; // UNKNOWN module idx
static WORD ModSymCnt = 0; // count of modsyms
static WORD SymCnt = 0; // count of symbols
static WORD PropCnt = 0; // count of props
static DWORD RefCnt = 0; // count of refs
static WORD DefCnt = 0; // count of defs
static WORD CbyCnt = 0; // count of use half of above
static WORD CalCnt = 0; // count of used by half of above
static DWORD lbModList; // offset to Module list
static DWORD lbModSymList; // offset to ModSym list
static DWORD lbSymList; // offset to Symbol list
static DWORD lbPropList; // offset to Property list
static DWORD lbRefList; // offset to Reference list
static DWORD lbDefList; // offset to Definition list
static DWORD lbCalList; // offset to Call/used list
static DWORD lbCbyList; // offset to Call/used list
static DWORD lbAtomCache; // offset to Sym Atom cache
static DWORD lbSbrList; // offset to Sbr file names
extern char far *GetAtomCache (WORD);
void WriteBSC (char *OutputFileName) // Write .BSC Source Data Base
//
{ OutFile = fopen(OutputFileName, "wb"); if (OutFile == NULL) { Error(ERR_OPEN_FAILED, OutputFileName); }
//
// no backing out from here -- if we fail we must delete the database
//
fOutputBroken = TRUE;
WriteBSCHeader(); // save space for header
WriteAtoms(); // sort and write atom cache
IndexTree(); // xlate pointers to indices
BldModSymList(); // Build module symbol list
SetVMClient(VM_EMIT_TREE);
unknownModName = gSYM(vaUnknownSym).isym; // record UNKNOWN index
WriteMods(); // output modules
WriteModSyms(); // output module symbol lists
WriteSyms(); // output all symbols
WriteProps(); // output all prop headers
WriteRefs(); // output all refs
WriteDefs(); // output all defs
WriteCals(); // output all uses/calls
WriteCbys(); // output all UBY/CBY
WriteSbrInfo(); // output the SBR file names
if (fseek(OutFile, 0L, SEEK_SET)) // Beginning of file
SeekError (OutputFileName);
WriteBSCHeader (); // output .BSC header
fclose(OutFile);
//
// we're all done --- it's a keeper!
//
fOutputBroken = FALSE; SetVMClient(VM_MISC);
if (OptV) { printf ("%u\tModules\n", ModCnt); printf ("%u\tSymbols\n", SymCnt); printf ("%u\tDefinitions\n", DefCnt); printf ("%u\tReferences\n", RefCnt); printf ("%u\tCalls/Uses\n", CalCnt); printf ("%u\tCalled by/Used by\n", CbyCnt); #ifdef DEBUG
printf ("\n"); printf ("%u\tTotal ModSyms\n", ModSymCnt); printf ("%u\tTotal Properties\n", PropCnt); printf ("%u\tLast Atom page \n", AtomCnt); printf ("\n"); printf ("%lu\tBase of AtomCache\n", lbAtomCache); printf ("%lu\tBase of ModList\n", lbModList); printf ("%lu\tBase of ModSymList\n", lbModSymList); printf ("%lu\tBase of SymList\n", lbSymList); printf ("%lu\tBase of PropList\n", lbPropList); printf ("%lu\tBase of RefList\n", lbRefList); printf ("%lu\tBase of DefList\n", lbDefList); printf ("%lu\tBase of CalList\n", lbCalList); printf ("%lu\tBase of CbyList\n", lbCbyList); #endif
} }
static void pascal WriteBSCHeader () // Write .BSC header, counts, and table offsets.
//
{ BYTE ver; // version num
// output BSC version (major and minor)
ver = BSC_MAJ; BSCOut(ver); // major ver
ver = BSC_MIN; BSCOut(ver); // minor ver
ver = BSC_UPD; BSCOut(ver); // update ver
BSCOut(fCase); // case sensitive
BSCOut(MaxSymLen); // biggest symbol allowed
BSCOut(unknownModName); // UNKNOWN idx
// output counts (sizes) of each data area
BSCOut(ModCnt); BSCOut(ModSymCnt); BSCOut(SymCnt); BSCOut(PropCnt); BSCOut(RefCnt); BSCOut(DefCnt); BSCOut(CalCnt); BSCOut(CbyCnt);
// last page #
BSCOut(CntAtomPage);
// last page size
BSCOut(AtomCnt);
// output BSC data area offsets
BSCOut(lbModList); BSCOut(lbModSymList); BSCOut(lbSymList); BSCOut(lbPropList); BSCOut(lbRefList); BSCOut(lbDefList); BSCOut(lbCalList); BSCOut(lbCbyList); BSCOut(lbAtomCache); BSCOut(lbSbrList); }
static void pascal WriteAtoms () // Write a sorted version of the symbol Atom Cache to the .BSC file by walking
// the sorted symbol subscript array
//
{ WORD i; int Atomlen; LPCH lpchAtoms; LSZ lszAtom;
VA vaSym;
SetVMClient(VM_EMIT_ATOMS);
lpchAtoms = LpvAllocCb(ATOMALLOC);
lbAtomCache = ftell(OutFile); // offset to text of symbols
for (i=0; i < cAtomsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
gSYM(vaSym); lszAtom = gTEXT(cSYM.vaNameText);
Atomlen = strlen(lszAtom);
// write Atom page if not enough room
//
if (Atomlen + AtomCnt + 1 > ATOMALLOC) { if (AtomCnt < ATOMALLOC) memset(lpchAtoms + AtomCnt, 0, ATOMALLOC - AtomCnt);
if ((fwrite (lpchAtoms, ATOMALLOC, 1, OutFile)) != 1) WriteError (OutputFileName);
CntAtomPage++; AtomCnt = 0; }
strcpy(lpchAtoms + AtomCnt, lszAtom); // copy Atom
cSYM.vaNameText = (PVOID)(((long)CntAtomPage << 16) | (AtomCnt));
pSYM(vaSym);
AtomCnt += Atomlen + 1;
// force to even value
if (AtomCnt & 1) lpchAtoms[AtomCnt++] = 0; }
// write last Atom page
//
if (AtomCnt) if ((fwrite (lpchAtoms, AtomCnt, 1, OutFile)) != 1) WriteError (OutputFileName);
// free all the memory for the atom cache, we no longer need it
fflush (OutFile);
FreeLpv(lpchAtoms);
SetVMClient(VM_MISC); }
static void pascal WriteMods() // write out the list of modules
//
// compute the MODSYM indices as we do this
//
{ MODLIST bmod; VA vaMod; WORD i;
ModSymCnt = 0; lbModList = ftell(OutFile); // offset to Module list
for (i = cSymbolsMac; i < cAtomsMac; i++) { gSYM(rgvaSymSorted[i]); vaMod = cSYM.vaFirstProp; // points back to module, honest!
gMOD(vaMod);
bmod.ModName = gSYM(cMOD.vaNameSym).isym; // module name idx
ModSymCnt += cMOD.csyms; bmod.mSymEnd = ModSymCnt; // last ModSym idx +1
BSCOut(bmod); } }
static void pascal WriteModSyms() // write out the list of modsyms
//
{ MODSYMLIST bmodsym; VA vaMod, vaModSym; WORD i;
lbModSymList = ftell(OutFile); // offset to ModSym list
for (i = cSymbolsMac; i < cAtomsMac; i++) { gSYM(rgvaSymSorted[i]); vaMod = cSYM.vaFirstProp; // points back to module, honest!
gMOD(vaMod);
vaModSym = cMOD.vaFirstModSym; while (vaModSym) { gMODSYM(vaModSym);
// Symbol Property idx
bmodsym.ModSymProp = gPROP(cMODSYM.vaFirstProp).iprp;
BSCOut(bmodsym);
vaModSym = cMODSYM.vaNextModSym; } } }
static void pascal WriteSyms() // write out the list of SYMs
//
{ SYMLIST bsym; VA vaSym; WORD i;
lbSymList = ftell(OutFile); // offset to Symbol list
PropCnt = 0; for (i=0; i < cAtomsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
gSYM(vaSym);
PropCnt += cSYM.cprop;
bsym.PropEnd = PropCnt; // last Prop idx +1
bsym.Atom = (WORD)((long)cSYM.vaNameText & 0xffff); // Atom cache offset
bsym.Page = (WORD)((long)cSYM.vaNameText >> 16); // Atom cache page
BSCOut(bsym); } }
static void pascal WriteProps () // write out the list of PROPS to the database
//
// the number of definitions (DefCnt), references (RefCnt),
// calls (CalCnt) and called-by (CbyCnt) items are computed at this time
//
// Each PROP is assigned numbers for its associated objects
//
{ PROPLIST bprop; VA vaSym, vaProp; WORD i;
lbPropList = ftell(OutFile); // offset to Property list
DefCnt = 0; RefCnt = 0L; CalCnt = 0; CbyCnt = 0;
for (i=0; i < cSymbolsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
vaProp = gSYM(vaSym).vaFirstProp;
while (vaProp) { gPROP(vaProp); gSYM(cPROP.vaNameSym);
bprop.PropName = cSYM.isym; // Symbol idx
bprop.PropAttr = cPROP.sattr; // Property Attribute
DefCnt += CItemsList(cPROP.vaDefList);
bprop.DefEnd = DefCnt; // last Definition idx +1
RefCnt += cPROP.cref;
bprop.RefEnd = RefCnt; // last Reference idx +1
CalCnt += CItemsList(cPROP.vaCalList);
bprop.CalEnd = CalCnt; // last Calls/uses idx +1
CbyCnt += CItemsList(cPROP.vaCbyList);
bprop.CbyEnd = CbyCnt; // last Called by/used by idx +1
BSCOut(bprop);
vaProp = cPROP.vaNextProp; } } }
static void pascal WriteRefs() // write out the list of references
//
{ REFLIST bref; VA vaSym, vaProp, vaRef; WORD i;
lbRefList = ftell(OutFile); // offset to Reference list
for (i=0; i < cSymbolsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
vaProp = gSYM(vaSym).vaFirstProp;
while (vaProp) { gPROP(vaProp);
vaRef = VaFrVp(cPROP.vpFirstRef); while (vaRef) { gREF(vaRef);
gSYM(VaFrVp(cREF.vpFileSym));
bref.RefNam = cSYM.isym; // Symbol idx
bref.RefLin = cREF.reflin; // Symbol lin
bref.isbr = cREF.isbr; // owner
BSCOut(bref);
vaRef = VaFrVp(cREF.vpNextRef); }
vaProp = cPROP.vaNextProp; } } }
static void pascal WriteDefs() // write out the list of defintions
//
{ REFLIST bdef; WORD i; VA vaProp, vaSym;
lbDefList = ftell(OutFile); // offset to Definition list
for (i=0; i < cSymbolsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
vaProp = gSYM(vaSym).vaFirstProp;
while (vaProp) { gPROP(vaProp);
ENM_LIST (cPROP.vaDefList, DEF)
gSYM(cDEF.vaFileSym);
bdef.RefNam = cSYM.isym; // Symbol idx
bdef.RefLin = cDEF.deflin; // Symbol lin
bdef.isbr = cDEF.isbr; // owner
BSCOut(bdef);
ENM_END
vaProp = cPROP.vaNextProp; } } }
static void pascal WriteCals() // write out the list of uses (CALs) items
//
{ USELIST buse; PROP prop; VA vaSym, vaProp; WORD i;
lbCalList = ftell(OutFile); // offset to CAL list
for (i=0; i < cSymbolsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
vaProp = gSYM(vaSym).vaFirstProp;
while (vaProp) { prop = gPROP(vaProp);
ENM_LIST(prop.vaCalList, CAL)
gPROP(cCAL.vaCalProp);
buse.UseProp = cPROP.iprp; // property idx
buse.UseCnt = (BYTE) cCAL.calcnt; // use count
buse.isbr = cCAL.isbr; // owner
BSCOut(buse);
ENM_END
vaProp = prop.vaNextProp; } } BSCOut(buse); // Pad
}
static void pascal WriteCbys() // write out the list of used-by (CBY) items
//
{ USELIST buse; PROP prop; VA vaSym, vaProp; WORD i;
lbCbyList = ftell(OutFile); // offset to CBY list
for (i=0; i < cSymbolsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
vaProp = gSYM(vaSym).vaFirstProp;
while (vaProp) { prop = gPROP(vaProp);
ENM_LIST(prop.vaCbyList, CBY)
gPROP(cCBY.vaCbyProp);
buse.UseProp = cPROP.iprp; // property idx
buse.UseCnt = (BYTE) cCBY.cbycnt; // use count
buse.isbr = cCBY.isbr; // owner
BSCOut(buse);
ENM_END
vaProp = prop.vaNextProp; } } BSCOut(buse); // Pad
}
static void pascal WriteSbrInfo() // write out the names of the .sbr files in the correct order
//
{ VA vaSbr; WORD isbr; VA *rgVaSbr;
lbSbrList = ftell(OutFile);
rgVaSbr = (VA *)LpvAllocCb(SbrCnt * (WORD)sizeof(VA));
for (isbr = 0; isbr < SbrCnt; isbr++) rgVaSbr[isbr] = vaNil;
vaSbr = vaRootSbr; while (vaSbr) { gSBR(vaSbr); if (cSBR.isbr != -1) rgVaSbr[cSBR.isbr] = vaSbr;
vaSbr = cSBR.vaNextSbr; }
for (isbr = 0; isbr < SbrCnt; isbr++) { if (rgVaSbr[isbr] != vaNil) { gSBR(rgVaSbr[isbr]); BSCWriteLsz(cSBR.szName); } } BSCWriteLsz(""); }
static void pascal IndexTree () // Walk all the list of all symbols and index each prop as we find it
// at this point we also count the total number of defs + refs to
// make sure that we can actually create this database
//
{ VA vaSym, vaProp; DWORD cdefs = 0; DWORD crefs = 0; DWORD ccals = 0; DWORD ccbys = 0; WORD i;
SetVMClient(VM_INDEX_TREE);
SymCnt = 0; PropCnt = 0;
for (i=0; i < cAtomsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
gSYM(vaSym); cSYM.isym = SymCnt++; // Symbol index
pSYM(vaSym);
// the vaFirstProp field is used for something else in module symbols
if (cSYM.cprop) vaProp = cSYM.vaFirstProp; else vaProp = vaNil;
while (vaProp) { gPROP(vaProp);
cPROP.iprp = PropCnt++; // Property index
cdefs += CItemsList(cPROP.vaDefList); crefs += cPROP.cref; ccals += CItemsList(cPROP.vaCalList); ccbys += CItemsList(cPROP.vaCbyList);
pPROP(vaProp);
vaProp = cPROP.vaNextProp; } } SymCnt -= ModCnt; // Subtract module names
if (cdefs > 0xffffL || crefs > 0xffffffL || ccals > 0xffffL || ccbys > 0xffffL) { if (OptV) { printf ("%u\tModules\n", ModCnt); printf ("%u\tSymbols\n", SymCnt); printf ("%lu\tDefinitions\n", cdefs); printf ("%lu\tReferences\n", crefs); printf ("%lu\tCalls/Uses\n", ccals); printf ("%lu\tCalled by/Used by\n", ccbys); } Error(ERR_CAPACITY_EXCEEDED, ""); }
SetVMClient(VM_MISC); }
static void pascal BSCWrite(LPV lpv, WORD cch) // write block to the .bsc file
//
{ if (fwrite(lpv, cch, 1, OutFile) != 1) WriteError (OutputFileName); }
static void pascal BSCWriteLsz(LSZ lsz) // write a null terminated string to the BSC file
//
{ BSCWrite(lsz, (WORD)(strlen(lsz)+1)); }
#ifdef DEBUG
void DebugDump() { VA vaMod, vaProp, vaSym; WORD i;
vaMod = vaRootMod; printf("Modules:\n"); while (vaMod) { gMOD(vaMod); printf ("\t%s\n", GetAtomStr (cMOD.vaNameSym)); vaMod = cMOD.vaNextMod; } printf ("\nAll Symbols:\n");
for (i=0; i < cAtomsMac; i++) { vaSym = rgvaSymSorted[i]; if (vaSym == vaNil) continue;
gSYM(vaSym);
// the vaFirstProp field is used for something else in module symbols
if (cSYM.cprop) vaProp = cSYM.vaFirstProp; else vaProp = vaNil;
while (vaProp) { gPROP(vaProp);
DebugDumpProp(vaProp);
vaProp = gPROP(vaProp).vaNextProp; } } }
void DebugDumpProp(VA vaProp) { PROP prop; VA vaRef;
gPROP(vaProp); prop = cPROP;
printf ("%s ", GetAtomStr (prop.vaNameSym)); printf ("\t\t[%d %d %d %d]\n", CItemsList(prop.vaDefList), prop.cref, CItemsList(prop.vaCalList), CItemsList(prop.vaCbyList) );
ENM_LIST(prop.vaDefList, DEF)
printf ("\tdefined in %s(%d) <%d>\n", GetAtomStr (cDEF.vaFileSym), cDEF.deflin, cDEF.isbr ); ENM_END
vaRef = VaFrVp(prop.vpFirstRef); while (vaRef) { gREF(vaRef);
printf ("\trefer'd in %s(%d) <%d>\n", GetAtomStr ( VaFrVp(cREF.vpFileSym) ), cREF.reflin, cREF.isbr );
vaRef = VaFrVp(cREF.vpNextRef); }
ENM_LIST(prop.vaCalList, CAL)
printf ("\tcalls/uses %s[%d] <%d>\n", GetAtomStr (gPROP(cCAL.vaCalProp).vaNameSym), cCAL.calcnt, cCAL.isbr ); ENM_END
ENM_LIST(prop.vaCbyList, CBY)
printf ("\tc-by/u-by %s[%d] <%d>\n", GetAtomStr (gPROP(cCBY.vaCbyProp).vaNameSym), cCBY.cbycnt, cCBY.isbr ); ENM_END
} #endif
|