Merge change 2096

* changes:
  Implement architecture-dependent defaults.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 567e25e..cefe01d 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -1,4 +1,15 @@
 /*
+ * Android "Almost" C Compiler.
+ * This is a compiler for a small subset of the C language, intended for use
+ * in scripting environments where speed and memory footprint are important.
+ *
+ * This code is based upon the "unobfuscated" version of the
+ * Obfuscated Tiny C compiler, and retains the
+ * original copyright notice and license from that compiler, see below.
+ *
+ */
+
+/*
  Obfuscated Tiny C Compiler
 
  Copyright (C) 2001-2003 Fabrice Bellard
@@ -31,11 +42,24 @@
 #include <unistd.h>
 #endif
 
+#if defined(__arm__)
+#define DEFAULT_ARM_CODEGEN
+#elif defined(__i386__)
+#define DEFAULT_X86_CODEGEN
+#elif defined(__x86_64__)
+#define DEFAULT_X64_CODEGEN
+#endif
+
+#define PROVIDE_X86_CODEGEN
+#define PROVIDE_ARM_CODEGEN
+
+#ifdef PROVIDE_ARM_CODEGEN
 #include "disassem.h"
+#endif
 
 namespace acc {
 
-class compiler {
+class Compiler {
     class CodeBuf {
         char* ind;
         char* pProgramBase;
@@ -63,14 +87,6 @@
             ind = pProgramBase;
         }
 
-        void o(int n) {
-            /* cannot use unsigned, so we must do a hack */
-            while (n && n != -1) {
-                *ind++ = n;
-                n = n >> 8;
-            }
-        }
-
         int o4(int n) {
             int result = (int) ind;
             * (int*) ind = n;
@@ -85,31 +101,6 @@
             *ind++ = n;
         }
 
-        /* output a symbol and patch all calls to it */
-        void gsym(int t) {
-            int n;
-            while (t) {
-                n = *(int *) t; /* next value */
-                *(int *) t = ((int) ind) - t - 4;
-                t = n;
-            }
-        }
-
-        /* psym is used to put an instruction with a data field which is a
-         reference to a symbol. It is in fact the same as oad ! */
-        int psym(int n, int t) {
-            return oad(n, t);
-        }
-
-        /* instruction + address */
-        int oad(int n, int t) {
-            o(n);
-            *(int *) ind = t;
-            t = (int) ind;
-            ind = ind + 4;
-            return t;
-        }
-
         inline void* getBase() {
             return (void*) pProgramBase;
         }
@@ -184,9 +175,7 @@
         virtual int disassemble(FILE* out) = 0;
 
         /* output a symbol and patch all calls to it */
-        virtual void gsym(int t) {
-            pCodeBuf->gsym(t);
-        }
+        virtual void gsym(int t) = 0;
 
         virtual int finishCompile() {
 #if defined(__arm__)
@@ -205,10 +194,6 @@
         virtual int jumpOffset() = 0;
 
     protected:
-        void o(int n) {
-            pCodeBuf->o(n);
-        }
-
         /*
          * Output a byte. Handles all values, 0..ff.
          */
@@ -216,15 +201,8 @@
             pCodeBuf->ob(n);
         }
 
-        /* psym is used to put an instruction with a data field which is a
-         reference to a symbol. It is in fact the same as oad ! */
-        int psym(int n, int t) {
-            return oad(n, t);
-        }
-
-        /* instruction + address */
-        int oad(int n, int t) {
-            return pCodeBuf->oad(n,t);
+        int o4(int data) {
+            return pCodeBuf->o4(data);
         }
 
         int getBase() {
@@ -234,14 +212,12 @@
         int getPC() {
             return pCodeBuf->getPC();
         }
-
-        int o4(int data) {
-            return pCodeBuf->o4(data);
-        }
     private:
         CodeBuf* pCodeBuf;
     };
 
+#ifdef PROVIDE_ARM_CODEGEN
+
     class ARMCodeGenerator : public CodeGenerator {
     public:
         ARMCodeGenerator() {}
@@ -701,6 +677,10 @@
         }
     };
 
+#endif // PROVIDE_X86_CODEGEN
+
+#ifdef PROVIDE_X86_CODEGEN
+
     class X86CodeGenerator : public CodeGenerator {
     public:
         X86CodeGenerator() {}
@@ -829,7 +809,45 @@
             return 1;
         }
 
+        /* output a symbol and patch all calls to it */
+        virtual void gsym(int t) {
+            int n;
+            int pc = getPC();
+            while (t) {
+                n = *(int *) t; /* next value */
+                *(int *) t = pc - t - 4;
+                t = n;
+            }
+        }
+
     private:
