Merge commit 'goog/master' into merge_master
diff --git a/adb/services.c b/adb/services.c
index 0a5edcf..b99cca1 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -33,6 +33,10 @@
 #  endif
 #endif
 
+#ifndef HAVE_WIN32_PROC
+#include <sys/poll.h>
+#endif
+
 typedef struct stinfo stinfo;
 
 struct stinfo {
@@ -199,8 +203,8 @@
 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
 {
 #ifdef HAVE_WIN32_PROC
-	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
-	return -1;
+    fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
+    return -1;
 #else /* !HAVE_WIN32_PROC */
     char *devname;
     int ptm;
@@ -267,6 +271,54 @@
 #define SHELL_COMMAND "/system/bin/sh"
 #endif
 
+static void shell_service(int s, void *command)
+{
+    char    buffer[MAX_PAYLOAD];
+    int     fd, ret = 0;
+    unsigned count = 0;
+
+    fd = create_subprocess(SHELL_COMMAND, "-c", (char *)command);
+
+    while (1) {
+        while (count < sizeof(buffer)) {
+#ifndef HAVE_WIN32_PROC
+            /* add a 200ms timeout so we don't block indefinitely with our
+               buffer partially filled.
+            */
+            if (count > 0) {
+                struct pollfd pollfd;
+
+                pollfd.fd = fd;
+                pollfd.events = POLLIN;
+                ret = poll(&pollfd, 1, 200);
+                if (ret <= 0) {
+                    D("poll returned %d\n", ret);
+                    // file has closed or we timed out
+                    // set ret to 1 so we don't exit the outer loop
+                    ret = 1;
+                    break;
+                }
+            }
+#endif
+            ret = adb_read(fd, buffer + count, sizeof(buffer) - count);
+            D("ret: %d, count: %d\n", ret, count);
+            if (ret > 0)
+                count += ret;
+            else
+                break;
+        }
+
+        D("writing: %d\n", count);
+        adb_write(s, buffer, count);
+        count = 0;
+        if (ret <= 0)
+            break;
+    }
+
+    adb_close(fd);
+    adb_close(s);
+}
+
 int service_to_fd(const char *name)
 {
     int ret = -1;
@@ -320,7 +372,7 @@
 #endif
     } else if(!HOST && !strncmp(name, "shell:", 6)) {
         if(name[6]) {
-            ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
+            ret = create_service_thread(shell_service, (void *)(name + 6));
         } else {
             ret = create_subprocess(SHELL_COMMAND, "-", 0);
         }
diff --git a/include/acc/acc.h b/include/acc/acc.h
index 054d6a0..e25fde0 100644
--- a/include/acc/acc.h
+++ b/include/acc/acc.h
@@ -69,6 +69,9 @@
 void accGetScriptLabel(ACCscript* script, const ACCchar * name,
                        ACCvoid** address);
 
+void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount,
+                   ACCsizei maxStringCount, ACCchar** strings);
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/include/cutils/ashmem.h b/include/cutils/ashmem.h
index 6e19ad4..fd56dbe 100644
--- a/include/cutils/ashmem.h
+++ b/include/cutils/ashmem.h
@@ -20,6 +20,7 @@
 int ashmem_set_prot_region(int fd, int prot);
 int ashmem_pin_region(int fd, size_t offset, size_t len);
 int ashmem_unpin_region(int fd, size_t offset, size_t len);
+int ashmem_get_size_region(int fd);
 
 #ifdef __cplusplus
 }
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 733f188..de36ce5 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -41,7 +41,6 @@
 
 #define LOG_API(...) do {} while(0)
 // #define LOG_API(...) fprintf (stderr, __VA_ARGS__)
-
 // #define ENABLE_ARM_DISASSEMBLY
 
 namespace acc {
@@ -389,7 +388,7 @@
         /* returns address to patch with local variable size
         */
         virtual int functionEntry(int argCount) {
-            LOG_API(stderr, "functionEntry(%d);\n", argCount);
+            LOG_API("functionEntry(%d);\n", argCount);
             // sp -> arg4 arg5 ...
             // Push our register-based arguments back on the stack
             if (argCount > 0) {
@@ -1039,16 +1038,35 @@
 
     class InputStream {
     public:
+        int getChar() {
+            if (bumpLine) {
+                line++;
+                bumpLine = false;
+            }
+            int ch = get();
+            if (ch == '\n') {
+                bumpLine = true;
+            }
+            return ch;
+        }
+        int getLine() {
+            return line;
+        }
+    protected:
+        InputStream() :
+            line(1), bumpLine(false) {
+        }
+    private:
         virtual int get() = 0;
-        virtual long tell() = 0;
+        int line;
+        bool bumpLine;
     };
 
     class FileInputStream : public InputStream {
     public:
         FileInputStream(FILE* in) : f(in) {}
-        virtual int get() { return fgetc(f); }
-        virtual long tell() { return ftell(f); }
     private:
+        virtual int get() { return fgetc(f); }
         FILE* f;
     };
 
@@ -1057,14 +1075,12 @@
         TextInputStream(const char* text, size_t textLength)
             : pText(text), mTextLength(textLength), mPosition(0) {
         }
+
+    private:
         virtual int get() {
             return mPosition < mTextLength ? pText[mPosition++] : EOF;
         }
-        virtual long tell() {
-            return mPosition;
-        }
 
-    private:
         const char* pText;
         size_t mTextLength;
         size_t mPosition;
@@ -1091,24 +1107,96 @@
     CodeBuf codeBuf;
     CodeGenerator* pGen;
 
-    static const int ERROR_BUF_SIZE = 512;
-    char mErrorBuf[ERROR_BUF_SIZE];
+    class String {
+    public:
+        String() {
+            mpBase = 0;
+            mUsed = 0;
+            mSize = 0;
+        }
+
+        ~String() {
+            if (mpBase) {
+                free(mpBase);
+            }
+        }
+
+        char* getUnwrapped() {
+            return mpBase;
+        }
+
+        void appendCStr(const char* s) {
+            int n = strlen(s);
+            memcpy(ensure(n), s, n + 1);
+        }
+
+        void append(char c) {
+            * ensure(1) = c;
+        }
+
+        void printf(const char* fmt,...) {
+            va_list ap;
+            va_start(ap, fmt);
+            vprintf(fmt, ap);
+            va_end(ap);
+        }
+
+        void vprintf(const char* fmt, va_list ap) {
+            char* temp;
+            int numChars = vasprintf(&temp, fmt, ap);
+            memcpy(ensure(numChars), temp, numChars+1);
+            free(temp);
+        }
+
+        size_t len() {
+            return mUsed;
+        }
+
+    private:
+        char* ensure(int n) {
+            size_t newUsed = mUsed + n;
+            if (newUsed > mSize) {
+                size_t newSize = mSize * 2 + 10;
+                if (newSize < newUsed) {
+                    newSize = newUsed;
+                }
+                mpBase = (char*) realloc(mpBase, newSize + 1);
+                mSize = newSize;
+            }
+            mpBase[newUsed] = '\0';
+            char* result = mpBase + mUsed;
+            mUsed = newUsed;
+            return result;
+        }
+
+        char* mpBase;
+        size_t mUsed;
+        size_t mSize;
+    };
+
+    String mErrorBuf;
+
     jmp_buf mErrorRecoveryJumpBuf;
 
+    String mPragmas;
+    int mPragmaStringCount;
+
     static const int ALLOC_SIZE = 99999;
 
-    /* depends on the init string */
-    static const int TOK_STR_SIZE = 48;
+    // Indentifiers start at 0x100 and increase by # (chars + 1) * 8
     static const int TOK_IDENT = 0x100;
     static const int TOK_INT = 0x100;
-    static const int TOK_IF = 0x120;
-    static const int TOK_ELSE = 0x138;
-    static const int TOK_WHILE = 0x160;
-    static const int TOK_BREAK = 0x190;
-    static const int TOK_RETURN = 0x1c0;
-    static const int TOK_FOR = 0x1f8;
-    static const int TOK_DEFINE = 0x218;
-    static const int TOK_MAIN = 0x250;
+    static const int TOK_CHAR = TOK_INT + 4*8;
+    static const int TOK_VOID = TOK_CHAR + 5*8;
+    static const int TOK_IF = TOK_VOID + 5*8;
+    static const int TOK_ELSE = TOK_IF + 3*8;
+    static const int TOK_WHILE = TOK_ELSE + 5*8;
+    static const int TOK_BREAK = TOK_WHILE + 6*8;
+    static const int TOK_RETURN = TOK_BREAK + 6*8;
+    static const int TOK_FOR = TOK_RETURN + 7*8;
+    static const int TOK_PRAGMA = TOK_FOR + 4*8;
+    static const int TOK_DEFINE = TOK_PRAGMA + 7*8;
+    static const int TOK_MAIN = TOK_DEFINE + 7*8;
 
     static const int TOK_DUMMY = 1;
     static const int TOK_NUM = 2;
@@ -1168,8 +1256,10 @@
                 ch = dch;
             }
         } else
-            ch = file->get();
-        /*    printf("ch=%c 0x%x\n", ch, ch); */
+            ch = file->getChar();
+#if 0
+        printf("ch='%c' 0x%x\n", ch, ch);
+#endif
     }
 
     int isid() {
@@ -1197,14 +1287,18 @@
                     pdef(TAG_TOK); /* fill last ident tag */
                     *(int *) tok = SYM_DEFINE;
                     *(char* *) (tok + 4) = dstk; /* define stack */
-                }
-                /* well we always save the values ! */
-                while (ch != '\n') {
+                    while (ch != '\n') {
+                        pdef(ch);
+                        inp();
+                    }
                     pdef(ch);
-                    inp();
+                    pdef(TAG_MACRO);
+                } else if (tok == TOK_PRAGMA) {
+                    doPragma();
+                } else {
+                    error("Unsupported preprocessor directive \"%s\"", last_id);
                 }
-                pdef(ch);
-                pdef(TAG_MACRO);
+
             }
             inp();
         }
