Browse Source

Qt5 command options processing

nemerle 10 years ago
parent
commit
3603877f42
11 changed files with 99 additions and 131 deletions
  1. 9 5
      CMakeLists.txt
  2. 3 3
      include/dcc.h
  3. 6 14
      include/symtab.h
  4. 3 3
      regression_tester.rb
  5. 3 3
      src/backend.cpp
  6. 0 1
      src/chklib.cpp
  7. 64 86
      src/dcc.cpp
  8. 1 1
      src/disassem.cpp
  9. 1 1
      src/frontend.cpp
  10. 7 13
      src/procs.cpp
  11. 2 1
      src/project.cpp

+ 9 - 5
CMakeLists.txt

@@ -1,5 +1,8 @@
 PROJECT(dcc_original)
-CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.9)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_AUTOMOC ON)
+find_package(Qt5Core)
 
 OPTION(dcc_build_tests "Enable unit tests." OFF)
 #SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR})
@@ -9,7 +12,7 @@ IF(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)")
     ADD_DEFINITIONS(/W4)
 ELSE()
 #-D_GLIBCXX_DEBUG
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++0x")
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall --std=c++11")
     SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} "  ) #--coverage
 ENDIF()
 
@@ -34,6 +37,7 @@ INCLUDE_DIRECTORIES(
     ${LLVM_INCLUDE_DIRS}
 )
 set(dcc_LIB_SOURCES
+    src/CallConvention.cpp
     src/ast.cpp
     src/backend.cpp
     src/bundle.cpp
@@ -73,7 +77,6 @@ set(dcc_LIB_SOURCES
     src/symtab.cpp
     src/udm.cpp
     src/BasicBlock.cpp
-    src/CallConvention.cpp
 )
 set(dcc_SOURCES
     src/dcc.cpp
@@ -100,6 +103,7 @@ set(dcc_HEADERS
     include/idioms/shift_idioms.h
     include/idioms/xor_idioms.h
     include/locident.h
+    include/CallConvention.h
     include/perfhlib.h
     include/project.h
     include/scanner.h
@@ -109,7 +113,6 @@ set(dcc_HEADERS
     include/Procedure.h
     include/StackFrame.h
     include/BasicBlock.h
-    include/CallConvention.h
 
 )
 SOURCE_GROUP(Source FILES ${dcc_SOURCES})
@@ -120,7 +123,8 @@ ADD_LIBRARY(dcc_lib STATIC ${dcc_LIB_SOURCES} ${dcc_HEADERS})
 
 ADD_EXECUTABLE(dcc_original ${dcc_SOURCES} ${dcc_HEADERS})
 ADD_DEPENDENCIES(dcc_original dcc_lib)
-TARGET_LINK_LIBRARIES(dcc_original LLVMSupport dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} LLVMSupport)
+TARGET_LINK_LIBRARIES(dcc_original dcc_lib disasm_s ${REQ_LLVM_LIBRARIES} ncurses LLVMSupport)
+qt5_use_modules(dcc_original Core)
 if(dcc_build_tests)
 ADD_SUBDIRECTORY(src)
 endif()

+ 3 - 3
include/dcc.h

@@ -26,7 +26,7 @@ extern bundle cCode;			/* Output C procedure's declaration and code */
 
 /**** Global variables ****/
 
-extern char *asm1_name, *asm2_name; /* Assembler output filenames 		*/
+extern std::string asm1_name, asm2_name; /* Assembler output filenames 		*/
 
 typedef struct {            /* Command line option flags */
     unsigned verbose        : 1;
@@ -37,7 +37,7 @@ typedef struct {            /* Command line option flags */
     unsigned Stats          : 1;
     unsigned Interact       : 1;    /* Interactive mode */
     unsigned Calls          : 1;    /* Follow register indirect calls */
-    char	filename[80];			/* The input filename */
+    std::string	filename;			/* The input filename */
 } OPTION;
 
 extern OPTION option;       /* Command line options             */
@@ -86,7 +86,7 @@ public:
 void    udm(void);                                          /* udm.c        */
 void    freeCFG(BB * cfg);                                  /* graph.c      */
 BB *    newBB(BB *, int, int, uint8_t, int, Function *);    /* graph.c      */
-void    BackEnd(char *filename, CALL_GRAPH *);              /* backend.c    */
+void    BackEnd(const std::string &filename, CALL_GRAPH *);              /* backend.c    */
 extern char   *cChar(uint8_t c);                            /* backend.c    */
 eErrorId scan(uint32_t ip, ICODE &p);                       /* scanner.c    */
 void    parse (CALL_GRAPH * *);                             /* parser.c     */

+ 6 - 14
include/symtab.h

@@ -36,21 +36,13 @@ struct SYM : public SymbolCommon
 struct STKSYM : public SymbolCommon
 {
     typedef int16_t tLabel;
-    Expr	*actual;	/* Expression tree of actual parameter 		*/
-    AstIdent 	*regs;		/* For register arguments only				*/
-    tLabel      label;        /* Immediate off from BP (+:args, -:params) */
-    uint8_t     regOff;     /* Offset is a register (e.g. SI, DI)       */
-    bool        hasMacro;	/* This type needs a macro					*/
+    Expr	*actual=0;	/* Expression tree of actual parameter 		*/
+    AstIdent 	*regs=0;		/* For register arguments only				*/
+    tLabel      label=0;        /* Immediate off from BP (+:args, -:params) */
+    uint8_t     regOff=0;     /* Offset is a register (e.g. SI, DI)       */
+    bool        hasMacro=false;	/* This type needs a macro					*/
     std::string macro;  	/* Macro name								*/
-    bool        invalid;	/* Boolean: invalid entry in formal arg list*/
-    STKSYM()
-    {
-        actual=0;
-        regs=0;
-        label=0;
-        regOff=0;
-        invalid=hasMacro = false;
-    }
+    bool        invalid=false;	/* Boolean: invalid entry in formal arg list*/
     void setArgName(int i)
     {
         char buf[32];

+ 3 - 3
regression_tester.rb

@@ -14,9 +14,9 @@ def perform_test(exepath,filepath,outname,args)
 	filepath=path_local(filepath)
 	joined_args = args.join(' ')
 	printf("calling:" + "#{exepath} -a1 #{joined_args} -o#{output_path}.a1 #{filepath}\n")
-	STDERR << "Errors for : #{filepath}"
-	result = `#{exepath} -a1 -o#{output_path}.a1 #{filepath}`
-	result = `#{exepath} -a2 #{joined_args} -o#{output_path}.a2 #{filepath}`
+	STDERR << "Errors for : #{filepath}\n"
+	result = `#{exepath} -a 1 -o#{output_path}.a1 #{filepath}`
+	result = `#{exepath} -a 2 #{joined_args} -o#{output_path}.a2 #{filepath}`
 	result = `#{exepath} #{joined_args} -o#{output_path} #{filepath}`
 	puts result
 	p $?

+ 3 - 3
src/backend.cpp

@@ -167,7 +167,7 @@ void Project::writeGlobSymTable()
 
 /* Writes the header information and global variables to the output C file
  * fp. */
-static void writeHeader (std::ostream &_ios, char *fileName)
+static void writeHeader (std::ostream &_ios, const char *fileName)
 {
     PROG &prog(Project::get()->prog);
     /* Write header information */
@@ -341,7 +341,7 @@ static void backBackEnd (CALL_GRAPH * pcallGraph, std::ostream &_ios)
 
 
 /* Invokes the necessary routines to produce code one procedure at a time. */
-void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
+void BackEnd (const std::string &fileName, CALL_GRAPH * pcallGraph)
 {
     std::ofstream fs; /* Output C file 	*/
 
@@ -356,7 +356,7 @@ void BackEnd (char *fileName, CALL_GRAPH * pcallGraph)
     printf ("dcc: Writing C beta file %s\n", outNam.c_str());
 
     /* Header information */
-    writeHeader (fs, option.filename);
+    writeHeader (fs, option.filename.c_str());
 
     /* Initialize total Icode instructions statistics */
     stats.totalLL = 0;

+ 0 - 1
src/chklib.cpp

@@ -68,7 +68,6 @@ void readFileSection(uint16_t* p, int len, FILE *_file);
 void cleanup(void);
 void checkStartup(STATE *state);
 void readProtoFile(void);
-void fixNewline(char *s);
 int  searchPList(char *name);
 void checkHeap(char *msg);              /* For debugging */
 

+ 64 - 86
src/dcc.cpp

@@ -4,13 +4,15 @@
  * (C) Cristina Cifuentes
  ****************************************************************************/
 
+#include <QtCore/QCoreApplication>
+#include <QCommandLineParser>
 #include <cstring>
 #include "dcc.h"
 #include "project.h"
 
 #include "CallGraph.h"
 /* Global variables - extern to other modules */
-extern char    *asm1_name, *asm2_name;     /* Assembler output filenames     */
+extern std::string asm1_name, asm2_name;     /* Assembler output filenames     */
 extern SYMTAB  symtab;             /* Global symbol table      			  */
 extern STATS   stats;              /* cfg statistics       				  */
 //PROG    prog;               /* programs fields      				  */
@@ -40,6 +42,7 @@ static void displayTotalStats(void);
 /****************************************************************************
  * main
  ***************************************************************************/
+#include <QtCore/QFile>
 #include <iostream>
 using namespace llvm;
 bool TVisitor(raw_ostream &OS, RecordKeeper &Records)
@@ -111,11 +114,68 @@ int testTblGen(int argc, char **argv)
 
     exit(0);
 
+}
+void setupOptions(QCoreApplication &app) {
+    //[-a1a2cmsi]
+    QCommandLineParser parser;
+    parser.setApplicationDescription("dcc");
+    parser.addHelpOption();
+    //parser.addVersionOption();
+    //QCommandLineOption showProgressOption("p", QCoreApplication::translate("main", "Show progress during copy"));
+    QCommandLineOption boolOpts[] {
+        QCommandLineOption {"v", QCoreApplication::translate("main", "verbose")},
+        QCommandLineOption {"V", QCoreApplication::translate("main", "very verbose")},
+        QCommandLineOption {"c", QCoreApplication::translate("main", "Follow register indirect calls")},
+        QCommandLineOption {"m", QCoreApplication::translate("main", "Print memory maps of program")},
+        QCommandLineOption {"s", QCoreApplication::translate("main", "Print stats")}
+    };
+    for(QCommandLineOption &o : boolOpts) {
+        parser.addOption(o);
+    }
+    QCommandLineOption assembly("a", QCoreApplication::translate("main", "Produce assembly"),"assembly_level");
+    // A boolean option with multiple names (-f, --force)
+    //QCommandLineOption forceOption(QStringList() << "f" << "force", "Overwrite existing files.");
+    // An option with a value
+    QCommandLineOption targetFileOption(QStringList() << "o" << "output",
+                                        QCoreApplication::translate("main", "Place output into <file>."),
+                                        QCoreApplication::translate("main", "file"));
+    parser.addOption(targetFileOption);
+    parser.addOption(assembly);
+    //parser.addOption(forceOption);
+    // Process the actual command line arguments given by the user
+    parser.addPositionalArgument("source", QCoreApplication::translate("main", "Dos Executable file to decompile."));
+    parser.process(app);
+
+    const QStringList args = parser.positionalArguments();
+    if(args.empty()) {
+        parser.showHelp();
+    }
+    // source is args.at(0), destination is args.at(1)
+    option.verbose = parser.isSet(boolOpts[0]);
+    option.VeryVerbose = parser.isSet(boolOpts[1]);
+    if(parser.isSet(assembly)) {
+        option.asm1 = parser.value(assembly).toInt()==1;
+        option.asm2 = parser.value(assembly).toInt()==2;
+    }
+    option.Map = parser.isSet(boolOpts[3]);
+    option.Stats = parser.isSet(boolOpts[4]);
+    option.Interact = false;
+    option.Calls = parser.isSet(boolOpts[2]);
+    option.filename = args.first().toStdString();
+    if(parser.isSet(targetFileOption))
+        asm1_name = asm2_name = parser.value(targetFileOption).toStdString();
+    else if(option.asm1 || option.asm2) {
+        asm1_name = option.filename+".a1";
+        asm2_name = option.filename+".a2";
+    }
+
 }
 int main(int argc, char **argv)
 {
-    /* Extract switches and filename */
-    strcpy(option.filename, initargs(argc, argv));
+    QCoreApplication app(argc,argv);
+
+    QCoreApplication::setApplicationVersion("0.1");
+    setupOptions(app);
 
     /* Front end reads in EXE or COM file, parses it into I-code while
      * building the call graph and attaching appropriate bits of code for
@@ -138,98 +198,16 @@ int main(int argc, char **argv)
      * analysis, data flow etc. and outputs it to output file ready for
      * re-compilation.
     */
-    BackEnd(asm1_name ? asm1_name:option.filename, Project::get()->callGraph);
+    BackEnd(!asm1_name.empty() ? asm1_name:option.filename, Project::get()->callGraph);
 
     Project::get()->callGraph->write();
 
     if (option.Stats)
         displayTotalStats();
 
-    /*
-    freeDataStructures(pProcList);
-*/
     return 0;
 }
 
-/****************************************************************************
- * initargs - Extract command line arguments
- ***************************************************************************/
-static char *initargs(int argc, char *argv[])
-{
-    char *pc;
-
-    while (--argc > 0 && (*++argv)[0] == '-')
-    {
-        for (pc = argv[0]+1; *pc; pc++)
-            switch (*pc)
-            {
-                case 'a':       /* Print assembler listing */
-                    if (*(pc+1) == '2')
-                        option.asm2 = true;
-                    else
-                        option.asm1 = true;
-                    if (*(pc+1) == '1' || *(pc+1) == '2')
-                        pc++;
-                    break;
-                case 'c':
-                    option.Calls = true;
-                    break;
-                case 'i':
-                    option.Interact = true;
-                    break;
-                case 'm':       /* Print memory map */
-                    option.Map = true;
-                    break;
-                case 's':       /* Print Stats */
-                    option.Stats = true;
-                    break;
-                case 'V':       /* Very verbose => verbose */
-                    option.VeryVerbose = true;
-                case 'v':
-                    option.verbose = true; /* Make everything verbose */
-                    break;
-                case 'o':       /* assembler output file */
-                    if (*(pc+1)) {
-                        asm1_name = asm2_name = pc+1;
-                        goto NextArg;
-                    }
-                    else if (--argc > 0) {
-                        asm1_name = asm2_name = *++argv;
-                        goto NextArg;
-                    }
-                default:
-                    fatalError(INVALID_ARG, *pc);
-                    return *argv;
-            }
-NextArg:;
-    }
-
-    if (argc == 1)
-    {
-        if (option.asm1 || option.asm2)
-        {
-            if (! asm1_name)
-            {
-                asm1_name = strcpy((char*)malloc(strlen(*argv)+4), *argv);
-                pc = strrchr(asm1_name, '.');
-                if (pc > strrchr(asm1_name, '/'))
-                {
-                    *pc = '\0';
-                }
-                asm2_name = (char*)malloc(strlen(asm1_name)+4) ;
-                strcat(strcpy(asm2_name, asm1_name), ".a2");
-                unlink(asm2_name);
-                strcat(asm1_name, ".a1");
-            }
-            unlink(asm1_name);  /* Remove asm output files */
-        }
-        return *argv;       /* filename of the program to decompile */
-    }
-
-    fatalError(USAGE);
-    return *argv; // does not reach this.
-}
-
 static void
 displayTotalStats ()
 /* Displays final statistics for the complete program */

+ 1 - 1
src/disassem.cpp

@@ -153,7 +153,7 @@ void Disassembler::disassem(Function * ppProc)
         m_fp.open(p,ios_base::app);
         if (!m_fp.is_open())
         {
-            fatalError(CANNOT_OPEN, p);
+            fatalError(CANNOT_OPEN, p.c_str());
         }
     }
     /* Create temporary code array */

+ 1 - 1
src/frontend.cpp

@@ -82,7 +82,7 @@ bool DccFrontend::FrontEnd ()
 
     if (option.asm1)
     {
-        printf("dcc: writing assembler file %s\n", asm1_name);
+        printf("dcc: writing assembler file %s\n", asm1_name.c_str());
     }
 
     /* Search through code looking for impure references and flag them */

+ 7 - 13
src/procs.cpp

@@ -27,7 +27,6 @@ const char *indentStr(int indLevel) // Indentation according to the depth of the
  * not exist.  */
 void CALL_GRAPH::insertArc (ilFunction newProc)
 {
-    CALL_GRAPH *pcg;
 
 
     /* Check if procedure already exists */
@@ -35,7 +34,7 @@ void CALL_GRAPH::insertArc (ilFunction newProc)
     if(res!=outEdges.end())
         return;
     /* Include new arc */
-    pcg = new CALL_GRAPH;
+    CALL_GRAPH *pcg = new CALL_GRAPH;
     pcg->proc = newProc;
     outEdges.push_back(pcg);
 }
@@ -49,13 +48,10 @@ bool CALL_GRAPH::insertCallGraph(ilFunction caller, ilFunction callee)
         insertArc (callee);
         return true;
     }
-    else
-    {
         for (CALL_GRAPH *edg : outEdges)
             if (edg->insertCallGraph (caller, callee))
                 return true;
-        return (false);
-    }
+    return false;
 }
 
 bool CALL_GRAPH::insertCallGraph(Function *caller, ilFunction callee)
@@ -333,7 +329,6 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
 {
     hlType forType;
     STKSYM * psym, * nsym;
-    int off;
     /* If formal argument does not exist, do not create new ones, just
      * ignore actual argument
      */
@@ -341,7 +336,7 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
         return;
 
     /* Find stack offset for this argument */
-    off = m_minOff;
+    int off = m_minOff;
     size_t i=0;
     for(STKSYM &s : *this) // walk formal arguments upto numArg_
     {
@@ -353,7 +348,6 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
 
     /* Find formal argument */
     //psym = &at(numArg_);
-    //i = numArg_;
         //auto iter=std::find_if(sym.begin(),sym.end(),[off](STKSYM &s)->bool {s.off==off;});
     auto iter=std::find_if(begin()+numArg_,end(),[off](STKSYM &s)->bool {return s.label==off;});
     if(iter==end()) // symbol not found
@@ -361,15 +355,16 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
         psym = &(*iter);
 
     forType = psym->type;
-    if (forType != actType_)
-    {
+    if (forType == actType_)
+        return;
         switch (actType_) {
             case TYPE_UNKNOWN: case TYPE_BYTE_SIGN:
             case TYPE_BYTE_UNSIGN: case TYPE_WORD_SIGN:
             case TYPE_WORD_UNSIGN: case TYPE_RECORD:
                 break;
 
-            case TYPE_LONG_UNSIGN: case TYPE_LONG_SIGN:
+    case TYPE_LONG_UNSIGN:
+    case TYPE_LONG_SIGN:
                 if ((forType == TYPE_WORD_UNSIGN) ||
                         (forType == TYPE_WORD_SIGN) ||
                         (forType == TYPE_UNKNOWN))
@@ -395,6 +390,5 @@ void STKFRAME::adjustForArgType(size_t numArg_, hlType actType_)
             default:
                 fprintf(stderr,"STKFRAME::adjustForArgType unhandled actType_ %d \n",actType_);
         } /* eos */
-    }
 }
 

+ 2 - 1
src/project.cpp

@@ -1,10 +1,11 @@
 #include <utility>
 #include "dcc.h"
+#include "CallGraph.h"
 #include "project.h"
 #include "Procedure.h"
 using namespace std;
 //Project g_proj;
-char    *asm1_name, *asm2_name;     /* Assembler output filenames     */
+string asm1_name, asm2_name;     /* Assembler output filenames     */
 SYMTAB  symtab;             /* Global symbol table      			  */
 STATS   stats;              /* cfg statistics       				  */
 //PROG    prog;               /* programs fields      				  */