dcc.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*****************************************************************************
  2. * dcc decompiler
  3. * Reads the command line switches and then executes each major section in turn
  4. * (C) Cristina Cifuentes
  5. ****************************************************************************/
  6. #include "dcc.h"
  7. #include <string.h>
  8. #ifdef __UNIX__
  9. #include <unistd.h>
  10. #else
  11. #include <stdio.h>
  12. #include <io.h> /* For unlink() */
  13. #endif
  14. /* Global variables - extern to other modules */
  15. char *progname; /* argv[0] - for error msgs */
  16. char *asm1_name, *asm2_name; /* Assembler output filenames */
  17. SYMTAB symtab; /* Global symbol table */
  18. STATS stats; /* cfg statistics */
  19. PROG prog; /* programs fields */
  20. OPTION option; /* Command line options */
  21. PPROC pProcList; /* List of procedures, topologically sort */
  22. PPROC pLastProc; /* Pointer to last node in procedure list */
  23. CALL_GRAPH *callGraph; /* Call graph of the program */
  24. static char *initargs(int argc, char *argv[]);
  25. static void displayTotalStats();
  26. /****************************************************************************
  27. * main
  28. ***************************************************************************/
  29. int main(int argc, char *argv[])
  30. {
  31. /* Extract switches and filename */
  32. strcpy(option.filename, initargs(argc, argv));
  33. /* Front end reads in EXE or COM file, parses it into I-code while
  34. * building the call graph and attaching appropriate bits of code for
  35. * each procedure.
  36. */
  37. FrontEnd (option.filename, &callGraph);
  38. /* In the middle is a so called Universal Decompiling Machine.
  39. * It processes the procedure list and I-code and attaches where it can
  40. * to each procedure an optimised cfg and ud lists
  41. */
  42. udm();
  43. /* Back end converts each procedure into C using I-code, interval
  44. * analysis, data flow etc. and outputs it to output file ready for
  45. * re-compilation.
  46. */
  47. BackEnd(option.filename, callGraph);
  48. writeCallGraph (callGraph);
  49. if (option.Stats)
  50. displayTotalStats();
  51. /*
  52. freeDataStructures(pProcList);
  53. */
  54. return 0;
  55. }
  56. /****************************************************************************
  57. * initargs - Extract command line arguments
  58. ***************************************************************************/
  59. static char *initargs(int argc, char *argv[])
  60. {
  61. char *pc;
  62. progname = *argv; /* Save invocation name for error messages */
  63. while (--argc > 0 && (*++argv)[0] == '-') {
  64. for (pc = argv[0]+1; *pc; pc++)
  65. switch (*pc) {
  66. case 'a': /* Print assembler listing */
  67. if (*(pc+1) == '2')
  68. option.asm2 = TRUE;
  69. else
  70. option.asm1 = TRUE;
  71. if (*(pc+1) == '1' || *(pc+1) == '2')
  72. pc++;
  73. break;
  74. case 'c':
  75. option.Calls = TRUE;
  76. break;
  77. case 'i':
  78. option.Interact = TRUE;
  79. break;
  80. case 'm': /* Print memory map */
  81. option.Map = TRUE;
  82. break;
  83. case 's': /* Print Stats */
  84. option.Stats = TRUE;
  85. break;
  86. case 'V': /* Very verbose => verbose */
  87. option.VeryVerbose = TRUE;
  88. case 'v': /* Make everything verbose */
  89. option.verbose = TRUE;
  90. break;
  91. case 'o': /* assembler output file */
  92. if (*(pc+1)) {
  93. asm1_name = asm2_name = pc+1;
  94. goto NextArg;
  95. }
  96. else if (--argc > 0) {
  97. asm1_name = asm2_name = *++argv;
  98. goto NextArg;
  99. }
  100. default:
  101. fatalError(INVALID_ARG, *pc);
  102. return *argv;
  103. }
  104. NextArg:;
  105. }
  106. if (argc == 1)
  107. {
  108. if (option.asm1 || option.asm2)
  109. {
  110. if (! asm1_name)
  111. {
  112. asm1_name = strcpy((char*)allocMem(strlen(*argv)+4), *argv);
  113. pc = strrchr(asm1_name, '.');
  114. if (pc > strrchr(asm1_name, '/'))
  115. {
  116. *pc = '\0';
  117. }
  118. asm2_name = (char*)allocMem(strlen(asm1_name)+4) ;
  119. strcat(strcpy(asm2_name, asm1_name), ".a2");
  120. unlink(asm2_name);
  121. strcat(asm1_name, ".a1");
  122. }
  123. unlink(asm1_name); /* Remove asm output files */
  124. }
  125. return *argv; /* filename of the program to decompile */
  126. }
  127. fatalError(USAGE);
  128. return *argv;
  129. }
  130. static void
  131. displayTotalStats ()
  132. /* Displays final statistics for the complete program */
  133. {
  134. printf ("\nFinal Program Statistics\n");
  135. printf (" Total number of low-level Icodes : %ld\n", stats.totalLL);
  136. printf (" Total number of high-level Icodes: %ld\n", stats.totalHL);
  137. printf (" Total reduction of instructions : %2.2f%%\n", 100.0 -
  138. (stats.totalHL * 100.0) / stats.totalLL);
  139. }