@@ -1321,23 +1415,54 @@
 #endif
     }
 
+    void doPragma() {
+        // # pragma name(val)
+        int state = 0;
+        while(ch != EOF && ch != '\n' && state < 10) {
+            switch(state) {
+                case 0:
+                    if (isspace(ch)) {
+                        inp();
+                    } else {
+                        state++;
+                    }
+                    break;
+                case 1:
+                    if (isalnum(ch)) {
+                        mPragmas.append(ch);
+                        inp();
+                    } else if (ch == '(') {
+                        mPragmas.append(0);
+                        inp();
+                        state++;
+                    } else {
+                        state = 11;
+                    }
+                    break;
+                case 2:
+                    if (isalnum(ch)) {
+                        mPragmas.append(ch);
+                        inp();
+                    } else if (ch == ')') {
+                        mPragmas.append(0);
+                        inp();
+                        state = 10;
+                    } else {
+                        state = 11;
+                    }
+                    break;
+            }
+        }
+        if(state != 10) {
+            error("Unexpected pragma syntax");
+        }
+        mPragmaStringCount += 2;
+    }
 
     virtual void verror(const char* fmt, va_list ap) {
-        char* pBase = mErrorBuf;
-        int bytesLeft = sizeof(mErrorBuf);
-        int bytesAdded = snprintf(pBase, bytesLeft, "%ld: ", file->tell());
-        bytesLeft -= bytesAdded;
-        pBase += bytesAdded;
-        if (bytesLeft > 0) {
-            bytesAdded = vsnprintf(pBase, bytesLeft, fmt, ap);
-            bytesLeft -= bytesAdded;
-            pBase += bytesAdded;
-        }
-        if (bytesLeft > 0) {
-            bytesAdded = snprintf(pBase, bytesLeft, "\n");
-            bytesLeft -= bytesAdded;
-            pBase += bytesAdded;
-        }
+        mErrorBuf.printf("%ld: ", file->getLine());
+        mErrorBuf.vprintf(fmt, ap);
+        mErrorBuf.printf("\n");
         longjmp(mErrorRecoveryJumpBuf, 1);
     }
 
@@ -1563,7 +1688,7 @@
         } else if (tok == '{') {
             next();
             /* declarations */
-            decl(1);
+            localDeclarations();
             while (tok != '}')
                 block(l);
             next();
@@ -1582,36 +1707,125 @@
         }
     }
 
