diff options
Diffstat (limited to 'private/utils/mep/browser/mbrmake/mbrwbsc.c')
-rw-r--r-- | private/utils/mep/browser/mbrmake/mbrwbsc.c | 782 |
1 files changed, 782 insertions, 0 deletions
diff --git a/private/utils/mep/browser/mbrmake/mbrwbsc.c b/private/utils/mep/browser/mbrmake/mbrwbsc.c new file mode 100644 index 000000000..a63e6a520 --- /dev/null +++ b/private/utils/mep/browser/mbrmake/mbrwbsc.c @@ -0,0 +1,782 @@ +// +// +// 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 |