home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PROG_C
/
BSC32.ZIP
/
BSCDUMP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-25
|
11KB
|
464 lines
/*
* Bscdump - Browser Data Base (.BSC) Dumper
* (C) 1988-1992 By Microsoft
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include "hungary.h"
#include "bsc.h"
#include "bscsup.h"
#define TRUE 1
#define FALSE 0
#define BUF_SIZE 256
#define BUF_LINES 20
char * psymbol;
char FAR * fname;
int chSwitch = 0;
MBF mbf = mbfAll;
char * buffer[BUF_LINES];
void DumpFunctionComments(LSZ);
void DumpComments(FILE *f, WORD iline);
void DumpDefRefLsz(LSZ);
void ListUnused(MBF);
void ListRawSyms(void);
void Usage(void);
void GenericError(LSZ lsz);
MBF MbfFromLsz(LSZ lszPattern);
void ParseArgs(int argc, char **argv, int argcReqd);
void BSC_API DumpBobInfo(BOB bob);
void BSC_API DumpFwdTree(BOB bob);
void BSC_API DumpRevTree(BOB bob);
void BSC_API DumpDefRef(BOB bob);
// main entry point, parse args and dispatch workers...
//
void main(int argc, char **argv)
{
// check if any switches allowed
if (argc > 2) {
if (argv[1][0] != '-' && argv[1][0] != '/')
Usage();
chSwitch = argv[1][1];
}
switch (chSwitch) {
case 'S':
ParseArgs(argc, argv, 3);
ListRawSyms();
break;
case 'i':
ParseArgs(argc, argv, 4);
if (!GenerateOverloads(psymbol, mbf, DumpBobInfo))
GenericError(psymbol);
break;
case 'o':
ParseArgs(argc, argv, 4);
FOutlineModuleLsz(psymbol, mbf);
break;
case 'O':
ParseArgs(argc, argv, 4);
DumpFunctionComments(psymbol);
break;
case 'l':
ParseArgs(argc, argv, 3);
ListRefs(mbf);
break;
case 'u':
ParseArgs(argc, argv, 3);
ListUnused(mbf);
break;
case 't':
ParseArgs(argc, argv, 4);
if (!GenerateOverloads(psymbol, mbfFuncs|mbfClass, DumpFwdTree))
GenericError(psymbol);
break;
case 'b':
ParseArgs(argc, argv, 4);
if (!GenerateOverloads(psymbol, mbfFuncs|mbfClass, DumpRevTree))
GenericError(psymbol);
break;
case 'R':
case 'D':
ParseArgs(argc, argv, 4);
SetCaseBSC(FALSE);
DumpDefRefLsz(psymbol);
break;
case 'r':
case 'd':
ParseArgs(argc, argv, 4);
DumpDefRefLsz(psymbol);
break;
case 's':
ParseArgs(argc, argv, 3);
StatsBSC();
break;
case 0:
ParseArgs(argc, argv, 2);
DumpBSC();
break;
default:
Usage();
}
CloseBSC();
}
// emit usage information
//
void Usage()
{
BSCPrintf("Microsoft (R) Bscdump Utility Version 2.0\n");
BSCPrintf("Copyright (c) Microsoft Corp 1988-1992. All rights reserved.\n");
BSCPrintf("Usage: bscdump [options] file.bsc\n\n");
BSCPrintf(" -o[FCVMT] <file> outline\n");
BSCPrintf(" -l[FCVMT] List references\n");
BSCPrintf(" -u[FCVMT] List unused definitions\n");
BSCPrintf(" -i[FCVMT] <sym> List info about given symbol\n");
BSCPrintf(" -r <sym> List all references to symbol\n");
BSCPrintf(" -d <sym> List all definitions of symbol\n");
BSCPrintf(" -R <sym> List all references to symbol (case insens)\n");
BSCPrintf(" -D <sym> List all definitions of symbol (case insens)\n");
BSCPrintf(" -t <sym> Calltree/classtree <sym>\n");
BSCPrintf(" -b <sym> Backwards calltree/classtree <sym>\n");
BSCPrintf(" -s Emit BSC summary/statistics\n");
BSCPrintf(" -S List raw symbols in database\n");
BSCPrintf(" -O <file> outline functions with source comments\n");
exit(1);
}
// dump definition or reference starting from possibly overloaded symbol name
//
void DumpDefRefLsz(LSZ lszSym)
{
if (!GenerateOverloads(lszSym, mbfAll, DumpDefRef))
GenericError(lszSym);
}
// list unused definitions, these are items which are not used by some other
// symbol known to the browser. Note, entry points like "main" should appear
// in the list. This output is helpful in locating dead code.
//
void ListUnused(MBF mbf)
{
ISYM isym, isymMac;
IINST iinst, iinstMac;
IUBY iubyFirst, iubyLast;
isymMac = IsymMac();
for (isym = 0 ; isym < isymMac ; isym++) {
InstRangeOfSym(isym, &iinst, &iinstMac);
for ( ; iinst < iinstMac ; iinst++) {
if (!FInstFilter(iinst, mbf))
continue;
UbyRangeOfInst(iinst, &iubyFirst, &iubyLast);
if (iubyFirst == iubyLast) {
DumpInst(iinst);
BSCPrintf("\n");
}
}
}
}
// list the raw text of all the symbols in the database, useful
// for grepping. Note sorting order is subject to change so
// use a comparision API to compare...
//
void ListRawSyms()
{
ISYM isym, isymMac;
isymMac = IsymMac();
for (isym = 0 ; isym < isymMac ; isym++)
BSCPrintf("%s\n", LszNameFrSym(isym));
}
// get a mask of object types (nobody knows how this ended up getting
// called an MBF) from a string...
//
MBF MbfFromLsz(LSZ lszPattern)
{
MBF mbf = mbfNil;
for (;;)
switch (*lszPattern++) {
case 'F':
mbf |= mbfFuncs;
break;
case 'M':
mbf |= mbfMacros;
break;
case 'V':
mbf |= mbfVars;
break;
case 'T':
mbf |= mbfTypes;
break;
case 'C':
mbf |= mbfClass;
break;
default :
if (mbf == mbfNil) mbf = mbfAll;
return mbf;
}
}
// dump the instance info from a BOB, the BOB must be of clsInst
//
void BSC_API DumpBobInfo(BOB bob)
{
if (ClsOfBob(bob) != clsInst)
return;
DumpInst(IinstFrBob(bob));
BSCPrintf("\n");
}
// dump a forward tree, either class tree or call tree depending on
// the type of BOB that we get. The bob must be an instance BOB.
//
void BSC_API DumpFwdTree(BOB bob)
{
IINST iinst;
if (ClsOfBob(bob) != clsInst)
return;
iinst = IinstFrBob(bob);
if (FInstFilter(iinst, mbfClass))
ClassTreeInst(iinst);
else
CallTreeInst(iinst);
}
// dump a reverse tree, either class tree or call tree depending on
// the type of BOB that we get. The bob must be an instance BOB.
//
void BSC_API DumpRevTree(BOB bob)
{
IINST iinst;
if (ClsOfBob(bob) != clsInst)
return;
iinst = IinstFrBob(bob);
if (FInstFilter(iinst, mbfClass))
RevClassTreeInst(iinst);
else
RevTreeInst(iinst);
}
// dump definitions or references for a single BOB, suitable for use
// in GenerateOverloads
//
void BSC_API DumpDefRef(BOB bob)
{
IINST iinst;
IDEF idef, idefMac;
IREF iref, irefMac;
LSZ lsz;
WORD line;
if (ClsOfBob(bob) != clsInst)
return;
iinst = IinstFrBob(bob);
DumpInst(iinst);
BSCPrintf("\n");
if (chSwitch == 'd' || chSwitch == 'D') {
DefRangeOfInst(iinst, &idef, &idefMac);
for ( ; idef < idefMac; idef++) {
DefInfo(idef, &lsz, &line);
BSCPrintf("%s %d\n", lsz, line+1);
}
}
else {
RefRangeOfInst(iinst, &iref, &irefMac);
for ( ; iref < irefMac; iref++) {
RefInfo(iref, &lsz, &line);
BSCPrintf("%s %d\n", lsz, line+1);
}
}
BSCPrintf("\n");
}
// non-specific error message about a given symbol
//
void GenericError(LSZ lsz)
{
BSCPrintf("No info about '%s' available\n", lsz);
}
// parse arguments into global variables and open a database
//
void ParseArgs(int argc, char **argv, int argcReqd)
{
if (argc != argcReqd)
Usage();
switch (argc) {
case 2:
fname = argv[1];
break;
case 3:
fname = argv[2];
if (argv[1][0] && argv[1][1])
mbf = MbfFromLsz(argv[1]+2);
break;
case 4:
fname = argv[3];
psymbol = argv[2];
if (argv[1][0] && argv[1][1])
mbf = MbfFromLsz(argv[1]+2);
break;
}
if (!FOpenBSC(fname)) {
BSCPrintf("BSCdump: cannot open database %s\n", fname);
exit(4);
}
}
// show any comment headers that are associated with functions
// in the given module. The module may include wildcards
//
void DumpFunctionComments(LSZ lszName)
{
IMS ims, imsMac;
IINST iinst;
IMOD imod, imodMac;
IDEF idef, idefMac;
FILE *f;
LSZ lszMod;
WORD iline;
WORD ibuf;
char szFileBuf[256];
for (ibuf = 0; ibuf < BUF_LINES; ibuf++) {
buffer[ibuf] = malloc(BUF_SIZE);
if (!buffer[ibuf]) {
BSCPrintf("Out of Memory\n");
return;
}
}
imodMac = ImodMac();
// we match base names only
lszName = LszBaseName(lszName);
for (imod = 0; imod < imodMac; imod++) {
lszMod = LszNameFrMod(imod);
if (FWildMatch(lszName, LszBaseName(lszMod))) {
_fstrcpy(szFileBuf, lszMod);
f = fopen(szFileBuf, "r");
if (!f) {
BSCPrintf("unable to open source file '%s'\n\n", lszMod);
continue;
}
BSCPrintf("\n\n[[[[[[[[[[[[[ %s ]]]]]]]]]]]]\n\n", lszMod);
MsRangeOfMod(imod, &ims, &imsMac);
for ( ;ims < imsMac; ims++) {
iinst = IinstOfIms(ims);
if (!FInstFilter (iinst, mbfFuncs))
continue;
DefRangeOfInst(iinst, &idef, &idefMac);
DefInfo(idef, &lszMod, &iline);
BSCPrintf("\n## ");
DumpInst(iinst);
BSCPrintf("\n{\n");
DumpComments(f, iline);
BSCPrintf("}\n");
}
fclose(f);
}
}
}
// having opened a particular file, we are now looking for comments at
// or before the given line number
//
void DumpComments(FILE *f, WORD lineFun)
{
WORD i, lineCur;
BOOL fComment = FALSE;
WORD ibuf = 0;
// this seeking is not exactly optimal but we don't need to
// be really fast here (good thing...)
fseek(f, 0, SEEK_SET);
if (lineFun >= BUF_LINES)
lineCur = lineFun - BUF_LINES;
else
lineCur = 0;
for (i=0; i < lineCur; i++)
if (!fgets(buffer[0], BUF_SIZE, f))
return;
// we have to buffer up the lines that might be comments so
// that we can see if we found a closing brace from a previous
// function and skip those comments that belong to the previous
// function
while (lineCur < lineFun) {
if (!fgets(buffer[ibuf], BUF_SIZE, f))
break;
// take a stab at finding comment blocks before the function
if (strchr(buffer[ibuf], '}')) {
for (i=0; i<=ibuf; i++)
buffer[i][0] = '\0'; // clear all previous buffers...
}
if (strstr(buffer[ibuf], "/*") || strstr(buffer[ibuf], "//"))
fComment = TRUE;
if (!fComment)
buffer[ibuf][0] = '\0';
if (strstr(buffer[ibuf], "*/") || strstr(buffer[ibuf], "//"))
fComment = FALSE;
ibuf++;
lineCur++;
}
for (i=0; i<ibuf; i++)
BSCPrintf("%s", (LSZ)buffer[i]);
}