-    /* 'l' is true if local declarations */
-    void decl(bool l) {
-        intptr_t a;
+    typedef int Type;
+    static const Type TY_UNKNOWN = 0;
+    static const Type TY_INT = 1;
+    static const Type TY_CHAR = 2;
+    static const Type TY_VOID = 3;
+    static const int TY_BASE_TYPE_MASK = 0xf;
+    static const int TY_INDIRECTION_MASK = 0xf0;
+    static const int TY_INDIRECTION_SHIFT = 4;
+    static const int MAX_INDIRECTION_COUNT = 15;
 
-        while ((tok == TOK_INT) | ((tok != EOF) & (!l))) {
-            if (tok == TOK_INT) {
+    Type getBaseType(Type t) {
+        return t & TY_BASE_TYPE_MASK;
+    }
+
+    int getIndirectionCount(Type t) {
+        return (TY_INDIRECTION_MASK & t) >> TY_INDIRECTION_SHIFT;
+    }
+
+    void setIndirectionCount(Type& t, int count) {
+        t = ((TY_INDIRECTION_MASK & (count << TY_INDIRECTION_SHIFT))
+                | (t & ~TY_INDIRECTION_MASK));
+    }
+
+    bool acceptType(Type& t) {
+        t = TY_UNKNOWN;
+        if (tok == TOK_INT) {
+            t = TY_INT;
+        } else if (tok == TOK_CHAR) {
+            t = TY_CHAR;
+        } else if (tok == TOK_VOID) {
+            t = TY_VOID;
+        } else {
+            return false;
+        }
+        next();
+        return true;
+    }
+
+    Type acceptPointerDeclaration(Type& base) {
+        Type t = base;
+        int indirectionCount = 0;
+        while (tok == '*' && indirectionCount <= MAX_INDIRECTION_COUNT) {
+            next();
+            indirectionCount++;
+        }
+        if (indirectionCount > MAX_INDIRECTION_COUNT) {
+            error("Too many levels of pointer. Max %d", MAX_INDIRECTION_COUNT);
+        }
+        setIndirectionCount(t, indirectionCount);
+        return t;
+    }
+
+    void expectType(Type& t) {
+        if (!acceptType(t)) {
+            error("Expected a type.");
+        }
+    }
+
+    void checkSymbol() {
+        if (tok <= TOK_DEFINE) {
+            error("Expected a symbol");
+        }
+    }
+
+    void localDeclarations() {
+        intptr_t a;
+        Type base;
+
+        while (acceptType(base)) {
+            while (tok != ';') {
+                Type t = acceptPointerDeclaration(t);
+                checkSymbol();
+                loc = loc + 4;
+                *(int *) tok = -loc;
+
                 next();
-                while (tok != ';') {
-                    if (l) {
-                        loc = loc + 4;
-                        *(int *) tok = -loc;
-                    } else {
-                        *(int* *) tok = (int*) allocGlobalSpace(4);
+                if (tok == ',')
+                    next();
+            }
+            skip(';');
+        }
+    }
+
+    void globalDeclarations() {
+        while (tok != EOF) {
+            Type base;
+            expectType(base);
+            Type t = acceptPointerDeclaration(t);
+            checkSymbol();
+            int name = tok;
+            next();
+            if (tok == ',' || tok == ';') {
+                // it's a variable declaration
+                for(;;) {
+                    *(int* *) name = (int*) allocGlobalSpace(4);
+                    if (tok != ',') {
+                        break;
                     }
                     next();
-                    if (tok == ',')
-                        next();
+                    t = acceptPointerDeclaration(t);
+                    checkSymbol();
+                    name = tok;
+                    next();
                 }
                 skip(';');
             } else {
-                /* patch forward references (XXX: do not work for function
+                /* patch forward references (XXX: does not work for function
                  pointers) */
-                pGen->gsym(*(int *) (tok + 4));
+                pGen->gsym(*(int *) (name + 4));
                 /* put function address */
-                *(int *) tok = codeBuf.getPC();
-                next();
+                *(int *) name = codeBuf.getPC();
                 skip('(');
-                a = 8;
+                intptr_t a = 8;
                 int argCount = 0;
                 while (tok != ')') {
+                    Type aType;
+                    expectType(aType);
+                    aType = acceptPointerDeclaration(aType);
+                    checkSymbol();
                     /* read param name and compute offset */
                     *(int *) tok = a;
                     a = a + 4;
@@ -1620,7 +1834,7 @@
                         next();
                     argCount++;
                 }
-                next(); /* skip ')' */
+                skip(')'); /* skip ')' */
                 rsym = loc = 0;
                 a = pGen->functionEntry(argCount);
                 block(0);
@@ -1680,7 +1894,7 @@
         pGlobalBase = 0;
         pVarsBase = 0;
         pGen = 0;
-        mErrorBuf[0] = 0;
+        mPragmaStringCount = 0;
     }
 
     void setArchitecture(const char* architecture) {
@@ -1745,15 +1959,18 @@
             pGen->init(&codeBuf);
             file = new TextInputStream(text, textLength);
             sym_stk = (char*) calloc(1, ALLOC_SIZE);
-            dstk = strcpy(sym_stk,
-                    " int if else while break return for define main ")
-                    + TOK_STR_SIZE;
+            static const char* predefinedSymbols =
+                " int char void"
+                " if else while break return for"
+                " pragma define main ";
+            dstk = strcpy(sym_stk, predefinedSymbols)
+                    + strlen(predefinedSymbols);
             pGlobalBase = (char*) calloc(1, ALLOC_SIZE);
             glo = pGlobalBase;
             pVarsBase = (char*) calloc(1, ALLOC_SIZE);
             inp();
             next();
-            decl(0);
+            globalDeclarations();
             pGen->finishCompile();
         }
         return result;
@@ -1810,8 +2027,26 @@
         return NULL;
     }
 
+    void getPragmas(ACCsizei* actualStringCount,
+                    ACCsizei maxStringCount, ACCchar** strings) {
+        int stringCount = mPragmaStringCount;
+        if (actualStringCount) {
+            *actualStringCount = stringCount;
+        }
+        if (stringCount > maxStringCount) {
+            stringCount = maxStringCount;
+        }
+        if (strings) {
+            char* pPragmas = mPragmas.getUnwrapped();
+            while (stringCount-- > 0) {
+                *strings++ = pPragmas;
+                pPragmas += strlen(pPragmas) + 1;
+            }
+        }
+    }
+
     char* getErrorMessage() {
-        return mErrorBuf;
+        return mErrorBuf.getUnwrapped();
     }
 
 };
@@ -1988,5 +2223,12 @@
     }
 }
 
+extern "C"
+void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount,
+                   ACCsizei maxStringCount, ACCchar** strings){
+    script->compiler.getPragmas(actualStringCount, maxStringCount, strings);
+}
+
+
 } // namespace acc
 
diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c
new file mode 100644
index 0000000..069514b
--- /dev/null
+++ b/libacc/tests/data/otcc-ansi.c
@@ -0,0 +1,449 @@
+// #include <stdio.h>
+int d, z, C, h, P, K, ac, q, G, v, Q, R, D, L, W, M;
+
+void E(int e) {
+    *(char*) D++ = e;
+}
+
+void o() {
+    if (L) {
+        h = *(char*) L++;
+        if (h == 2) {
+            L = 0;
+            h = W;
+        }
+    } else
+        h = fgetc(Q);
+}
+
+int X() {
+    return isalnum(h) | h == 95;
+}
+
+void Y() {
+    if (h == 92) {
+        o();
+        if (h == 110)
+            h = 10;
+    }
+}
+
+void ad() {
+    int e, j, m;
+    while (isspace(h) | h == 35) {
+        if (h == 35) {
+            o();
+            ad();
+            if (d == 536) {
+                ad();
+                E(32);
+                *(int*) d = 1;
+                *(int*) (d + 4) = D;
+            }
+            while (h != 10) {
+                E(h);
+                o();
+            }
+            E(h);
+            E(2);
+        }
+        o();
+    }
+    C = 0;
+    d = h;
+    if (X()) {
+        E(32);
+        M = D;
+        while (X()) {
+            E(h);
+            o();
+        }
+        if (isdigit(d)) {
+            z = strtol(M, 0, 0);
+            d = 2;
+        } else {
+            *(char*) D = 32;
+            d = strstr(R, M - 1) - R;
+            *(char*) D = 0;
+            d = d * 8 + 256;
+            if (d > 536) {
+                d = P + d;
+                if (*(int*) d == 1) {
+                    L = *(int*) (d + 4);
+                    W = h;
+                    o();
+                    ad();
+                }
+            }
+        }
+    } else {
+        o();
+        if (d == 39) {
+            d = 2;
+            Y();
+            z = h;
+            o();
+            o();
+        } else if (d == 47 & h == 42) {
+            o();
+            while (h) {
+                while (h != 42)
+                    o();
+                o();
+                if (h == 47)
+                    h = 0;
+            }
+            o();
+            ad();
+        } else {
+            e
+                    = "++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b";
+            while (j = *(char*) e++) {
+                m = *(char*) e++;
+                z = 0;
+                while ((C = *(char*) e++ - 98) < 0)
+                    z = z * 64 + C + 64;
+                if (j == d & (m == h | m == 64)) {
+                    if (m == h) {
+                        o();
+                        d = 1;
+                    }
+                    break;
+                }
+            }
+        }
+    }
+}
+
+void ae(int g) {
+    while( g&&g!=-1) {
+        *(char*) q++=g;
+        g=g>>8;
+    }
+}
+
+void A(int e) {
+    int g;
+    while( e) {
+        g=*(int*) e;
+        *(int*) e=q-e-4;
+        e=g;
+    }
+}
+
+int s(int g, int e) {
+    ae(g);
+    *(int*) q = e;
+    e = q;
+    q = q + 4;
+    return e;
+}
+
+void H(int e) {
+    s(184,e);
+}
+
+int B(int e) {
+    return s(233,e);
+}
+
+int S(int j, int e) {
+    ae(1032325);
+    return s(132 + j, e);
+}
+
+void Z(int e) {
+    ae( 49465);
+    H(0);
+    ae( 15);
+    ae( e+144);
+    ae( 192);
+}
+
+void N(int j, int e) {
+    ae(j + 131);
+    s((e < 512) << 7 | 5, e);
+}
+
+void T (int j) {
+    int g,e,m,aa;
+    g=1;
+    if( d == 34) {
+        H(v);
+        while( h!=34) {
+            Y ();
+            *(char*) v++=h;
+            o ();
+        }
+        *(char*) v=0;
+        v=v +4&-4;
+        o ();
+        ad();
+    }
+    else {
+        aa=C;
+        m= z;
+        e=d;
+        ad();
+        if( e == 2) {
+            H(m);
+        }
+        else if( aa == 2) {
+            T(0);
+            s(185,0);
+            if( e == 33)Z(m);
+            else ae( m);
+        }
+        else if( e == 40) {
+            w ();
+            ad();
+        }
+        else if( e == 42) {
+            ad();
+            e=d;
+            ad();
+            ad();
+            if( d == 42) {
+                ad();
+                ad();
+                ad();
+                ad();
+                e=0;
+            }
+            ad();
+            T(0);
+            if( d == 61) {
+                ad();
+                ae( 80);
+                w ();
+                ae( 89);
+                ae( 392+(e == 256));
+            }
+            else if( e) {
+                if( e == 256)ae( 139);
+                else ae( 48655);
+                q++;
+            }
+        }
+        else if( e == 38) {
+            N(10,*(int*) d);
+            ad();
+        }
+        else {
+            g=*(int*) e;
+            if(!g)g=dlsym(0,M);
+            if( d == 61&j) {
+                ad();
+                w ();
+                N(6,g);
+            }
+            else if( d!= 40) {
+                N(8,g);
+                if( C == 11) {
+                    N(0,g);
+                    ae( z);
+                    ad();
+                }
+            }
+        }
+    }
+    if( d == 40) {
+        if( g == 1)ae( 80);
+        m= s(60545,0);
+        ad();
+        j=0;
+        while( d!= 41) {
+            w ();
+            s(2393225,j);
+            if( d == 44)ad();
+            j=j +4;
+        }
+        *(int*) m= j;
+        ad();
+        if(!g) {
+            e=e +4;
+            *(int*) e=s(232,*(int*) e);
+        }
+        else if( g == 1) {
+            s(2397439,j);
+            j=j +4;
+        }
+        else {
+            s(232,g-q-5);
+        }
+        if( j)s(50305,j);
+    }
+}
+
+void O (int j) {
+    int e,g,m;
+    if( j--== 1)T(1);
+    else {
+        O (j);
+        m= 0;
+        while( j == C) {
+            g=d;
+            e=z;
+            ad();
+            if( j>8) {
+                m= S(e,m);
+                O (j);
+            }
+            else {
+                ae( 80);
+                O (j);
+                ae( 89);
+                if( j == 4|j == 5) {
+                    Z(e);
+                }
+                else {
+                    ae( e);
+                    if( g == 37)ae( 146);
+                }
+            }
+        }
+        if( m&&j>8) {
+            m= S(e,m);
+            H(e^1);
+            B(5);
+            A(m);
+            H(e);
+        }
+    }
+}
+
+void w() {
+    O(11);
+}
+
+int U() {
+    w();
+    return S(0, 0);
+}
+
+void I (int j) {
+    int m,g,e;
+    if( d == 288) {
+        ad();
+        ad();
+        m= U ();
+        ad();
+        I (j);
+        if( d == 312) {
+            ad();
+            g=B(0);
+            A(m);
+            I (j);
+            A(g);
+        }
+        else {
+            A(m);
+        }
+    }
+    else if( d == 352|d == 504) {
+        e=d;
+        ad();
+        ad();
+        if( e == 352) {
+            g=q;
+            m= U ();
+        }
+        else {
+            if( d!= 59)w ();
+            ad();
+            g=q;
+            m= 0;
+            if( d!= 59)m= U ();
+            ad();
+            if( d!= 41) {
+                e=B(0);
+                w ();
+                B(g-q-5);
+                A(e);
+                g=e +4;
+            }
+        }
+        ad();
+        I(&m);
+        B(g-q-5);
+        A(m);
+    }
+    else if( d == 123) {
+        ad();
+        ab(1);
+        while( d!= 125)I (j);
+        ad();
+    }
+    else {
+        if( d == 448) {
+            ad();
+            if( d!= 59)w ();
+            K=B(K);
+        }
+        else if( d == 400) {
+            ad();
+            *(int*) j=B(*(int*) j);
+        }
+        else if( d!= 59)w ();
+        ad();
+    }
+}
+
+void ab (int j) {
+    int m;
+    while( d == 256|d!=-1&!j) {
+        if( d == 256) {
+            ad();
+            while( d!= 59) {
+                if( j) {
+                    G=G +4;
+                    *(int*) d=-G;
+                }
+                else {
+                    *(int*) d=v;
+                    v=v +4;
+                }
+                ad();
+                if( d == 44)ad();
+            }
+            ad();
+        }
+        else {
+            A(*(int*)(d +4));
+            *(int*) d=q;
+            ad();
+            ad();
+            m= 8;
+            while( d!= 41) {
+                *(int*) d=m;
+                m= m +4;
+                ad();
+                if( d == 44)ad();
+            }
+            ad();
+            K=G=0;
+            ae( 15042901);
+            m= s(60545,0);
+            I(0);
+            A(K);
+            ae( 50121);
+            *(int*) m= G;
+        }
+    }
+}
+
+int main(int g, int e) {
+    Q = stdin;
+    if (g-- > 1) {
+        e = e + 4;
+        Q = fopen(*(int*) e, "r");
+    }
+    D = strcpy(R = calloc(1, 99999), " int if else while break return for define main ") + 48;
+    v = calloc(1, 99999);
+    q = ac = calloc(1, 99999);
+    P = calloc(1, 99999);
+    o();
+    ad();
+    ab(0);
+    return (*(int(*)()) *(int*) (P + 592))(g, e);
+}
diff --git a/libacc/tests/data/otcc-noinclude.c b/libacc/tests/data/otcc-noinclude.c
new file mode 100644
index 0000000..530f9e2
--- /dev/null
+++ b/libacc/tests/data/otcc-noinclude.c
@@ -0,0 +1,446 @@
+// #include <stdio.h>
+#define k *(int*)
+#define a if(
+#define c ad()
+#define i else
+#define p while(
+#define x *(char*)
+#define b ==
+#define V =calloc(1,99999)
+#define f ()
+#define J return
+#define l ae(
+#define n e)
+#define u d!=
+#define F int 
+#define y (j)
+#define r m=
+#define t +4
+F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M;
+E(n{
+x D++=e;
+}
+o f{
+a L){
+h=x L++;
+a h b 2){
+L=0;
+h=W;
+}
+}
+i h=fgetc(Q);
+}
+X f{
+J isalnum(h)|h b 95;
+}
+Y f{
+a h b 92){
+o f;
+a h b 110)h=10;
+}
+}
+c{
+F e,j,m;
+p isspace(h)|h b 35){
+a h b 35){
+o f;
+c;
+a d b 536){
+c;
+E(32);
+k d=1;
+k(d t)=D;
+}
+p h!=10){
+E(h);
+o f;
+}
+E(h);
+E(2);
+}
+o f;
+}
+C=0;
+d=h;
+a X f){
+E(32);
+M=D;
+p X f){
+E(h);
+o f;
+}
+a isdigit(d)){
+z=strtol(M,0,0);
+d=2;
+}
+i{
+x D=32;
+d=strstr(R,M-1)-R;
+x D=0;
+d=d*8+256;
+a d>536){
+d=P+d;
+a k d b 1){
+L=k(d t);
+W=h;
+o f;
+c;
+}
+}
+}
+}
+i{
+o f;
+a d b 39){
+d=2;
+Y f;
+z=h;
+o f;
+o f;
+}
+i a d b 47&h b 42){
+o f;
+p h){
+p h!=42)o f;
+o f;
+a h b 47)h=0;
+}
+o f;
+c;
+}
+i{
+e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b";
+p j=x e++){
+r x e++;
+z=0;
+p(C=x e++-98)<0)z=z*64+C+64;
+a j b d&(m b h|m b 64)){
+a m b h){
+o f;
+d=1;
+}
+break;
+}
+}
+}
+}
+}
+l g){
+p g&&g!=-1){
+x q++=g;
+g=g>>8;
+}
+}
+A(n{
+F g;
+p n{
+g=k e;
+k e=q-e-4;
+e=g;
+}
+}
+s(g,n{
+l g);
+k q=e;
+e=q;
+q=q t;
+J e;
+}
+H(n{
+s(184,n;
+}
+B(n{
+J s(233,n;
+}
+S(j,n{
+l 1032325);
+J s(132+j,n;
+}
+Z(n{
+l 49465);
+H(0);
+l 15);
+l e+144);
+l 192);
+}
+N(j,n{
+l j+131);
+s((e<512)<<7|5,n;
+}
+T y{
+F g,e,m,aa;
+g=1;
+a d b 34){
+H(v);
+p h!=34){
+Y f;
+x v++=h;
+o f;
+}
+x v=0;
+v=v t&-4;
+o f;
+c;
+}
+i{
+aa=C;
+r z;
+e=d;
+c;
+a e b 2){
+H(m);
+}
+i a aa b 2){
+T(0);
+s(185,0);
+a e b 33)Z(m);
+i l m);
+}
+i a e b 40){
+w f;
+c;
+}
+i a e b 42){
+c;
+e=d;
+c;
+c;
+a d b 42){
+c;
+c;
+c;
+c;
+e=0;
+}
+c;
+T(0);
+a d b 61){
+c;
+l 80);
+w f;
+l 89);
+l 392+(e b 256));
+}
+i a n{
+a e b 256)l 139);
+i l 48655);
+q++;
+}
+}
+i a e b 38){
+N(10,k d);
+c;
+}
+i{
+g=k e;
+a!g)g=dlsym(0,M);
+a d b 61&j){
+c;
+w f;
+N(6,g);
+}
+i a u 40){
+N(8,g);
+a C b 11){
+N(0,g);
+l z);
+c;
+}
+}
+}
+}
+a d b 40){
+a g b 1)l 80);
+r s(60545,0);
+c;
+j=0;
+p u 41){
+w f;
+s(2393225,j);
+a d b 44)c;
+j=j t;
+}
+k r j;
+c;
+a!g){
+e=e t;
+k e=s(232,k n;
+}
+i a g b 1){
+s(2397439,j);
+j=j t;
+}
+i{
+s(232,g-q-5);
+}
+a j)s(50305,j);
+}
+}
+O y{
+F e,g,m;
+a j--b 1)T(1);
+i{
+O y;
+r 0;
+p j b C){
+g=d;
+e=z;
+c;
+a j>8){
+r S(e,m);
+O y;
+}
+i{
+l 80);
+O y;
+l 89);
+a j b 4|j b 5){
+Z(n;
+}
+i{
+l n;
+a g b 37)l 146);
+}
+}
+}
+a m&&j>8){
+r S(e,m);
+H(e^1);
+B(5);
+A(m);
+H(n;
+}
+}
+}
+w f{
+O(11);
+}
+U f{
+w f;
+J S(0,0);
+}
+I y{
+F m,g,e;
+a d b 288){
+c;
+c;
+r U f;
+c;
+I y;
+a d b 312){
+c;
+g=B(0);
+A(m);
+I y;
+A(g);
+}
+i{
+A(m);
+}
+}
+i a d b 352|d b 504){
+e=d;
+c;
+c;
+a e b 352){
+g=q;
+r U f;
+}
+i{
+a u 59)w f;
+c;
+g=q;
+r 0;
+a u 59)r U f;
+c;
+a u 41){
+e=B(0);
+w f;
+B(g-q-5);
+A(n;
+g=e t;
+}
+}
+c;
+I(&m);
+B(g-q-5);
+A(m);
+}
+i a d b 123){
+c;
+ab(1);
+p u 125)I y;
+c;
+}
+i{
+a d b 448){
+c;
+a u 59)w f;
+K=B(K);
+}
+i a d b 400){
+c;
+k j=B(k j);
+}
+i a u 59)w f;
+c;
+}
+}
+ab y{
+F m;
+p d b 256|u-1&!j){
+a d b 256){
+c;
+p u 59){
+a j){
+G=G t;
+k d=-G;
+}
+i{
+k d=v;
+v=v t;
+}
+c;
+a d b 44)c;
+}
+c;
+}
+i{
+A(k(d t));
+k d=q;
+c;
+c;
+r 8;
+p u 41){
+k d=m;
+r m t;
+c;
+a d b 44)c;
+}
+c;
+K=G=0;
+l 15042901);
+r s(60545,0);
+I(0);
+A(K);
+l 50121);
+k r G;
+}
+}
+}
+main(g,n{
+Q=stdin;
+a g-->1){
+e=e t;
+Q=fopen(k e,"r");
+}
+D=strcpy(R V," int if else while break return for define main ")+48;
+v V;
+q=ac V;
+P V;
+o f;
+c;
+ab(0);
+J(*(int(*)f)k(P+592))(g,n;
+}
+
diff --git a/libacc/tests/data/returnval-ansi.c b/libacc/tests/data/returnval-ansi.c
new file mode 100644
index 0000000..42802c5
--- /dev/null
+++ b/libacc/tests/data/returnval-ansi.c
@@ -0,0 +1,7 @@
+int main(int argc, char** argv) {
+  return f();
+}
+
+int f() {
+    return 10;
+}
diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c
index 3142fe2..1b9dd81 100644
--- a/libacc/tests/data/returnval.c
+++ b/libacc/tests/data/returnval.c
@@ -1,3 +1,7 @@
+#pragma foo3(bar) //sdfsfd
+#pragma a(b)
+
 main() {
   return 42;
-}
\ No newline at end of file
+}
+
diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp
index e65103e..acee09d 100644
--- a/libacc/tests/main.cpp
+++ b/libacc/tests/main.cpp
@@ -68,12 +68,14 @@
     fseek(in, 0, SEEK_END);
     size_t fileSize = (size_t) ftell(in);
     rewind(in);
