Merge change 7048

* changes:
  Implement general casts and pointer dereferencing.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 219a436..fb7ec80 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -1019,6 +1019,7 @@
             LOG_API("storeR0(%d);\n", ea);
             TypeTag tag = pType->tag;
             switch (tag) {
+                case TY_POINTER:
                 case TY_INT:
                 case TY_FLOAT:
                     if (ea > -LOCAL && ea < LOCAL) {
@@ -2027,6 +2028,7 @@
             TypeTag tag = pType->tag;
             switch (tag) {
                 case TY_INT:
+                case TY_POINTER:
                     gmov(6, ea); /* mov %eax, EA */
                     break;
                 case TY_FLOAT:
@@ -3663,41 +3665,34 @@
                     pGen->genUnaryOp(a);
                 }
             } else if (t == '(') {
-                expr();
-                skip(')');
-            } else if (t == '*') {
-                /* This is a pointer dereference, but we currently only
-                 * support a pointer dereference if it's immediately
-                 * in front of a cast. So parse the cast right here.
-                 */
-                skip('(');
-                Type* pCast = expectCastTypeDeclaration(mLocalArena);
-                // We currently only handle 3 types of cast:
-                // (int*), (char*) , (int (*)())
-                if(typeEqual(pCast, mkpIntPtr)) {
-                    t = TOK_INT;
-                } else if (typeEqual(pCast, mkpCharPtr)) {
-                    t = TOK_CHAR;
-                } else if (typeEqual(pCast, mkpFloatPtr)) {
-                    t = TOK_FLOAT;
-                } else if (typeEqual(pCast, mkpDoublePtr)) {
-                    t = TOK_DOUBLE;
-                } else if (typeEqual(pCast, mkpPtrIntFn)){
-                    t = 0;
+                // It's either a cast or an expression
+                Type* pCast = acceptCastTypeDeclaration(mLocalArena);
+                if (pCast) {
+                    skip(')');
+                    unary(false);
+                    pGen->convertR0(pCast);
                 } else {
-                    String buffer;
-                    decodeType(buffer, pCast);
-                    error("Unsupported cast type %s", buffer.getUnwrapped());
-                    decodeType(buffer, mkpPtrIntFn);
-                }
-                skip(')');
-                unary(false);
-                if (accept('=')) {
-                    pGen->pushR0();
                     expr();
-                    pGen->storeR0ToTOS(pCast);
-                } else if (t) {
-                    pGen->loadR0FromR0(pCast);
+                    skip(')');
+                }
+            } else if (t == '*') {
+                /* This is a pointer dereference.
+                 */
+                unary(false);
+                Type* pR0Type = pGen->getR0Type();
+                if (pR0Type->tag != TY_POINTER) {
+                    error("Expected a pointer type.");
+                } else {
+                    if (pR0Type->pHead->tag == TY_FUNC) {
+                        t = 0;
+                    }
+                    if (accept('=')) {
+                        pGen->pushR0();
+                        expr();
+                        pGen->storeR0ToTOS(pR0Type);
+                    } else if (t) {
+                        pGen->loadR0FromR0(pR0Type);
+                    }
                 }
                 // Else we fall through to the function call below, with
                 // t == 0 to trigger an indirect function call. Hack!
diff --git a/libacc/tests/data/casts.c b/libacc/tests/data/casts.c
new file mode 100644
index 0000000..d3a49b4
--- /dev/null
+++ b/libacc/tests/data/casts.c
@@ -0,0 +1,85 @@
+void test1() {
+    int a = 3;
+    int* pb = &a;
+    int c = *pb;
+    printf("Reading from a pointer: %d %d\n", a, c);
+    *pb = 4;
+    printf("Writing to a pointer: %d\n", a);
+    printf("Testing casts: %d %g %g %d\n", 3, (float) 3, 4.5, (int) 4.5);
+}
+
+void test2() {
+    int x = 4;
+    int px = &x;
+    // int z = * px; // An error, expected a pointer type
+    int y = * (int*) px;
+    printf("Testing reading (int*): %d\n", y);
+}
+
+void test3() {
+    int px = (int) malloc(120);
+    * (int*) px = 8;
+    * (int*) (px + 4) = 9;
+    printf("Testing writing (int*): %d %d\n", * (int*) px, * (int*) (px + 4));
+    free((void*) px);
+}
+
+void test4() {
+    int x = 0x12345678;
+    int px = &x;
+    int a = * (char*) px;
+    int b = * (char*) (px + 1);
+    int c = * (char*) (px + 2);
+    int d = * (char*) (px + 3);
+    printf("Testing reading (char*): 0x%02x 0x%02x 0x%02x 0x%02x\n", a, b, c, d);
+}
+
+void test5() {
+    int x = 0xFFFFFFFF;
+    int px = &x;
+    * (char*) px = 0x21;
+    * (char*) (px + 1) = 0x43;
+    * (char*) (px + 2) = 0x65;
+    * (char*) (px + 3) = 0x87;
+    printf("Testing writing (char*): 0x%08x\n", x);
+}
+
+int f(int b) {
+    printf("f(%d)\n", b);
+    return 7 * b;
+}
+
+void test6() {
+    int fp = &f;
+    int x = (*(int(*)()) fp)(10);
+    printf("Function pointer result: %d\n", x);
+}
+
+void test7() {
+    int px = (int) malloc(120);
+    * (float*) px = 8.8f;
+    * (float*) (px + 4) = 9.9f;
+    printf("Testing read/write (float*): %g %g\n", * (float*) px, * (float*) (px + 4));
+    free((void*) px);
+}
+
+void test8() {
+    int px = (int) malloc(120);
+    * (double*) px = 8.8;
+    * (double*) (px + 8) = 9.9;
+    printf("Testing read/write (double*): %g %g\n", * (double*) px, * (double*) (px + 8));
+    free((void*) px);
+}
+
+
+int main() {
+    test1();
+    test2();
+    test3();
+    test4();
+    test5();
+    test6();
+    test7();
+    test8();
+    return 0;
+}
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index 991c7de..702f49d 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -77,7 +77,14 @@
             return i
     return commonLen
 
-def compareSet(a1,a2,b1,b2):
+# a1 and a2 are the expected stdout and stderr.
+# b1 and b2 are the actual stdout and stderr.
+# Compare the two, sets. Allow any individual line
+# to appear in either stdout or stderr. This is because
+# the way we obtain output on the ARM combines both
+# streams into one sequence.
+
+def compareOuput(a1,a2,b1,b2):
     while True:
         totalLen = len(a1) + len(a2) + len(b1) + len(b2)
         a1, b1 = matchCommon(a1, b1)
@@ -96,6 +103,8 @@
             return False
 
 def matchCommon(a, b):
+    """Remove common items from the beginning of a and b,
+       return just the tails that are different."""
     while len(a) > 0 and len(b) > 0 and a[0] == b[0]:
         a = a[1:]
         b = b[1:]
@@ -105,25 +114,20 @@
     return [rewritePath(x) for x in args]
 
 def rewritePath(p):
+    """Take a path that's correct on the x86 and convert to a path
+       that's correct on ARM."""
     if p.startswith("data/"):
         p = "/system/bin/accdata/" + p
     return p
 
 class TestACC(unittest.TestCase):
- 
-    def compileCheckOld(self, args, stdErrResult, stdOutResult=""):
-        out, err = compile(args)
-        compare(out, stdOutResult)
-        compare(err, stdErrResult)
-        self.assertEqual(out, stdOutResult)
-        self.assertEqual(err, stdErrResult)
 
     def checkResult(self, out, err, stdErrResult, stdOutResult=""):
         a1 = out.splitlines()
         a2 = err.splitlines()
         b2 = stdErrResult.splitlines()
         b1 = stdOutResult.splitlines()
-        self.assertEqual(True, compareSet(a1,a2,b1,b2))
+        self.assertEqual(True, compareOuput(a1,a2,b1,b2))
         
     def compileCheck(self, args, stdErrResult, stdOutResult="",
                      targets=['arm', 'x86']):
@@ -174,65 +178,77 @@
         
     def testRunFlops(self):
         self.compileCheck(["-R", "data/flops.c"],
-            "Executing compiled code:\nresult: 0\n",
-            "-1.1 = -1.1\n" +
-            "!1.2 = 0\n" +
-            "!0 = 1\n" +
-            "double op double:\n" +
-            "1 + 2 = 3\n" +
-            "1 - 2 = -1\n" +
-            "1 * 2 = 2\n" +
-            "1 / 2 = 0.5\n" +
-            "float op float:\n" +
-            "1 + 2 = 3\n" +
-            "1 - 2 = -1\n" +
-            "1 * 2 = 2\n" +
-            "1 / 2 = 0.5\n" +
-            "double op float:\n" +
-            "1 + 2 = 3\n" +
-            "1 - 2 = -1\n" +
-            "1 * 2 = 2\n" +
-            "1 / 2 = 0.5\n" +
-            "double op int:\n" +
-            "1 + 2 = 3\n" +
-            "1 - 2 = -1\n" +
-            "1 * 2 = 2\n" +
-            "1 / 2 = 0.5\n" +
-            "int op double:\n" +
-            "1 + 2 = 3\n" +
-            "1 - 2 = -1\n" +
-            "1 * 2 = 2\n" +
-            "1 / 2 = 0.5\n" +
-            "double op double:\n" +
-            "1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1\n" +
-            "1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0\n" +
-            "2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1\n" +
-            "double op float:\n" +
-            "1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1\n" +
-            "1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0\n" +
-            "2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1\n" +
-            "float op float:\n" +
-            "1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1\n" +
-            "1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0\n" +
-            "2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1\n" +
-            "int op double:\n" +
-            "1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1\n" +
-            "1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0\n" +
-            "2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1\n" +
-            "double op int:\n" +
-            "1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1\n" +
-            "1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0\n" +
-            "2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1\n" +
-            "branching: 1 0 1\n" +
-            "testpassi: 1 2 3 4 5 6 7 8\n" +
-            "testpassf: 1 2 3 4 5 6 7 8\n" +
-            "testpassd: 1 2 3 4 5 6 7 8\n" +
-            "testpassidf: 1 2 3\n"
-            )
-        
-    def oldtestArmRunReturnVal(self):
-        self.compileCheckArm(["-R", "/system/bin/accdata/data/returnval-ansi.c"],
-            "Executing compiled code:\nresult: 42\n")
+            """Executing compiled code:
+result: 0""",
+"""-1.1 = -1.1
+!1.2 = 0
+!0 = 1
+double op double:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+float op float:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+double op float:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+double op int:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+int op double:
+1 + 2 = 3
+1 - 2 = -1
+1 * 2 = 2
+1 / 2 = 0.5
+double op double:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+double op float:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+float op float:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+int op double:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+double op int:
+1 op 2: < 1   <= 1   == 0   >= 0   > 0   != 1
+1 op 1: < 0   <= 1   == 1   >= 1   > 0   != 0
+2 op 1: < 0   <= 0   == 0   >= 1   > 1   != 1
+branching: 1 0 1
+testpassi: 1 2 3 4 5 6 7 8
+testpassf: 1 2 3 4 5 6 7 8
+testpassd: 1 2 3 4 5 6 7 8
+testpassidf: 1 2 3
+""")
+    def testCasts(self):
+        self.compileCheck(["-R", "data/casts.c"],
+            """Executing compiled code:
+result: 0""", """Reading from a pointer: 3 3
+Writing to a pointer: 4
+Testing casts: 3 3 4.5 4
+Testing reading (int*): 4
+Testing writing (int*): 8 9
+Testing reading (char*): 0x78 0x56 0x34 0x12
+Testing writing (char*): 0x87654321
+f(10)
+Function pointer result: 70
+Testing read/write (float*): 8.8 9.9
+Testing read/write (double*): 8.8 9.9
+""")
 
 if __name__ == '__main__':
     if not outputCanRun():