home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / BSC32.ZIP / BSCDUMP.C < prev    next >
C/C++ Source or Header  |  1993-06-25  |  11KB  |  464 lines

  1. /*
  2.  *  Bscdump - Browser Data Base (.BSC) Dumper
  3.  *          (C) 1988-1992 By Microsoft
  4.  *
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include <stddef.h>
  11.  
  12. #include "hungary.h"
  13. #include "bsc.h"
  14. #include "bscsup.h"
  15.  
  16. #define TRUE 1
  17. #define FALSE 0
  18. #define BUF_SIZE 256
  19. #define BUF_LINES 20
  20.  
  21. char *         psymbol;
  22. char FAR *     fname;
  23. int         chSwitch = 0;
  24. MBF         mbf = mbfAll;
  25. char *        buffer[BUF_LINES];
  26.  
  27. void DumpFunctionComments(LSZ);
  28. void DumpComments(FILE *f, WORD iline);
  29. void DumpDefRefLsz(LSZ);
  30. void ListUnused(MBF);
  31. void ListRawSyms(void);
  32. void Usage(void);
  33. void GenericError(LSZ lsz);
  34. MBF  MbfFromLsz(LSZ lszPattern);
  35. void ParseArgs(int argc, char **argv, int argcReqd);
  36.  
  37. void BSC_API DumpBobInfo(BOB bob);
  38. void BSC_API DumpFwdTree(BOB bob);
  39. void BSC_API DumpRevTree(BOB bob);
  40. void BSC_API DumpDefRef(BOB bob);
  41.  
  42. // main entry point, parse args and dispatch workers...
  43. //
  44. void main(int argc, char **argv)
  45. {
  46.     // check if any switches allowed
  47.     if (argc > 2) {
  48.     if (argv[1][0] != '-' && argv[1][0] != '/')
  49.         Usage();
  50.  
  51.     chSwitch = argv[1][1];
  52.     }
  53.  
  54.     switch (chSwitch) {
  55.     case 'S':
  56.         ParseArgs(argc, argv, 3);
  57.         ListRawSyms();
  58.         break;
  59.     case 'i':
  60.         ParseArgs(argc, argv, 4);
  61.         if (!GenerateOverloads(psymbol, mbf, DumpBobInfo))
  62.             GenericError(psymbol);
  63.         break;
  64.     case 'o':
  65.         ParseArgs(argc, argv, 4);
  66.         FOutlineModuleLsz(psymbol, mbf);
  67.         break;
  68.     case 'O':
  69.         ParseArgs(argc, argv, 4);
  70.         DumpFunctionComments(psymbol);
  71.         break;
  72.     case 'l':
  73.         ParseArgs(argc, argv, 3);
  74.         ListRefs(mbf);
  75.         break;
  76.     case 'u':
  77.         ParseArgs(argc, argv, 3);
  78.         ListUnused(mbf);
  79.         break;
  80.     case 't':
  81.         ParseArgs(argc, argv, 4);
  82.         if (!GenerateOverloads(psymbol, mbfFuncs|mbfClass, DumpFwdTree))
  83.             GenericError(psymbol);
  84.         break;
  85.     case 'b':
  86.         ParseArgs(argc, argv, 4);
  87.         if (!GenerateOverloads(psymbol, mbfFuncs|mbfClass, DumpRevTree))
  88.             GenericError(psymbol);
  89.         break;
  90.     case 'R':
  91.     case 'D':
  92.         ParseArgs(argc, argv, 4);
  93.         SetCaseBSC(FALSE);
  94.         DumpDefRefLsz(psymbol);
  95.         break;
  96.     case 'r':
  97.     case 'd':
  98.         ParseArgs(argc, argv, 4);
  99.         DumpDefRefLsz(psymbol);
  100.         break;
  101.     case 's':
  102.         ParseArgs(argc, argv, 3);
  103.         StatsBSC();
  104.         break;
  105.     case 0:
  106.         ParseArgs(argc, argv, 2);
  107.         DumpBSC();
  108.         break;
  109.     default:
  110.         Usage();
  111.     }
  112.  
  113.  
  114.     CloseBSC();
  115. }
  116.  
  117. // emit usage information
  118. //
  119. void Usage()
  120. {
  121.     BSCPrintf("Microsoft (R) Bscdump Utility Version 2.0\n");
  122.     BSCPrintf("Copyright (c) Microsoft Corp 1988-1992. All rights reserved.\n");
  123.  
  124.     BSCPrintf("Usage: bscdump [options] file.bsc\n\n");
  125.     BSCPrintf("  -o[FCVMT] <file> outline\n");
  126.     BSCPrintf("  -l[FCVMT]        List references\n");
  127.     BSCPrintf("  -u[FCVMT]        List unused definitions\n");
  128.     BSCPrintf("  -i[FCVMT] <sym>  List info about given symbol\n");
  129.     BSCPrintf("  -r <sym>         List all references to symbol\n");
  130.     BSCPrintf("  -d <sym>         List all definitions of symbol\n");
  131.     BSCPrintf("  -R <sym>         List all references to symbol (case insens)\n");
  132.     BSCPrintf("  -D <sym>         List all definitions of symbol (case insens)\n");
  133.     BSCPrintf("  -t <sym>         Calltree/classtree <sym>\n");
  134.     BSCPrintf("  -b <sym>         Backwards calltree/classtree <sym>\n");
  135.     BSCPrintf("  -s               Emit BSC summary/statistics\n");
  136.     BSCPrintf("  -S               List raw symbols in database\n");
  137.     BSCPrintf("  -O <file>        outline functions with source comments\n");
  138.     exit(1);
  139. }
  140.  
  141. // dump definition or reference starting from possibly overloaded symbol name
  142. //
  143. void DumpDefRefLsz(LSZ lszSym)
  144. {
  145.     if (!GenerateOverloads(lszSym, mbfAll, DumpDefRef))
  146.         GenericError(lszSym);
  147. }
  148.  
  149. // list unused definitions, these are items which are not used by some other
  150. // symbol known to the browser.  Note, entry points like "main" should appear
  151. // in the list.  This output is helpful in locating dead code.
  152. //
  153. void ListUnused(MBF mbf)
  154. {
  155.     ISYM isym, isymMac;
  156.     IINST iinst, iinstMac;
  157.     IUBY iubyFirst, iubyLast;
  158.  
  159.     isymMac = IsymMac();
  160.  
  161.     for (isym = 0 ; isym < isymMac ; isym++) {
  162.  
  163.     InstRangeOfSym(isym, &iinst, &iinstMac);
  164.  
  165.     for ( ; iinst < iinstMac ; iinst++) {
  166.  
  167.         if (!FInstFilter(iinst, mbf))
  168.         continue;
  169.  
  170.         UbyRangeOfInst(iinst, &iubyFirst, &iubyLast);
  171.  
  172.         if (iubyFirst == iubyLast) {
  173.         DumpInst(iinst);
  174.         BSCPrintf("\n");
  175.         }
  176.     }
  177.     }
  178. }
  179.  
  180. // list the raw text of all the symbols in the database, useful
  181. // for grepping.  Note sorting order is subject to change so
  182. // use a comparision API to compare...
  183. //
  184. void ListRawSyms()
  185. {
  186.     ISYM isym, isymMac;
  187.  
  188.     isymMac = IsymMac();
  189.  
  190.     for (isym = 0 ; isym < isymMac ; isym++)
  191.     BSCPrintf("%s\n", LszNameFrSym(isym));
  192. }
  193.  
  194. // get a mask of object types (nobody knows how this ended up getting
  195. // called an MBF) from a string...
  196. //
  197. MBF MbfFromLsz(LSZ lszPattern)
  198. {
  199.     MBF mbf = mbfNil;
  200.  
  201.     for (;;)
  202.     switch (*lszPattern++) {
  203.  
  204.     case 'F':
  205.         mbf |= mbfFuncs;
  206.         break;
  207.     case 'M':
  208.         mbf |= mbfMacros;
  209.         break;
  210.     case 'V':
  211.         mbf |= mbfVars;
  212.         break;
  213.     case 'T':
  214.         mbf |= mbfTypes;
  215.         break;
  216.     case 'C':
  217.         mbf |= mbfClass;
  218.         break;
  219.     default :  
  220.         if (mbf == mbfNil) mbf = mbfAll;
  221.         return mbf;
  222.     }
  223. }
  224.  
  225. // dump the instance info from a BOB, the BOB must be of clsInst
  226. //
  227. void BSC_API DumpBobInfo(BOB bob)
  228. {
  229.     if (ClsOfBob(bob) != clsInst)
  230.     return;
  231.  
  232.     DumpInst(IinstFrBob(bob));
  233.     BSCPrintf("\n");
  234. }
  235.  
  236. // dump a forward tree, either class tree or call tree depending on
  237. // the type of BOB that we get.  The bob must be an instance BOB.
  238. //
  239. void BSC_API DumpFwdTree(BOB bob)
  240. {
  241.     IINST iinst;
  242.  
  243.     if (ClsOfBob(bob) != clsInst)
  244.     return;
  245.  
  246.     iinst = IinstFrBob(bob);
  247.  
  248.     if (FInstFilter(iinst, mbfClass))
  249.     ClassTreeInst(iinst);
  250.     else
  251.     CallTreeInst(iinst);
  252. }
  253.  
  254. // dump a reverse tree, either class tree or call tree depending on
  255. // the type of BOB that we get.  The bob must be an instance BOB.
  256. //
  257. void BSC_API DumpRevTree(BOB bob)
  258. {
  259.     IINST iinst;
  260.  
  261.     if (ClsOfBob(bob) != clsInst)
  262.     return;
  263.  
  264.     iinst = IinstFrBob(bob);
  265.  
  266.     if (FInstFilter(iinst, mbfClass))
  267.     RevClassTreeInst(iinst);
  268.     else
  269.     RevTreeInst(iinst);
  270. }
  271.  
  272. // dump definitions or references for a single BOB, suitable for use
  273. // in GenerateOverloads
  274. //
  275. void BSC_API DumpDefRef(BOB bob)
  276. {
  277.     IINST iinst;
  278.     IDEF  idef, idefMac;
  279.     IREF  iref, irefMac;
  280.     LSZ   lsz;
  281.     WORD  line;
  282.  
  283.     if (ClsOfBob(bob) != clsInst)
  284.     return;
  285.  
  286.     iinst = IinstFrBob(bob);
  287.  
  288.     DumpInst(iinst);
  289.     BSCPrintf("\n");
  290.  
  291.     if (chSwitch == 'd' || chSwitch == 'D') {
  292.         DefRangeOfInst(iinst, &idef, &idefMac);
  293.  
  294.         for ( ; idef < idefMac; idef++) {
  295.         DefInfo(idef, &lsz, &line);
  296.         BSCPrintf("%s %d\n", lsz, line+1);
  297.     }
  298.     }
  299.     else {
  300.         RefRangeOfInst(iinst, &iref, &irefMac);
  301.  
  302.         for ( ; iref < irefMac; iref++) {
  303.         RefInfo(iref, &lsz, &line);
  304.         BSCPrintf("%s %d\n", lsz, line+1);
  305.     }
  306.     }
  307.     BSCPrintf("\n");
  308. }
  309.  
  310. // non-specific error message about a given symbol
  311. //
  312. void GenericError(LSZ lsz)
  313. {
  314.     BSCPrintf("No info about '%s' available\n", lsz);
  315. }
  316.  
  317. // parse arguments into global variables and open a database
  318. //
  319. void ParseArgs(int argc, char **argv, int argcReqd)
  320. {
  321.     if (argc != argcReqd)
  322.     Usage();
  323.  
  324.     switch (argc) {
  325.     case 2:
  326.         fname = argv[1];
  327.         break;
  328.  
  329.     case 3:
  330.         fname = argv[2];
  331.         if (argv[1][0] && argv[1][1])
  332.         mbf = MbfFromLsz(argv[1]+2);
  333.         break;
  334.  
  335.     case 4:
  336.         fname = argv[3];
  337.         psymbol = argv[2];
  338.         if (argv[1][0] && argv[1][1])
  339.         mbf = MbfFromLsz(argv[1]+2);
  340.         break;
  341.     }
  342.  
  343.     if (!FOpenBSC(fname)) {
  344.     BSCPrintf("BSCdump: cannot open database %s\n", fname);
  345.     exit(4);
  346.     }
  347. }
  348.  
  349. // show any comment headers that are associated with functions
  350. // in the given module.  The module may include wildcards
  351. //
  352. void DumpFunctionComments(LSZ lszName)
  353. {
  354.     IMS ims, imsMac;
  355.     IINST iinst;
  356.     IMOD imod, imodMac;
  357.     IDEF idef, idefMac;
  358.     FILE *f;
  359.     LSZ  lszMod;
  360.     WORD iline;
  361.     WORD ibuf;
  362.     char szFileBuf[256];
  363.  
  364.     for (ibuf = 0; ibuf < BUF_LINES; ibuf++) {
  365.     buffer[ibuf] = malloc(BUF_SIZE);    
  366.     if (!buffer[ibuf]) {
  367.         BSCPrintf("Out of Memory\n");
  368.         return;
  369.     }
  370.     }
  371.  
  372.     imodMac = ImodMac();
  373.  
  374.     // we match base names only
  375.  
  376.     lszName = LszBaseName(lszName);
  377.  
  378.     for (imod = 0; imod < imodMac; imod++) {
  379.         lszMod = LszNameFrMod(imod);
  380.     if (FWildMatch(lszName, LszBaseName(lszMod))) {
  381.         _fstrcpy(szFileBuf, lszMod);
  382.         f = fopen(szFileBuf, "r");
  383.         if (!f) {
  384.         BSCPrintf("unable to open source file '%s'\n\n", lszMod);
  385.         continue;
  386.         }
  387.         BSCPrintf("\n\n[[[[[[[[[[[[[ %s ]]]]]]]]]]]]\n\n", lszMod);
  388.         MsRangeOfMod(imod, &ims, &imsMac);
  389.         for ( ;ims < imsMac; ims++) {
  390.         iinst = IinstOfIms(ims);
  391.  
  392.         if (!FInstFilter (iinst, mbfFuncs))
  393.             continue;
  394.  
  395.         DefRangeOfInst(iinst, &idef, &idefMac);
  396.         DefInfo(idef, &lszMod, &iline);
  397.  
  398.         BSCPrintf("\n## ");
  399.         DumpInst(iinst);
  400.         BSCPrintf("\n{\n");
  401.         DumpComments(f, iline);
  402.         BSCPrintf("}\n");
  403.         }
  404.         fclose(f);
  405.     }
  406.     }
  407. }
  408.  
  409. // having opened a particular file, we are now looking for comments at
  410. // or before the given line number
  411. //
  412. void DumpComments(FILE *f, WORD lineFun)
  413. {
  414.     WORD i, lineCur;
  415.     BOOL fComment = FALSE;
  416.     WORD ibuf = 0;
  417.  
  418.     // this seeking is not exactly optimal but we don't need to
  419.     // be really fast here (good thing...)
  420.  
  421.     fseek(f, 0, SEEK_SET);
  422.  
  423.     if (lineFun >= BUF_LINES)
  424.     lineCur = lineFun - BUF_LINES;
  425.     else
  426.     lineCur = 0;
  427.  
  428.     for (i=0; i < lineCur; i++)
  429.     if (!fgets(buffer[0], BUF_SIZE, f))
  430.        return;
  431.  
  432.     // we have to buffer up the lines that might be comments so
  433.     // that we can see if we found a closing brace from a previous
  434.     // function and skip those comments that belong to the previous
  435.     // function
  436.  
  437.     while (lineCur < lineFun) {
  438.     if (!fgets(buffer[ibuf], BUF_SIZE, f))
  439.         break;
  440.  
  441.     // take a stab at finding comment blocks before the function
  442.  
  443.         if (strchr(buffer[ibuf], '}')) {
  444.         for (i=0; i<=ibuf; i++)
  445.         buffer[i][0] = '\0';    // clear all previous buffers...
  446.     }
  447.  
  448.     if (strstr(buffer[ibuf], "/*") || strstr(buffer[ibuf], "//"))
  449.        fComment = TRUE;
  450.  
  451.     if (!fComment)
  452.        buffer[ibuf][0] = '\0';
  453.  
  454.     if (strstr(buffer[ibuf], "*/") || strstr(buffer[ibuf], "//"))
  455.        fComment = FALSE;
  456.  
  457.     ibuf++;
  458.     lineCur++;
  459.     }
  460.  
  461.     for (i=0; i<ibuf; i++)
  462.     BSCPrintf("%s", (LSZ)buffer[i]);
  463. }
  464.