-    ACCchar* text = new ACCchar[fileSize];
+    ACCchar* text = new ACCchar[fileSize + 1];
     size_t bytesRead = fread(text, 1, fileSize, in);
     if (bytesRead != fileSize) {
         fprintf(stderr, "Could not read all of file %s\n", inFile);
     }
 
+    text[fileSize] = '\0';
+
     ACCscript* script = accCreateScript();
 
     const ACCchar* scriptSource[] = {text};
@@ -86,10 +88,23 @@
     if (result != 0) {
         char buf[1024];
         accGetScriptInfoLog(script, sizeof(buf), NULL, buf);
-        fprintf(stderr, "%ss", buf);
+        fprintf(stderr, "%s", buf);
         goto exit;
     }
 
+    {
+        ACCsizei numPragmaStrings;
+        accGetPragmas(script, &numPragmaStrings, 0, NULL);
+        if (numPragmaStrings) {
+            char** strings = new char*[numPragmaStrings];
+            accGetPragmas(script, NULL, numPragmaStrings, strings);
+            for(ACCsizei i = 0; i < numPragmaStrings; i += 2) {
+                fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]);
+            }
+            delete[] strings;
+        }
+    }
+
     accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
 
     result = accGetError(script);
diff --git a/libacc/tests/testarm b/libacc/tests/testarm
index db7ebe5..24fbc42 100755
--- a/libacc/tests/testarm
+++ b/libacc/tests/testarm
@@ -1,9 +1,9 @@
 #!/bin/sh
 adb remount
 adb shell rm /system/bin/acc
