325 lines
6.7 KiB
C
325 lines
6.7 KiB
C
|
/*
|
||
|
* BSCdump - Browser Data Base (.BSC) Dumper
|
||
|
* (C) 1988 By Microsoft
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#define LINT_ARGS
|
||
|
#if defined(OS2)
|
||
|
#define INCL_NOCOMMON
|
||
|
#define INCL_DOSPROCESS
|
||
|
#define INCL_DOSSEMAPHORES
|
||
|
#define INCL_DOSFILEMGR
|
||
|
#define INCL_DOSERRORS
|
||
|
#define INCL_DOSMISC
|
||
|
#include <os2.h>
|
||
|
#else
|
||
|
#include <windows.h>
|
||
|
#endif
|
||
|
|
||
|
#include <dos.h>
|
||
|
|
||
|
|
||
|
#include "bscdump.h"
|
||
|
#include "version.h"
|
||
|
#include "hungary.h"
|
||
|
#include "bsc.h"
|
||
|
#include "bscsup.h"
|
||
|
#include "sbrvers.h"
|
||
|
|
||
|
// this is gross but I don't know where these are supposed to come from
|
||
|
//
|
||
|
|
||
|
#ifndef TRUE
|
||
|
#define TRUE 1
|
||
|
#define FALSE 0
|
||
|
#endif
|
||
|
|
||
|
#if defined (DEBUG)
|
||
|
char fDEBUG = FALSE;
|
||
|
#endif
|
||
|
|
||
|
char *psymbol = NULL;
|
||
|
char *OutlineFileName = NULL;
|
||
|
char far * fname;
|
||
|
|
||
|
extern char *strdup();
|
||
|
|
||
|
void DumpRefsLsz(LSZ);
|
||
|
void DumpDefsLsz(LSZ);
|
||
|
void ListRdds(MBF);
|
||
|
|
||
|
main (argc, argv)
|
||
|
int argc;
|
||
|
char *argv[];
|
||
|
{
|
||
|
unsigned char Cont;
|
||
|
unsigned char fCalltree = FALSE;
|
||
|
unsigned char fSymRefs = FALSE;
|
||
|
unsigned char fSymDefs = FALSE;
|
||
|
unsigned char fRevtree = FALSE;
|
||
|
unsigned char fDumpStats = FALSE;
|
||
|
unsigned char fRedundant = FALSE;
|
||
|
MBF mbf = mbfNil, mbfRef = mbfNil, mbfRdd = mbfNil;
|
||
|
|
||
|
char *s;
|
||
|
--argc;
|
||
|
++argv;
|
||
|
while (argc && ((**argv == '-') || (**argv == '-'))) {
|
||
|
Cont = TRUE;
|
||
|
while (Cont && *++*argv)
|
||
|
switch (**argv) {
|
||
|
case 'o':
|
||
|
s = *argv+1;
|
||
|
while (*s) {
|
||
|
switch (*s) {
|
||
|
case 'F': mbf |= mbfFuncs; break;
|
||
|
case 'M': mbf |= mbfMacros; break;
|
||
|
case 'V': mbf |= mbfVars; break;
|
||
|
case 'T': mbf |= mbfTypes; break;
|
||
|
}
|
||
|
s++;
|
||
|
}
|
||
|
|
||
|
if (mbf == mbfNil) mbf = mbfAll;
|
||
|
if (--argc == 0)
|
||
|
Usage();
|
||
|
OutlineFileName = *++argv;
|
||
|
Cont = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'l':
|
||
|
s = *argv+1;
|
||
|
while (*s) {
|
||
|
switch (*s) {
|
||
|
case 'F': mbfRef |= mbfFuncs; break;
|
||
|
case 'M': mbfRef |= mbfMacros; break;
|
||
|
case 'V': mbfRef |= mbfVars; break;
|
||
|
case 'T': mbfRef |= mbfTypes; break;
|
||
|
}
|
||
|
s++;
|
||
|
}
|
||
|
|
||
|
if (mbfRef == mbfNil) mbfRef = mbfAll;
|
||
|
Cont = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'u':
|
||
|
s = *argv+1;
|
||
|
while (*s) {
|
||
|
switch (*s) {
|
||
|
case 'F': mbfRdd |= mbfFuncs; break;
|
||
|
case 'M': mbfRdd |= mbfMacros; break;
|
||
|
case 'V': mbfRdd |= mbfVars; break;
|
||
|
case 'T': mbfRdd |= mbfTypes; break;
|
||
|
}
|
||
|
s++;
|
||
|
}
|
||
|
|
||
|
if (mbfRdd == mbfNil) mbfRdd = mbfAll;
|
||
|
Cont = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 't':
|
||
|
if (--argc == 0) Usage();
|
||
|
psymbol = *++argv;
|
||
|
fCalltree = TRUE;
|
||
|
Cont = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'r':
|
||
|
if (--argc == 0) Usage();
|
||
|
psymbol = *++argv;
|
||
|
fSymRefs = TRUE;
|
||
|
Cont = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'd':
|
||
|
if (--argc == 0) Usage();
|
||
|
psymbol = *++argv;
|
||
|
fSymDefs = TRUE;
|
||
|
Cont = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 'b':
|
||
|
if (--argc == 0) Usage();
|
||
|
psymbol = *++argv;
|
||
|
fRevtree = TRUE;
|
||
|
Cont = FALSE;
|
||
|
break;
|
||
|
|
||
|
case 's':
|
||
|
fDumpStats = TRUE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Usage();
|
||
|
break;
|
||
|
}
|
||
|
--argc;
|
||
|
++argv;
|
||
|
}
|
||
|
|
||
|
if (argc < 1) {
|
||
|
Usage();
|
||
|
}
|
||
|
|
||
|
fname = strdup(*argv++);
|
||
|
|
||
|
if (!FOpenBSC(fname)) {
|
||
|
BSCPrintf("BSCdump: cannot open database %s\n", fname);
|
||
|
exit(4);
|
||
|
}
|
||
|
|
||
|
if (fDumpStats)
|
||
|
StatsBSC();
|
||
|
else if (fCalltree)
|
||
|
FCallTreeLsz(psymbol);
|
||
|
else if (fSymRefs)
|
||
|
DumpRefsLsz(psymbol);
|
||
|
else if (fSymDefs)
|
||
|
DumpDefsLsz(psymbol);
|
||
|
else if (fRevtree)
|
||
|
FRevTreeLsz(psymbol);
|
||
|
else if (OutlineFileName)
|
||
|
FOutlineModuleLsz(OutlineFileName, mbf);
|
||
|
else if (mbfRef)
|
||
|
ListRefs(mbfRef);
|
||
|
else if (mbfRdd)
|
||
|
ListRdds(mbfRdd);
|
||
|
else
|
||
|
DumpBSC();
|
||
|
|
||
|
CloseBSC();
|
||
|
|
||
|
free (fname);
|
||
|
}
|
||
|
|
||
|
Usage()
|
||
|
{
|
||
|
BSCPrintf("Microsoft (R) BSCdump Utility ");
|
||
|
BSCPrintf(VERS(rmj, rmm, rup));
|
||
|
BSCPrintf(CPYRIGHT);
|
||
|
|
||
|
BSCPrintf("Usage: bscdump [options] file.bsc\n\n");
|
||
|
BSCPrintf(" -o[FVMT] <file> outline\n");
|
||
|
BSCPrintf(" -l[FVMT] List References\n");
|
||
|
BSCPrintf(" -u[FVMT] List Redundant definitions\n");
|
||
|
BSCPrintf(" -t <sym> Calltree <sym>\n");
|
||
|
BSCPrintf(" -b <sym> Backwards Calltree <sym>\n");
|
||
|
BSCPrintf(" -s Emit BSC stats\n");
|
||
|
BSCPrintf(" -r <sym> List all references to symbol\n");
|
||
|
BSCPrintf(" -d <sym> List all definitions of symbol\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
void DumpDefsLsz(LSZ lszSym)
|
||
|
{
|
||
|
ISYM isym;
|
||
|
IINST iinst, iinstMac;
|
||
|
IDEF idef, idefMac;
|
||
|
LSZ lsz;
|
||
|
WORD line;
|
||
|
|
||
|
isym = IsymFrLsz(lszSym);
|
||
|
|
||
|
if (isym == isymNil) {
|
||
|
BSCPrintf("unknown symbol %s\n", lszSym);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
InstRangeOfSym(isym, &iinst, &iinstMac);
|
||
|
|
||
|
for (;iinst < iinstMac; iinst++) {
|
||
|
|
||
|
DefRangeOfInst(iinst, &idef, &idefMac);
|
||
|
|
||
|
for ( ; idef < idefMac; idef++) {
|
||
|
DefInfo(idef, &lsz, &line);
|
||
|
BSCPrintf("%s %d\n", lsz, line);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void DumpRefsLsz(LSZ lszSym)
|
||
|
{
|
||
|
ISYM isym;
|
||
|
IINST iinst, iinstMac;
|
||
|
IREF iref, irefMac;
|
||
|
LSZ lsz;
|
||
|
WORD line;
|
||
|
|
||
|
isym = IsymFrLsz(lszSym);
|
||
|
|
||
|
if (isym == isymNil) {
|
||
|
BSCPrintf("unknown symbol %s\n", lszSym);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
InstRangeOfSym(isym, &iinst, &iinstMac);
|
||
|
|
||
|
for (;iinst < iinstMac; iinst++) {
|
||
|
|
||
|
RefRangeOfInst(iinst, &iref, &irefMac);
|
||
|
|
||
|
for ( ; iref < irefMac; iref++) {
|
||
|
RefInfo(iref, &lsz, &line);
|
||
|
BSCPrintf("%s %d\n", lsz, line);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void ListRdds(MBF mbf)
|
||
|
{
|
||
|
ISYM isym, isymMac, isymname;
|
||
|
IINST iinst, iinstMac;
|
||
|
IUBY iubyFirst, iubyLast;
|
||
|
LSZ lszsymname;
|
||
|
TYP iinsttyp;
|
||
|
ATR iinstattr;
|
||
|
|
||
|
isymMac = IsymMac();
|
||
|
|
||
|
for (isym = 0 ; isym < isymMac ; isym++)
|
||
|
{
|
||
|
lszsymname = LszNameFrSym(isym);
|
||
|
InstRangeOfSym(isym,&iinst,&iinstMac);
|
||
|
|
||
|
for ( ; iinst < iinstMac ; iinst++)
|
||
|
{
|
||
|
UbyRangeOfInst(iinst,&iubyFirst,&iubyLast);
|
||
|
|
||
|
if (iubyFirst == iubyLast)
|
||
|
{
|
||
|
InstInfo(iinst,&isymname, &iinsttyp, &iinstattr);
|
||
|
|
||
|
// iinstattr &= INST_TYPMASK;
|
||
|
|
||
|
if (iinsttyp <= INST_TYP_LABEL && !!(mbf & mbfFuncs))
|
||
|
|
||
|
BSCPrintf("Function not called : %s\n",lszsymname);
|
||
|
|
||
|
else if
|
||
|
((iinsttyp <= INST_TYP_VARIABLE ||
|
||
|
iinsttyp >= INST_TYP_SEGMENT ) && !!(mbf & mbfVars))
|
||
|
|
||
|
BSCPrintf("Variable not used : %s\n",lszsymname);
|
||
|
|
||
|
else if
|
||
|
(iinsttyp <= INST_TYP_MACRO && !!(mbf & mbfMacros))
|
||
|
|
||
|
BSCPrintf("Macro not referenced : %s\n",lszsymname);
|
||
|
|
||
|
else if (!!(mbf & mbfTypes))
|
||
|
|
||
|
BSCPrintf("Type not referenced : %s\n",lszsymname);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|