Merge change 1627

* changes:
  Add stub Arm code generator.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 0f8e606..13a863f 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -30,7 +30,6 @@
 namespace acc {
 
 class compiler {
-
     class CodeBuf {
         char* ind;
         char* pProgramBase;
@@ -116,12 +115,60 @@
         CodeGenerator() {}
         virtual ~CodeGenerator() {}
 
-        void init(CodeBuf* pCodeBuf) {
+        virtual void init(CodeBuf* pCodeBuf) {
             this->pCodeBuf = pCodeBuf;
         }
 
+        /* returns address to patch with local variable size
+        */
+        virtual int functionEntry() = 0;
+
+        virtual void functionExit() = 0;
+
+        /* load immediate value */
+        virtual int li(int t) = 0;
+
+        virtual int gjmp(int t) = 0;
+
+        /* l = 0: je, l == 1: jne */
+        virtual int gtst(bool l, int t) = 0;
+
+        virtual void gcmp(int op) = 0;
+
+        virtual int genOp(int op) = 0;
+
+        virtual void clearECX() = 0;
+
+        virtual void pushEAX() = 0;
+
+        virtual void popECX() = 0;
+
+        virtual void storeEAXToAddressECX(bool isInt) = 0;
+
+        virtual void loadEAXIndirect(bool isInt) = 0;
+
+        virtual void leaEAX(int ea) = 0;
+
+        virtual void storeEAX(int ea) = 0;
+
+        virtual void loadEAX(int ea) = 0;
+
+        virtual void postIncrementOrDecrement(int n, int op) = 0;
+
+        virtual int allocStackSpaceForArgs() = 0;
+
+        virtual void storeEAToArg(int l) = 0;
+
+        virtual int callForward(int symbol) = 0;
+
+        virtual void callRelative(int t) = 0;
+
+        virtual void callIndirect(int l) = 0;
+
+        virtual void adjustStackAfterCall(int l) = 0;
+
         /* output a symbol and patch all calls to it */
-        void gsym(int t) {
+        virtual void gsym(int t) {
             pCodeBuf->gsym(t);
         }
 
@@ -156,6 +203,157 @@
         CodeBuf* pCodeBuf;
     };
 
+    class ARMCodeGenerator : public CodeGenerator {
+    public:
+        ARMCodeGenerator() {}
+        virtual ~ARMCodeGenerator() {}
+
+        /* returns address to patch with local variable size
+        */
+        virtual int functionEntry() {
+            fprintf(stderr, "functionEntry();\n");
+            o(0xe58955); /* push   %ebp, mov %esp, %ebp */
+            return oad(0xec81, 0); /* sub $xxx, %esp */
+        }
+
+        virtual void functionExit() {
+            fprintf(stderr, "functionExit();\n");
+            o(0xc3c9); /* leave, ret */
+        }
+
+        /* load immediate value */
+        virtual int li(int t) {
+            fprintf(stderr, "li(%d);\n", t);
+            oad(0xb8, t); /* mov $xx, %eax */
+        }
+
+        virtual int gjmp(int t) {
+            fprintf(stderr, "gjmp(%d);\n", t);
+            return psym(0xe9, t);
+        }
+
+        /* l = 0: je, l == 1: jne */
+        virtual int gtst(bool l, int t) {
+            fprintf(stderr, "gtst(%d, %d);\n", l, t);
+            o(0x0fc085); /* test %eax, %eax, je/jne xxx */
+            return psym(0x84 + l, t);
+        }
+
+        virtual void gcmp(int op) {
+            fprintf(stderr, "gcmp(%d);\n", op);
+#if 0
+            int t = decodeOp(op);
+            o(0xc139); /* cmp %eax,%ecx */
+            li(0);
+            o(0x0f); /* setxx %al */
+            o(t + 0x90);
+            o(0xc0);
+#endif
+        }
+
+        virtual int genOp(int op) {
+            fprintf(stderr, "genOp(%d);\n", op);
+#if 0
+            o(decodeOp(op));
+            if (op == OP_MOD)
+                o(0x92); /* xchg %edx, %eax */
+#endif
+        }
+
+        virtual void clearECX() {
+            fprintf(stderr, "clearECX();\n");
+            oad(0xb9, 0); /* movl $0, %ecx */
+        }
+
+        virtual void pushEAX() {
+            fprintf(stderr, "pushEAX();\n");
+            o(0x50); /* push %eax */
+        }
+
+        virtual void popECX() {
+            fprintf(stderr, "popECX();\n");
+            o(0x59); /* pop %ecx */
+        }
+
+        virtual void storeEAXToAddressECX(bool isInt) {
+            fprintf(stderr, "storeEAXToAddressECX(%d);\n", isInt);
+            o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */
+        }
+
+        virtual void loadEAXIndirect(bool isInt) {
+            fprintf(stderr, "loadEAXIndirect(%d);\n", isInt);
+            if (isInt)
+                o(0x8b); /* mov (%eax), %eax */
+            else
+                o(0xbe0f); /* movsbl (%eax), %eax */
+            ob(0); /* add zero in code */
+        }
+
+        virtual void leaEAX(int ea) {
+            fprintf(stderr, "leaEAX(%d);\n", ea);
+#if 0
+            gmov(10, ea); /* leal EA, %eax */
+#endif
+        }
+
+        virtual void storeEAX(int ea) {
+            fprintf(stderr, "storeEAX(%d);\n", ea);
+#if 0
+            gmov(6, ea); /* mov %eax, EA */
+#endif
+        }
+
+        virtual void loadEAX(int ea) {
+            fprintf(stderr, "loadEAX(%d);\n", ea);
+#if 0
+            gmov(8, ea); /* mov EA, %eax */
+#endif
+        }
+
+        virtual void postIncrementOrDecrement(int n, int op) {
+            fprintf(stderr, "postIncrementOrDecrement(%d, %d);\n", n, op);
+            /* Implement post-increment or post decrement.
+             */
+#if 0
+            gmov(0, n); /* 83 ADD */
+            o(decodeOp(op));
+#endif
+        }
+
+        virtual int allocStackSpaceForArgs() {
+            fprintf(stderr, "allocStackSpaceForArgs();\n");
+            return oad(0xec81, 0); /* sub $xxx, %esp */
+        }
+
+        virtual void storeEAToArg(int l) {
+            fprintf(stderr, "storeEAToArg(%d);\n", l);
+            oad(0x248489, l); /* movl %eax, xxx(%esp) */
+        }
+
+        virtual int callForward(int symbol) {
+            fprintf(stderr, "callForward(%d);\n", symbol);
+            return psym(0xe8, symbol); /* call xxx */
+        }
+
+        virtual void callRelative(int t) {
+            fprintf(stderr, "callRelative(%d);\n", t);
+            psym(0xe8, t); /* call xxx */
+        }
+
+        virtual void callIndirect(int l) {
+            fprintf(stderr, "callIndirect(%d);\n", l);
+            oad(0x2494ff, l); /* call *xxx(%esp) */
+        }
+
+        virtual void adjustStackAfterCall(int l) {
+            fprintf(stderr, "adjustStackAfterCall(%d);\n", l);
+            oad(0xc481, l); /* add $xxx, %esp */
+        }
+
+    private:
+
+    };
+
     class X86CodeGenerator : public CodeGenerator {
     public:
         X86CodeGenerator() {}
@@ -163,31 +361,31 @@
 
         /* returns address to patch with local variable size
         */
-        int functionEntry() {
+        virtual int functionEntry() {
             o(0xe58955); /* push   %ebp, mov %esp, %ebp */
             return oad(0xec81, 0); /* sub $xxx, %esp */
         }
 
-        void functionExit() {
+        virtual void functionExit() {
             o(0xc3c9); /* leave, ret */
         }
 
         /* load immediate value */
-        int li(int t) {
+        virtual int li(int t) {
             oad(0xb8, t); /* mov $xx, %eax */
         }
 
-        int gjmp(int t) {
+        virtual int gjmp(int t) {
             return psym(0xe9, t);
         }
 
         /* l = 0: je, l == 1: jne */
-        int gtst(int l, int t) {
+        virtual int gtst(bool l, int t) {
             o(0x0fc085); /* test %eax, %eax, je/jne xxx */
             return psym(0x84 + l, t);
         }
 
-        int gcmp(int op) {
+        virtual void gcmp(int op) {
             int t = decodeOp(op);
             o(0xc139); /* cmp %eax,%ecx */
             li(0);
@@ -196,29 +394,29 @@
             o(0xc0);
         }
 
-        int genOp(int op) {
+        virtual int genOp(int op) {
             o(decodeOp(op));
             if (op == OP_MOD)
                 o(0x92); /* xchg %edx, %eax */
         }
 
-        void clearECX() {
+        virtual void clearECX() {
             oad(0xb9, 0); /* movl $0, %ecx */
         }
 
-        void pushEAX() {
+        virtual void pushEAX() {
             o(0x50); /* push %eax */
         }
 
-        void popECX() {
+        virtual void popECX() {
             o(0x59); /* pop %ecx */
         }
 
-        void storeEAXToAddressECX(bool isInt) {
+        virtual void storeEAXToAddressECX(bool isInt) {
             o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */
         }
 
-        void loadEAXIndirect(bool isInt) {
+        virtual void loadEAXIndirect(bool isInt) {
             if (isInt)
                 o(0x8b); /* mov (%eax), %eax */
             else
@@ -226,46 +424,46 @@
             ob(0); /* add zero in code */
         }
 
-        void leaEAX(int ea) {
+        virtual void leaEAX(int ea) {
             gmov(10, ea); /* leal EA, %eax */
         }
 
-        void storeEAX(int ea) {
+        virtual void storeEAX(int ea) {
             gmov(6, ea); /* mov %eax, EA */
         }
 
-        void loadEAX(int ea) {
+        virtual void loadEAX(int ea) {
             gmov(8, ea); /* mov EA, %eax */
         }
 
-        void postIncrementOrDecrement(int n, int op) {
+        virtual void postIncrementOrDecrement(int n, int op) {
             /* Implement post-increment or post decrement.
              */
             gmov(0, n); /* 83 ADD */
             o(decodeOp(op));
         }
 
-        int allocStackSpaceForArgs() {
+        virtual int allocStackSpaceForArgs() {
             return oad(0xec81, 0); /* sub $xxx, %esp */
         }
 
-        void storeEAToArg(int l) {
+        virtual void storeEAToArg(int l) {
             oad(0x248489, l); /* movl %eax, xxx(%esp) */
         }
 
-        int callForward(int symbol) {
+        virtual int callForward(int symbol) {
             return psym(0xe8, symbol); /* call xxx */
         }
 
-        void callRelative(int t) {
+        virtual void callRelative(int t) {
             psym(0xe8, t); /* call xxx */
         }
 
-        void callIndirect(int l) {
+        virtual void callIndirect(int l) {
             oad(0x2494ff, l); /* call *xxx(%esp) */
         }
 
-        void adjustStackAfterCall(int l) {
+        virtual void adjustStackAfterCall(int l) {
             oad(0xc481, l); /* add $xxx, %esp */
         }
 
@@ -303,7 +501,7 @@
     FILE* file;
 
     CodeBuf codeBuf;
-    X86CodeGenerator* pGen;
+    CodeGenerator* pGen;
 
     static const int ALLOC_SIZE = 99999;
 
@@ -853,7 +1051,33 @@
         pGen = 0;
     }
 
+    void setArchitecture(const char* architecture) {
+        delete pGen;
+        pGen = 0;
+
+        if (architecture != NULL) {
+            if (strcmp(architecture, "arm") == 0) {
+                pGen = new ARMCodeGenerator();
+            } else if (strcmp(architecture, "x86") == 0) {
+                pGen = new X86CodeGenerator();
+            } else {
+                fprintf(stderr, "Unknown architecture %s", architecture);
+            }
+        }
+
+        if (pGen == NULL) {
+            pGen = new ARMCodeGenerator();
+        }
+    }
+
 public:
+    struct args {
+        args() {
+            architecture = 0;
+        }
+        const char* architecture;
+    };
+
     compiler() {
         clear();
     }
@@ -862,11 +1086,11 @@
         cleanup();
     }
 
-    int compile(FILE* in) {
+    int compile(FILE* in, args& args) {
         cleanup();
         clear();
         codeBuf.init(ALLOC_SIZE);
-        pGen = new X86CodeGenerator();
+        setArchitecture(args.architecture);
         pGen->init(&codeBuf);
         file = in;
         sym_stk = (int) calloc(1, ALLOC_SIZE);
@@ -939,20 +1163,29 @@
 } // namespace acc
 
 int main(int argc, char** argv) {
-    bool doTest = false;
+    bool doDump = false;
     const char* inFile = NULL;
     const char* outFile = NULL;
+    const char* architecture = "arm";
     int i;
     for (i = 1; i < argc; i++) {
         char* arg = argv[i];
         if (arg[0] == '-') {
             switch (arg[1]) {
-            case 'T':
+            case 'a':
                 if (i + 1 >= argc) {
-                    fprintf(stderr, "Expected filename after -T\n");
+                    fprintf(stderr, "Expected architecture after -a\n");
                     return 2;
                 }
-                doTest = true;
+                architecture = argv[i+1];
+                i += 1;
+                break;
+            case 'd':
+                if (i + 1 >= argc) {
+                    fprintf(stderr, "Expected filename after -d\n");
+                    return 2;
+                }
+                doDump = true;
                 outFile = argv[i + 1];
                 i += 1;
                 break;
@@ -976,7 +1209,9 @@
         }
     }
     acc::compiler compiler;
-    int compileResult = compiler.compile(in);
+    acc::compiler::args args;
+    args.architecture = architecture;
+    int compileResult = compiler.compile(in, args);
     if (in != stdin) {
         fclose(in);
     }
@@ -984,7 +1219,7 @@
         fprintf(stderr, "Compile failed: %d\n", compileResult);
         return 6;
     }
-    if (doTest) {
+    if (doDump) {
         FILE* save = fopen(outFile, "w");
         if (!save) {
             fprintf(stderr, "Could not open output file %s\n", outFile);
@@ -997,7 +1232,9 @@
         int codeArgc = argc - i + 1;
         char** codeArgv = argv + i - 1;
         codeArgv[0] = (char*) (inFile ? inFile : "stdin");
-        return compiler.run(codeArgc, codeArgv);
+        int result = compiler.run(codeArgc, codeArgv);
+        fprintf(stderr, "result: %d\n", result);
+        return result;
     }
 
     return 0;
diff --git a/libacc/test b/libacc/test
index 17d7b55..be883a6 100755
--- a/libacc/test
+++ b/libacc/test
@@ -1,2 +1,3 @@
 #!/bin/sh
-g++ acc.cpp -ldl -o tests/acc && tests/acc tests/otcc.c -T tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig
+g++ acc.cpp -ldl -o tests/acc && tests/acc tests/otcc.c -a x86 -d tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig
+tests/acc tests/simplest.c
diff --git a/libacc/tests/simplest.c b/libacc/tests/simplest.c
new file mode 100644
index 0000000..bae895a
--- /dev/null
+++ b/libacc/tests/simplest.c
@@ -0,0 +1 @@
+main() {}