-adb push data/returnval.c /system/bin/returnval.c
+adb push data/returnval-ansi.c /system/bin/returnval-ansi.c
 cd ..
 mm -j8
 cd tests
 adb sync
-adb shell /system/bin/acc -S /system/bin/returnval.c
+adb shell /system/bin/acc -S /system/bin/returnval-ansi.c
diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal
index a76322b..ccabf7d 100755
--- a/libacc/tests/testlocal
+++ b/libacc/tests/testlocal
@@ -4,12 +4,14 @@
 g++ -I../include acc.cpp disassem.cpp tests/main.cpp -g -ldl -o tests/test-acc
 cd tests
 if [ -x "test-acc" ]; then
-  ./test-acc -S data/returnval.c
+  ./test-acc -S data/returnval-ansi.c
 
   if [ "$(uname)" = "Linux" ]; then
     if [ "$(uname -m)" = "i686" ]; then
-      echo "Linux i686. Testing otcc.c"
-      ./test-acc data/otcc.c data/otcc.c data/returnval.c
+      echo "Linux i686. Testing otcc-ansi.c"
+      ./test-acc data/otcc-ansi.c data/returnval.c
+      echo "Linux i686. Testing otcc-ansi.c data/otcc.c"
+      ./test-acc data/otcc-ansi.c data/otcc.c data/returnval.c
     fi
   fi
 fi
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index 5e158af..8b71f87 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -83,3 +83,8 @@
 	struct ashmem_pin pin = { offset, len };
 	return ioctl(fd, ASHMEM_UNPIN, &pin);
 }