+
+        /** Output 1 to 4 bytes.
+         *
+         */
+        void o(int n) {
+            /* cannot use unsigned, so we must do a hack */
+            while (n && n != -1) {
+                ob(n & 0xff);
+                n = n >> 8;
+            }
+        }
+
+        /* psym is used to put an instruction with a data field which is a
+         reference to a symbol. It is in fact the same as oad ! */
+        int psym(int n, int t) {
+            return oad(n, t);
+        }
+
+        /* instruction + address */
+        int oad(int n, int t) {
+            o(n);
+            int result = getPC();
+            o4(t);
+            return result;
+        }
+
+
         static const int operatorHelper[];
 
         int decodeOp(int op) {
@@ -846,6 +864,8 @@
         }
     };
 
+#endif // PROVIDE_X86_CODEGEN
+
     /* vars: value of variables
      loc : local variable index
      glo : global variable index
@@ -1426,16 +1446,31 @@
 
         if (architecture != NULL) {
             if (strcmp(architecture, "arm") == 0) {
+#ifdef PROVIDE_ARM_CODEGEN
                 pGen = new ARMCodeGenerator();
+#else
+                fprintf(stderr, "Unsupported architecture %s", architecture);
+#endif
             } else if (strcmp(architecture, "x86") == 0) {
+#ifdef PROVIDE_X86_CODEGEN
                 pGen = new X86CodeGenerator();
+#else
+                fprintf(stderr, "Unsupported architecture %s", architecture);
+#endif
             } else {
                 fprintf(stderr, "Unknown architecture %s", architecture);
             }
         }
 
         if (pGen == NULL) {
+#if defined(DEFAULT_ARM_CODEGEN)
             pGen = new ARMCodeGenerator();
+#elif defined(DEFAULT_X86_CODEGEN)
+            pGen = new X86CodeGenerator();
+#endif
+        }
+        if (pGen == NULL) {
+            fprintf(stderr, "No code generator defined.");
         }
     }
 
@@ -1447,11 +1482,11 @@
         const char* architecture;
     };
 
-    compiler() {
+    Compiler() {
         clear();
     }
 
-    ~compiler() {
+    ~Compiler() {
         cleanup();
     }
 
@@ -1498,10 +1533,10 @@
 
 };
 
-const char* compiler::operatorChars =
+const char* Compiler::operatorChars =
     "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@";
 
-const char compiler::operatorLevel[] =
+const char Compiler::operatorLevel[] =
     {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4,
             5, 5, /* ==, != */
             9, 10, /* &&, || */
@@ -1509,9 +1544,9 @@
             2, 2 /* ~ ! */
             };
 
-FILE* compiler::ARMCodeGenerator::disasmOut;
+FILE* Compiler::ARMCodeGenerator::disasmOut;
 
-const int compiler::X86CodeGenerator::operatorHelper[] = {
+const int Compiler::X86CodeGenerator::operatorHelper[] = {
         0x1,     // ++
         0xff,    // --
         0xc1af0f, // *
@@ -1539,7 +1574,7 @@
 } // namespace acc
 
 // This is a separate function so it can easily be set by breakpoint in gdb.
-int run(acc::compiler& c, int argc, char** argv) {
+int run(acc::Compiler& c, int argc, char** argv) {
     return c.run(argc, argv);
 }
 
@@ -1548,7 +1583,7 @@
     bool doDisassemble = false;
     const char* inFile = NULL;
     const char* outFile = NULL;
-    const char* architecture = "arm";
+    const char* architecture = NULL;
     int i;
     for (i = 1; i < argc; i++) {
         char* arg = argv[i];
@@ -1593,9 +1628,11 @@
             return 1;
         }
     }
-    acc::compiler compiler;
-    acc::compiler::args args;
-    args.architecture = architecture;
+    acc::Compiler compiler;
+    acc::Compiler::args args;
+    if (architecture != NULL) {
+        args.architecture = architecture;
+    }
     int compileResult = compiler.compile(in, args);
     if (in != stdin) {
         fclose(in);
diff --git a/libacc/test b/libacc/test
index 0b767da..28b7655 100755
--- a/libacc/test
+++ b/libacc/test
@@ -1,3 +1,13 @@
 #!/bin/sh
+rm -f tests/acc
 g++ acc.cpp disassem.cpp -g -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 -S tests/returnval.c
+if [ -x "tests/acc" ]; then
+  tests/acc -S tests/returnval.c
+
+  if [ "$(uname)" = "Linux" ]; then
+    if [ "$(uname -m)" = "i686" ]; then
+      echo "Linux i686. Testing otcc.c"
+      tests/acc tests/otcc.c tests/otcc.c tests/returnval.c
+    fi
+  fi
+fi