+
+int ashmem_get_size_region(int fd)
+{
+  return ioctl(fd, ASHMEM_GET_SIZE, NULL);
+}
diff --git a/libcutils/ashmem-host.c b/libcutils/ashmem-host.c
index dbb52bc..f03e130 100644
--- a/libcutils/ashmem-host.c
+++ b/libcutils/ashmem-host.c
@@ -92,3 +92,23 @@
 {
 	return ASHMEM_IS_UNPINNED;
 }
+
+int ashmem_get_size_region(int fd)
+{
+        struct stat buf;
+        int result;
+
+        result = fstat(fd, &buf);
+        if (result == -1) {
+                return -1;
+        }
+
+        // Check if this is an "ashmem" region.
+        // TODO: This is very hacky, and can easily break. We need some reliable indicator.
+        if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) {
+                errno = ENOTTY;
+                return -1;
+        }
+
+        return (int)buf.st_size;  // TODO: care about overflow (> 2GB file)?
+}
diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h
index 8837e07..ef3b66a 100644
--- a/libpixelflinger/codeflinger/ARMAssembler.h
+++ b/libpixelflinger/codeflinger/ARMAssembler.h
@@ -21,8 +21,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/Vector.h>
-#include <utils/KeyedVector.h>
+#include "tinyutils/Vector.h"
+#include "tinyutils/KeyedVector.h"
+#include "tinyutils/smartpointer.h"
 
 #include "tinyutils/smartpointer.h"
 #include "codeflinger/ARMAssemblerInterface.h"
diff --git a/libpixelflinger/codeflinger/CodeCache.h b/libpixelflinger/codeflinger/CodeCache.h
index 370ce17..8ff1366 100644
--- a/libpixelflinger/codeflinger/CodeCache.h
+++ b/libpixelflinger/codeflinger/CodeCache.h
@@ -23,8 +23,7 @@
 #include <pthread.h>
 #include <sys/types.h>
 
-#include <utils/KeyedVector.h>
-
+#include "tinyutils/KeyedVector.h"
 #include "tinyutils/smartpointer.h"
 
 namespace android {
diff --git a/libpixelflinger/tinyutils/Errors.h b/libpixelflinger/tinyutils/Errors.h
new file mode 100644
index 0000000..b9fd5f4
--- /dev/null
+++ b/libpixelflinger/tinyutils/Errors.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ERRORS_H
+#define ANDROID_ERRORS_H
+
+#include <sys/types.h>
+#include <errno.h>
+
+namespace android {
+
+// use this type to return error codes
+typedef int32_t     status_t;
+
+/*
+ * Error codes. 
+ * All error codes are negative values.
+ */
+
+enum {
+    OK                = 0,    // Everything's swell.
+    NO_ERROR          = 0,    // No errors.
+    
+    UNKNOWN_ERROR       = 0x80000000,
+
+    NO_MEMORY           = -ENOMEM,
+    INVALID_OPERATION   = -ENOSYS,
+    BAD_VALUE           = -EINVAL,
+    BAD_TYPE            = 0x80000001,
+    NAME_NOT_FOUND      = -ENOENT,
+    PERMISSION_DENIED   = -EPERM,
+    NO_INIT             = -ENODEV,
+    ALREADY_EXISTS      = -EEXIST,
+    DEAD_OBJECT         = -EPIPE,
+    FAILED_TRANSACTION  = 0x80000002,
+    JPARKS_BROKE_IT     = -EPIPE,
+    BAD_INDEX           = -EOVERFLOW,
+    NOT_ENOUGH_DATA     = -ENODATA,
+    WOULD_BLOCK         = -EWOULDBLOCK, 
+    TIMED_OUT           = -ETIME,
+    UNKNOWN_TRANSACTION = -EBADMSG,
+};
+
+
+}; // namespace android
+    
+// ---------------------------------------------------------------------------
+    
+#endif // ANDROID_ERRORS_H
diff --git a/libpixelflinger/tinyutils/SortedVector.h b/libpixelflinger/tinyutils/SortedVector.h
new file mode 100644
index 0000000..7a6b443
--- /dev/null
+++ b/libpixelflinger/tinyutils/SortedVector.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SORTED_VECTOR_H
+#define ANDROID_SORTED_VECTOR_H
+
+#include <assert.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "tinyutils/Vector.h"
+#include "tinyutils/VectorImpl.h"
+#include "tinyutils/TypeHelpers.h"
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+template <class TYPE>
+class SortedVector : private SortedVectorImpl
+{
+public:
+            typedef TYPE    value_type;
+    
+    /*! 
+     * Constructors and destructors
+     */
+    
+                            SortedVector();
+                            SortedVector(const SortedVector<TYPE>& rhs);
+    virtual                 ~SortedVector();
+
+    /*! copy operator */
+    const SortedVector<TYPE>&   operator = (const SortedVector<TYPE>& rhs) const;    
+    SortedVector<TYPE>&         operator = (const SortedVector<TYPE>& rhs);    
+
+    /*
+     * empty the vector
+     */
+
+    inline  void            clear()             { VectorImpl::clear(); }
+
+    /*! 
+     * vector stats
+     */
+
+    //! returns number of items in the vector
+    inline  size_t          size() const                { return VectorImpl::size(); }
+    //! returns wether or not the vector is empty
+    inline  bool            isEmpty() const             { return VectorImpl::isEmpty(); }
+    //! returns how many items can be stored without reallocating the backing store
+    inline  size_t          capacity() const            { return VectorImpl::capacity(); }
+    //! setst the capacity. capacity can never be reduced less than size()
+    inline  ssize_t         setCapacity(size_t size)    { return VectorImpl::setCapacity(size); }
+
+    /*! 
+     * C-style array access
+     */
+     
+    //! read-only C-style access 
+    inline  const TYPE*     array() const;
+
+    //! read-write C-style access. BE VERY CAREFUL when modifying the array
+    //! you ust keep it sorted! You usually don't use this function.
+            TYPE*           editArray();
+
+            //! finds the index of an item
+            ssize_t         indexOf(const TYPE& item) const;
+            
+            //! finds where this item should be inserted
+            size_t          orderOf(const TYPE& item) const;
+            
+    
+    /*! 
+     * accessors
+     */
+
+    //! read-only access to an item at a given index
+    inline  const TYPE&     operator [] (size_t index) const;
+    //! alternate name for operator []
+    inline  const TYPE&     itemAt(size_t index) const;
+    //! stack-usage of the vector. returns the top of the stack (last element)
+            const TYPE&     top() const;
+    //! same as operator [], but allows to access the vector backward (from the end) with a negative index
+            const TYPE&     mirrorItemAt(ssize_t index) const;
+
+    /*!
+     * modifing the array
+     */
+
+            //! add an item in the right place (and replace the one that is there)
+            ssize_t         add(const TYPE& item);
+            
+            //! editItemAt() MUST NOT change the order of this item
+            TYPE&           editItemAt(size_t index) {
+                return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
+            }
+
+            //! merges a vector into this one
+            ssize_t         merge(const Vector<TYPE>& vector);
+            ssize_t         merge(const SortedVector<TYPE>& vector);
+            
+            //! removes an item
+            ssize_t         remove(const TYPE&);
+
+    //! remove several items
+    inline  ssize_t         removeItemsAt(size_t index, size_t count = 1);
+    //! remove one item
+    inline  ssize_t         removeAt(size_t index)  { return removeItemsAt(index); }
+            
+protected:
+    virtual void    do_construct(void* storage, size_t num) const;
+    virtual void    do_destroy(void* storage, size_t num) const;
+    virtual void    do_copy(void* dest, const void* from, size_t num) const;
+    virtual void    do_splat(void* dest, const void* item, size_t num) const;
+    virtual void    do_move_forward(void* dest, const void* from, size_t num) const;
+    virtual void    do_move_backward(void* dest, const void* from, size_t num) const;
+    virtual int     do_compare(const void* lhs, const void* rhs) const;
+};
+
+
+// ---------------------------------------------------------------------------
+// No user serviceable parts from here...
+// ---------------------------------------------------------------------------
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector()
+    : SortedVectorImpl(sizeof(TYPE),
+                ((traits<TYPE>::has_trivial_ctor   ? HAS_TRIVIAL_CTOR   : 0)
+                |(traits<TYPE>::has_trivial_dtor   ? HAS_TRIVIAL_DTOR   : 0)
+                |(traits<TYPE>::has_trivial_copy   ? HAS_TRIVIAL_COPY   : 0)
+                |(traits<TYPE>::has_trivial_assign ? HAS_TRIVIAL_ASSIGN : 0))
+                )
+{
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::SortedVector(const SortedVector<TYPE>& rhs)
+    : SortedVectorImpl(rhs) {
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>::~SortedVector() {
+    finish_vector();
+}
+
+template<class TYPE> inline
+SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
+    SortedVectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const SortedVector<TYPE>& SortedVector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
+    SortedVectorImpl::operator = (rhs);
+    return *this; 
+}
+
+template<class TYPE> inline
+const TYPE* SortedVector<TYPE>::array() const {
+    return static_cast<const TYPE *>(arrayImpl());
+}
+
+template<class TYPE> inline
+TYPE* SortedVector<TYPE>::editArray() {
+    return static_cast<TYPE *>(editArrayImpl());
+}
+
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::operator[](size_t index) const {
+    assert( index<size() );
+    return *(array() + index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::itemAt(size_t index) const {
+    return operator[](index);
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::mirrorItemAt(ssize_t index) const {
+    assert( (index>0 ? index : -index)<size() );
+    return *(array() + ((index<0) ? (size()-index) : index));
+}
+
+template<class TYPE> inline
+const TYPE& SortedVector<TYPE>::top() const {
+    return *(array() + size() - 1);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::add(const TYPE& item) {
+    return SortedVectorImpl::add(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::indexOf(const TYPE& item) const {
+    return SortedVectorImpl::indexOf(&item);
+}
+
+template<class TYPE> inline
+size_t SortedVector<TYPE>::orderOf(const TYPE& item) const {
+    return SortedVectorImpl::orderOf(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const Vector<TYPE>& vector) {
+    return SortedVectorImpl::merge(reinterpret_cast<const VectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::merge(const SortedVector<TYPE>& vector) {
+    return SortedVectorImpl::merge(reinterpret_cast<const SortedVectorImpl&>(vector));
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::remove(const TYPE& item) {
+    return SortedVectorImpl::remove(&item);
+}
+
+template<class TYPE> inline
+ssize_t SortedVector<TYPE>::removeItemsAt(size_t index, size_t count) {
+    return VectorImpl::removeItemsAt(index, count);
+}
+
+// ---------------------------------------------------------------------------
+
+template<class TYPE>
+void SortedVector<TYPE>::do_construct(void* storage, size_t num) const {
+    construct_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_destroy(void* storage, size_t num) const {
+    destroy_type( reinterpret_cast<TYPE*>(storage), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
+    copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
+    splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
+    move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+void SortedVector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
+    move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
+}
+
+template<class TYPE>
+int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
+    return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
+}
+
+}; // namespace android
+
+
+// ---------------------------------------------------------------------------
+
+#endif // ANDROID_SORTED_VECTOR_H
diff --git a/libpixelflinger/tinyutils/Vector.h b/libpixelflinger/tinyutils/Vector.h
index 182bc7b..14cf99a 100644
--- a/libpixelflinger/tinyutils/Vector.h
+++ b/libpixelflinger/tinyutils/Vector.h
@@ -15,6 +15,7 @@
 
 #include <cutils/log.h>
 
+#include "tinyutils/Errors.h"
 #include "tinyutils/VectorImpl.h"
 #include "tinyutils/TypeHelpers.h"
 
@@ -302,16 +303,6 @@
     return VectorImpl::removeItemsAt(index, count);
 }
 
-template<class TYPE> inline
-status_t Vector<TYPE>::sort(Vector<TYPE>::compar_t cmp) {
-    return VectorImpl::sort((VectorImpl::compar_t)cmp);
-}
-
-template<class TYPE> inline
-status_t Vector<TYPE>::sort(Vector<TYPE>::compar_r_t cmp, void* state) {
-    return VectorImpl::sort((VectorImpl::compar_r_t)cmp, state);
-}
-
 // ---------------------------------------------------------------------------
 
 template<class TYPE>
diff --git a/nexus/Android.mk b/nexus/Android.mk
index 1c4a394..bd4e3d4 100644
--- a/nexus/Android.mk
+++ b/nexus/Android.mk
@@ -32,7 +32,7 @@
 
 LOCAL_CFLAGS := 
 
-LOCAL_SHARED_LIBRARIES := libsysutils libwpa_client libutils
+LOCAL_SHARED_LIBRARIES := libsysutils libwpa_client
 
 include $(BUILD_EXECUTABLE)
 
@@ -46,7 +46,7 @@
 
 LOCAL_CFLAGS := 
 
-LOCAL_SHARED_LIBRARIES := libutils
+LOCAL_SHARED_LIBRARIES := libcutils
 
 include $(BUILD_EXECUTABLE)
 
diff --git a/nexus/ISupplicantEventHandler.h b/nexus/ISupplicantEventHandler.h
new file mode 100644
index 0000000..7e1bd5a
--- /dev/null
+++ b/nexus/ISupplicantEventHandler.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ISUPPLICANT_EVENT_HANDLER_H
+#define _ISUPPLICANT_EVENT_HANDLER_H
+
+class ISupplicantEventHandler {
+public:
+    virtual int onConnectedEvent(SupplicantEvent *evt) = 0;
+    virtual int onDisconnectedEvent(SupplicantEvent *evt) = 0;
+    virtual int onTerminatingEvent(SupplicantEvent *evt) = 0;
+    virtual int onPasswordChangedEvent(SupplicantEvent *evt) = 0;
+    virtual int onEapNotificationEvent(SupplicantEvent *evt) = 0;
+    virtual int onEapStartedEvent(SupplicantEvent *evt) = 0;
+    virtual int onEapMethodEvent(SupplicantEvent *evt) = 0;
+    virtual int onEapSuccessEvent(SupplicantEvent *evt) = 0;
+    virtual int onEapFailureEvent(SupplicantEvent *evt) = 0;
+    virtual int onScanResultsEvent(SupplicantEvent *evt) = 0;
+    virtual int onStateChangeEvent(SupplicantEvent *evt) = 0;
+    virtual int onLinkSpeedEvent(SupplicantEvent *evt) = 0;
+    virtual int onDriverStateEvent(SupplicantEvent *evt) = 0;
+};
+
+#endif
+
diff --git a/nexus/Supplicant.h b/nexus/Supplicant.h
index 34ecdcf..42f2f79 100644
--- a/nexus/Supplicant.h
+++ b/nexus/Supplicant.h
@@ -30,8 +30,9 @@
 #include "ScanResult.h"
 #include "WifiNetwork.h"
 #include "IPropertyProvider.h"
+#include "ISupplicantEventHandler.h"
 
-class Supplicant : public IPropertyProvider {
+class Supplicant : public IPropertyProvider, public ISupplicantEventHandler {
 private:
     struct wpa_ctrl      *mCtrl;
     struct wpa_ctrl      *mMonitor;
@@ -77,9 +78,13 @@
     int set(const char *name, const char *value);
     const char *get(const char *name, char *buffer, size_t max);
 
-// XXX: Extract these into an interface
-// handlers for SupplicantListener
-public:
+private:
+    int connectToSupplicant();
+    int sendCommand(const char *cmd, char *reply, size_t *reply_len);
+    int setupConfig();
+    int retrieveInterfaceName();
+
+    // ISupplicantEventHandler methods
     virtual int onConnectedEvent(SupplicantEvent *evt);
     virtual int onDisconnectedEvent(SupplicantEvent *evt);
     virtual int onTerminatingEvent(SupplicantEvent *evt);
@@ -93,12 +98,6 @@
     virtual int onStateChangeEvent(SupplicantEvent *evt);
     virtual int onLinkSpeedEvent(SupplicantEvent *evt);
     virtual int onDriverStateEvent(SupplicantEvent *evt);
-
-private:
-    int connectToSupplicant();
-    int sendCommand(const char *cmd, char *reply, size_t *reply_len);
-    int setupConfig();
-    int retrieveInterfaceName();
 };
 
 #endif
diff --git a/nexus/SupplicantListener.cpp b/nexus/SupplicantListener.cpp
index 852eeb2..b94648b 100644
--- a/nexus/SupplicantListener.cpp
+++ b/nexus/SupplicantListener.cpp
@@ -23,13 +23,14 @@
 
 #include "libwpa_client/wpa_ctrl.h"
 
-#include "Supplicant.h"
 #include "SupplicantListener.h"
 #include "SupplicantEvent.h"
+#include "ISupplicantEventHandler.h"
 
-SupplicantListener::SupplicantListener(Supplicant *supplicant, struct wpa_ctrl *monitor) :
+SupplicantListener::SupplicantListener(ISupplicantEventHandler *handlers, 
+                                       struct wpa_ctrl *monitor) :
                     SocketListener(wpa_ctrl_get_fd(monitor), false) {
-    mSupplicant = supplicant;
+    mHandlers = handlers;
     mMonitor = monitor;
 }
 
@@ -58,29 +59,29 @@
     // XXX: Instead of calling Supplicant directly
     // extract an Interface and use that instead
     if (evt->getType() == SupplicantEvent::EVENT_CONNECTED)
-        rc = mSupplicant->onConnectedEvent(evt);
+        rc = mHandlers->onConnectedEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_DISCONNECTED)
-        rc = mSupplicant->onDisconnectedEvent(evt);
+        rc = mHandlers->onDisconnectedEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_TERMINATING)
-        rc = mSupplicant->onTerminatingEvent(evt);
+        rc = mHandlers->onTerminatingEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_PASSWORD_CHANGED)
-        rc = mSupplicant->onPasswordChangedEvent(evt);
+        rc = mHandlers->onPasswordChangedEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_EAP_NOTIFICATION)
-        rc = mSupplicant->onEapNotificationEvent(evt);
+        rc = mHandlers->onEapNotificationEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_EAP_STARTED)
-        rc = mSupplicant->onEapStartedEvent(evt);
+        rc = mHandlers->onEapStartedEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_EAP_SUCCESS)
-        rc = mSupplicant->onEapSuccessEvent(evt);
+        rc = mHandlers->onEapSuccessEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_EAP_FAILURE)
-        rc = mSupplicant->onEapFailureEvent(evt);
+        rc = mHandlers->onEapFailureEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_SCAN_RESULTS)
-        rc = mSupplicant->onScanResultsEvent(evt);
+        rc = mHandlers->onScanResultsEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_STATE_CHANGE)
-        rc = mSupplicant->onStateChangeEvent(evt);
+        rc = mHandlers->onStateChangeEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_LINK_SPEED)
-        rc = mSupplicant->onLinkSpeedEvent(evt);
+        rc = mHandlers->onLinkSpeedEvent(evt);
     else if (evt->getType() == SupplicantEvent::EVENT_DRIVER_STATE)
-        rc = mSupplicant->onDriverStateEvent(evt);
+        rc = mHandlers->onDriverStateEvent(evt);
     else {
         LOGW("Ignoring unknown event");
     }
diff --git a/nexus/SupplicantListener.h b/nexus/SupplicantListener.h
index 680a523..3d186ad 100644
--- a/nexus/SupplicantListener.h
+++ b/nexus/SupplicantListener.h
@@ -22,22 +22,22 @@
 struct wpa_ctrl;
 class Supplicant;
 class SocketClient;
+class ISupplicantEventHandler;
 
 class SupplicantListener: public SocketListener {
 private:
-    struct wpa_ctrl *mMonitor;
-    Supplicant      *mSupplicant;
+    struct wpa_ctrl         *mMonitor;
+    ISupplicantEventHandler *mHandlers;
 
 public:
-    SupplicantListener(Supplicant *supplicant, struct wpa_ctrl *monitor);
+    SupplicantListener(ISupplicantEventHandler *handlers,
+                       struct wpa_ctrl *monitor);
     virtual ~SupplicantListener() {}
 
     struct wpa_ctrl *getMonitor() { return mMonitor; }
-    Supplicant *getSupplicant() { return mSupplicant; }
 
 protected:
     virtual bool onDataAvailable(SocketClient *c);
-
 };
 
 #endif
diff --git a/nexus/WifiNetwork.cpp b/nexus/WifiNetwork.cpp
index 1f53a20..818b91d 100644
--- a/nexus/WifiNetwork.cpp
+++ b/nexus/WifiNetwork.cpp
@@ -551,6 +551,20 @@
 }
 
 int WifiNetwork::setEnabled(bool enabled) {
+
+    if (enabled) {
+        if (getPriority() == -1) {
+            LOGE("Cannot enable network when priority is not set");
+            errno = EAGAIN;
+            return -1;
+        }
+        if (getAllowedKeyManagement() == KeyManagementMask::UNKNOWN) {
+            LOGE("Cannot enable network when KeyManagement is not set");
+            errno = EAGAIN;
+            return -1;
+        }
+    }
+
     if (mSuppl->enableNetwork(mNetid, enabled))
         return -1;
 
diff --git a/nexus/WifiNetwork.h b/nexus/WifiNetwork.h
index bdffa8b..360ccc2 100644
--- a/nexus/WifiNetwork.h
+++ b/nexus/WifiNetwork.h
@@ -23,10 +23,11 @@
 
 class KeyManagementMask {
 public:
-    static const uint32_t NONE      = 0;
-    static const uint32_t WPA_PSK   = 0x01;
-    static const uint32_t WPA_EAP   = 0x02;
-    static const uint32_t IEEE8021X = 0x04;
+    static const uint32_t UNKNOWN   = 0;
+    static const uint32_t NONE      = 0x01;
+    static const uint32_t WPA_PSK   = 0x02;
+    static const uint32_t WPA_EAP   = 0x04;
+    static const uint32_t IEEE8021X = 0x08;
     static const uint32_t ALL       = WPA_PSK | WPA_EAP | IEEE8021X;
 };
 
diff --git a/vold/volmgr_vfat.c b/vold/volmgr_vfat.c
index 4013df8..2b0e1fa 100644
--- a/vold/volmgr_vfat.c
+++ b/vold/volmgr_vfat.c
@@ -110,7 +110,7 @@
     LOG_VOL("vfat_mount(%d:%d, %s, %d):", dev->major, dev->minor, vol->mount_point, safe_mode);
 #endif
 
-    flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC | MS_SYNCHRONOUS;
+    flags = MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_DIRSYNC;
 
     if (vol->state == volstate_mounted) {
         LOG_VOL("Remounting %d:%d on %s, safe mode %d", dev->major,