Merge commit 'goog/master' into merge_master
diff --git a/include/android/log.h b/include/android/log.h
new file mode 100644
index 0000000..0ea4c29
--- /dev/null
+++ b/include/android/log.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2009 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_LOG_H
+#define _ANDROID_LOG_H
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ *   This file is part of Android's set of stable system headers
+ *   exposed by the Android NDK (Native Development Kit) since
+ *   platform release 1.5
+ *
+ *   Third-party source AND binary code relies on the definitions
+ *   here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ *   - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ *   - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ *   - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ *   - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+/*
+ * Support routines to send messages to the Android in-kernel log buffer,
+ * which can later be accessed through the 'logcat' utility.
+ *
+ * Each log message must have
+ *   - a priority
+ *   - a log tag
+ *   - some text
+ *
+ * The tag normally corresponds to the component that emits the log message,
+ * and should be reasonably small.
+ *
+ * Log message text may be truncated to less than an implementation-specific
+ * limit (e.g. 1023 characters max).
+ *
+ * Note that a newline character ("\n") will be appended automatically to your
+ * log message, if not already there. It is not possible to send several messages
+ * and have them appear on a single line in logcat.
+ *
+ * PLEASE USE LOGS WITH MODERATION:
+ *
+ *  - Sending log messages eats CPU and slow down your application and the
+ *    system.
+ *
+ *  - The circular log buffer is pretty small (<64KB), sending many messages
+ *    might push off other important log messages from the rest of the system.
+ *
+ *  - In release builds, only send log messages to account for exceptional
+ *    conditions.
+ *
+ * NOTE: These functions MUST be implemented by /system/lib/liblog.so
+ */
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Android log priority values, in ascending priority order.
+ */
+typedef enum android_LogPriority {
+    ANDROID_LOG_UNKNOWN = 0,
+    ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
+    ANDROID_LOG_VERBOSE,
+    ANDROID_LOG_DEBUG,
+    ANDROID_LOG_INFO,
+    ANDROID_LOG_WARN,
+    ANDROID_LOG_ERROR,
+    ANDROID_LOG_FATAL,
+    ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
+} android_LogPriority;
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_write(int prio, const char *tag, const char *text);
+
+/*
+ * Send a formatted string to the log, used like printf(fmt,...)
+ */
+int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
+#if defined(__GNUC__)
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+    ;
+
+/*
+ * A variant of __android_log_print() that takes a va_list to list
+ * additional parameters.
+ */
+int __android_log_vprint(int prio, const char *tag,
+                         const char *fmt, va_list ap);
+
+/*
+ * Log an assertion failure and SIGTRAP the process to have a chance
+ * to inspect it, if a debugger is attached. This uses the FATAL priority.
+ */
+void __android_log_assert(const char *cond, const char *tag,
+			  const char *fmt, ...)    
+#if defined(__GNUC__)
+    __attribute__ ((noreturn))
+    __attribute__ ((format(printf, 3, 4)))
+#endif
+    ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ANDROID_LOG_H */
diff --git a/include/cutils/logd.h b/include/cutils/logd.h
index a1cb012..8737639 100644
--- a/include/cutils/logd.h
+++ b/include/cutils/logd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2009 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.
@@ -17,6 +17,12 @@
 #ifndef _ANDROID_CUTILS_LOGD_H
 #define _ANDROID_CUTILS_LOGD_H
 
+/* the stable/frozen log-related definitions have been
+ * moved to this header, which is exposed by the NDK
+ */
+#include <android/log.h>
+
+/* the rest is only used internally by the system */
 #include <time.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -32,45 +38,10 @@
 extern "C" {
 #endif
 
-/*
- * Priority values, in ascending priority order.
- */
-typedef enum android_LogPriority {
-    ANDROID_LOG_UNKNOWN = 0,
-    ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
-    ANDROID_LOG_VERBOSE,
-    ANDROID_LOG_DEBUG,
-    ANDROID_LOG_INFO,
-    ANDROID_LOG_WARN,
-    ANDROID_LOG_ERROR,
-    ANDROID_LOG_FATAL,
-    ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
-} android_LogPriority;
-
-int __android_log_write(int prio, const char *tag, const char *text);
-
-int __android_log_vprint(int prio, const char *tag,
-			 const char *fmt, va_list ap);
-
 int __android_log_bwrite(int32_t tag, const void *payload, size_t len);
 int __android_log_btwrite(int32_t tag, char type, const void *payload,
     size_t len);
 
-int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
-#if defined(__GNUC__)
-    __attribute__ ((format(printf, 3, 4)))
-#endif
-    ;
-
-
-void __android_log_assert(const char *cond, const char *tag,
-			  const char *fmt, ...)    
-#if defined(__GNUC__)
-    __attribute__ ((noreturn))
-    __attribute__ ((format(printf, 3, 4)))
-#endif
-    ;
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index b7e4594..733f188 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -10,6 +10,7 @@
 
 #include <ctype.h>
 #include <dlfcn.h>
+#include <setjmp.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -45,10 +46,24 @@
 
 namespace acc {
 
-class Compiler {
+class ErrorSink {
+public:
+    void error(const char *fmt, ...) {
+        va_list ap;
+        va_start(ap, fmt);
+        verror(fmt, ap);
+        va_end(ap);
+    }
+
+    virtual void verror(const char* fmt, va_list ap) = 0;
+};
+
+class Compiler : public ErrorSink {
     class CodeBuf {
-        char* ind;
+        char* ind; // Output code pointer
         char* pProgramBase;
+        ErrorSink* mErrorSink;
+        int mSize;
 
         void release() {
             if (pProgramBase != 0) {
@@ -57,10 +72,21 @@
             }
         }
 
+        void check(int n) {
+            int newSize = ind - pProgramBase + n;
+            if (newSize > mSize) {
+                if (mErrorSink) {
+                    mErrorSink->error("Code too large: %d bytes", newSize);
+                }
+            }
+        }
+
     public:
         CodeBuf() {
             pProgramBase = 0;
             ind = 0;
+            mErrorSink = 0;
+            mSize = 0;
         }
 
         ~CodeBuf() {
@@ -69,11 +95,17 @@
 
         void init(int size) {
             release();
+            mSize = size;
             pProgramBase = (char*) calloc(1, size);
             ind = pProgramBase;
         }
 
+        void setErrorSink(ErrorSink* pErrorSink) {
+            mErrorSink = pErrorSink;
+        }
+
         int o4(int n) {
+            check(4);
             intptr_t result = (intptr_t) ind;
             * (int*) ind = n;
             ind += 4;
@@ -84,6 +116,7 @@
          * Output a byte. Handles all values, 0..ff.
          */
         void ob(int n) {
+            check(1);
             *ind++ = n;
         }
 
@@ -123,11 +156,22 @@
 
     class CodeGenerator {
     public:
-        CodeGenerator() {}
+        CodeGenerator() {
+            mErrorSink = 0;
+            pCodeBuf = 0;
+        }
         virtual ~CodeGenerator() {}
 
         virtual void init(CodeBuf* pCodeBuf) {
             this->pCodeBuf = pCodeBuf;
+            pCodeBuf->setErrorSink(mErrorSink);
+        }
+
+        void setErrorSink(ErrorSink* pErrorSink) {
+            mErrorSink = pErrorSink;
+            if (pCodeBuf) {
+                pCodeBuf->setErrorSink(mErrorSink);
+            }
         }
 
         /* Emit a function prolog.
@@ -323,8 +367,16 @@
         intptr_t getSize() {
             return pCodeBuf->getSize();
         }
+
+        void error(const char* fmt,...) {
+            va_list ap;
+            va_start(ap, fmt);
+            mErrorSink->verror(fmt, ap);
+            va_end(ap);
+        }
     private:
         CodeBuf* pCodeBuf;
+        ErrorSink* mErrorSink;
     };
 
 #ifdef PROVIDE_ARM_CODEGEN
@@ -643,7 +695,7 @@
         virtual void callRelative(int t) {
             LOG_API("callRelative(%d);\n", t);
             int abs = t + getPC() + jumpOffset();
-            fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs);
+            LOG_API("abs=%d (0x%08x)\n", abs, abs);
             if (t >= - (1 << 25) && t < (1 << 25)) {
                 o4(0xEB000000 | encodeAddress(t));
             } else {
@@ -791,14 +843,6 @@
         static int runtime_MOD(int a, int b) {
             return b % a;
         }
-
-        void error(const char* fmt,...) {
-            va_list ap;
-            va_start(ap, fmt);
-            vfprintf(stderr, fmt, ap);
-            va_end(ap);
-            exit(12);
-        }
     };
 
 #endif // PROVIDE_ARM_CODEGEN
@@ -980,8 +1024,7 @@
 
         int decodeOp(int op) {
             if (op < 0 || op > OP_COUNT) {
-                fprintf(stderr, "Out-of-range operator: %d\n", op);
-                exit(1);
+                error("Out-of-range operator: %d\n", op);
             }
             return operatorHelper[op];
         }
@@ -1027,26 +1070,31 @@
         size_t mPosition;
     };
 
-    /* vars: value of variables
-     loc : local variable index
-     glo : global variable index
-     ind : output code ptr
-     rsym: return symbol
-     prog: output code
-     dstk: define stack
-     dptr, dch: macro state
-     */
-    intptr_t tok, tokc, tokl, ch, vars, rsym, loc, glo, sym_stk, dstk,
-            dptr, dch, last_id;
+    int ch; // Current input character, or EOF
+    intptr_t tok;     // token
+    intptr_t tokc;    // token extra info
+    int tokl;         // token operator level
+    intptr_t rsym; // return symbol
+    intptr_t loc; // local variable index
+    char* glo;  // global variable index
+    char* sym_stk;
+    char* dstk; // Define stack
+    char* dptr; // Macro state: Points to macro text during macro playback.
+    int dch;    // Macro state: Saves old value of ch during a macro playback.
+    char* last_id;
     void* pSymbolBase;
-    void* pGlobalBase;
-    void* pVarsBase;
+    char* pGlobalBase;
+    char* pVarsBase; // Value of variables
 
     InputStream* file;
 
     CodeBuf codeBuf;
     CodeGenerator* pGen;
 
+    static const int ERROR_BUF_SIZE = 512;
+    char mErrorBuf[ERROR_BUF_SIZE];
+    jmp_buf mErrorRecoveryJumpBuf;
+
     static const int ALLOC_SIZE = 99999;
 
     /* depends on the init string */
@@ -1106,12 +1154,15 @@
     static const char operatorLevel[];
 
     void pdef(int t) {
-        *(char *) dstk++ = t;
+        if (dstk - sym_stk >= ALLOC_SIZE) {
+            error("Symbol table exhausted");
+        }
+        *dstk++ = t;
     }
 
     void inp() {
         if (dptr) {
-            ch = *(char *) dptr++;
+            ch = *dptr++;
             if (ch == TAG_MACRO) {
                 dptr = 0;
                 ch = dch;
@@ -1145,7 +1196,7 @@
                     next();
                     pdef(TAG_TOK); /* fill last ident tag */
                     *(int *) tok = SYM_DEFINE;
-                    *(int *) (tok + 4) = dstk; /* define stack */
+                    *(char* *) (tok + 4) = dstk; /* define stack */
                 }
                 /* well we always save the values ! */
                 while (ch != '\n') {
@@ -1168,21 +1219,27 @@
                 inp();
             }
             if (isdigit(tok)) {
-                tokc = strtol((char*) last_id, 0, 0);
+                tokc = strtol(last_id, 0, 0);
                 tok = TOK_NUM;
             } else {
-                *(char *) dstk = TAG_TOK; /* no need to mark end of string (we
+                if (dstk - sym_stk + 1 > ALLOC_SIZE) {
+                    error("symbol stack overflow");
+                }
+                * dstk = TAG_TOK; /* no need to mark end of string (we
                  suppose data is initialized to zero by calloc) */
-                tok = (intptr_t) (strstr((char*) sym_stk, (char*) (last_id - 1))
+                tok = (intptr_t) (strstr(sym_stk, (last_id - 1))
                         - sym_stk);
-                *(char *) dstk = 0; /* mark real end of ident for dlsym() */
+                * dstk = 0; /* mark real end of ident for dlsym() */
                 tok = tok * 8 + TOK_IDENT;
                 if (tok > TOK_DEFINE) {
-                    tok = vars + tok;
+                    if (tok + 8 > ALLOC_SIZE) {
+                        error("Variable Table overflow.");
+                    }
+                    tok = (intptr_t) (pVarsBase + tok);
                     /*        printf("tok=%s %x\n", last_id, tok); */
                     /* define handling */
                     if (*(int *) tok == SYM_DEFINE) {
-                        dptr = *(int *) (tok + 4);
+                        dptr = *(char* *) (tok + 4);
                         dch = ch;
                         inp();
                         next();
@@ -1243,17 +1300,17 @@
         }
 #if 0
         {
-            int p;
+            char* p;
 
             printf("tok=0x%x ", tok);
             if (tok >= TOK_IDENT) {
                 printf("'");
                 if (tok> TOK_DEFINE)
-                p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8;
+                p = sym_stk + 1 + ((char*) tok - pVarsBase - TOK_IDENT) / 8;
                 else
                 p = sym_stk + 1 + (tok - TOK_IDENT) / 8;
-                while (*(char *)p != TAG_TOK && *(char *)p)
-                printf("%c", *(char *)p++);
+                while (*p != TAG_TOK && *p)
+                printf("%c", *p++);
                 printf("'\n");
             } else if (tok == TOK_NUM) {
                 printf("%d\n", tokc);
@@ -1264,15 +1321,24 @@
 #endif
     }
 
-    void error(const char *fmt, ...) {
-        va_list ap;
 
-        va_start(ap, fmt);
-        fprintf(stderr, "%ld: ", file->tell());
-        vfprintf(stderr, fmt, ap);
-        fprintf(stderr, "\n");
-        va_end(ap);
-        exit(1);
+    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;
+        }
+        longjmp(mErrorRecoveryJumpBuf, 1);
     }
 
     void skip(intptr_t c) {
@@ -1284,19 +1350,21 @@
 
     /* l is one if '=' parsing wanted (quick hack) */
     void unary(intptr_t l) {
-        intptr_t n, t, a, c;
+        intptr_t n, t, a;
+        int c;
         t = 0;
         n = 1; /* type of expression 0 = forward, 1 = value, other =
          lvalue */
         if (tok == '\"') {
-            pGen->li(glo);
+            pGen->li((int) glo);
             while (ch != '\"') {
                 getq();
-                *(char *) glo++ = ch;
+                *allocGlobalSpace(1) = ch;
                 inp();
             }
-            *(char *) glo = 0;
-            glo = (glo + 4) & -4; /* align heap */
+            *glo = 0;
+            /* align heap */
+            allocGlobalSpace((char*) (((intptr_t) glo + 4) & -4) - glo);
             inp();
             next();
         } else {
@@ -1349,7 +1417,7 @@
                 n = *(int *) t;
                 /* forward reference: try dlsym */
                 if (!n) {
-                    n = (intptr_t) dlsym(RTLD_DEFAULT, (char*) last_id);
+                    n = (intptr_t) dlsym(RTLD_DEFAULT, last_id);
                 }
                 if ((tok == '=') & l) {
                     /* assignment */
@@ -1398,7 +1466,7 @@
         }
     }
 
-    void sum(intptr_t l) {
+    void sum(int l) {
         intptr_t t, n, a;
         t = 0;
         if (l-- == 1)
@@ -1518,7 +1586,7 @@
     void decl(bool l) {
         intptr_t a;
 
-        while ((tok == TOK_INT) | ((tok != -1) & (!l))) {
+        while ((tok == TOK_INT) | ((tok != EOF) & (!l))) {
             if (tok == TOK_INT) {
                 next();
                 while (tok != ';') {
@@ -1526,8 +1594,7 @@
                         loc = loc + 4;
                         *(int *) tok = -loc;
                     } else {
-                        *(int *) tok = glo;
-                        glo = glo + 4;
+                        *(int* *) tok = (int*) allocGlobalSpace(4);
                     }
                     next();
                     if (tok == ',')
@@ -1563,13 +1630,22 @@
         }
     }
 
+    char* allocGlobalSpace(int bytes) {
+        if (glo - pGlobalBase + bytes > ALLOC_SIZE) {
+            error("Global space exhausted");
+        }
+        char* result = glo;
+        glo += bytes;
+        return result;
+    }
+
     void cleanup() {
         if (sym_stk != 0) {
-            free((void*) sym_stk);
+            free(sym_stk);
             sym_stk = 0;
         }
         if (pGlobalBase != 0) {
-            free((void*) pGlobalBase);
+            free(pGlobalBase);
             pGlobalBase = 0;
         }
         if (pVarsBase != 0) {
@@ -1591,7 +1667,7 @@
         tokc = 0;
         tokl = 0;
         ch = 0;
-        vars = 0;
+        pVarsBase = 0;
         rsym = 0;
         loc = 0;
         glo = 0;
@@ -1604,6 +1680,7 @@
         pGlobalBase = 0;
         pVarsBase = 0;
         pGen = 0;
+        mErrorBuf[0] = 0;
     }
 
     void setArchitecture(const char* architecture) {
@@ -1622,7 +1699,7 @@
             }
 #endif
             if (!pGen ) {
-                fprintf(stderr, "Unknown architecture %s\n", architecture);
+                error("Unknown architecture %s\n", architecture);
             }
         }
 
@@ -1634,8 +1711,9 @@
 #endif
         }
         if (pGen == NULL) {
-            fprintf(stderr, "No code generator defined.\n");
+            error("No code generator defined.");
         }
+        pGen->setErrorSink(this);
     }
 
 public:
@@ -1655,33 +1733,35 @@
     }
 
     int compile(const char* text, size_t textLength) {
-        cleanup();
-        clear();
-        codeBuf.init(ALLOC_SIZE);
-        setArchitecture(NULL);
-        if (!pGen) {
-            return -1;
+        int result;
+        if (! (result = setjmp(mErrorRecoveryJumpBuf))) {
+            cleanup();
+            clear();
+            codeBuf.init(ALLOC_SIZE);
+            setArchitecture(NULL);
+            if (!pGen) {
+                return -1;
+            }
+            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;
+            pGlobalBase = (char*) calloc(1, ALLOC_SIZE);
+            glo = pGlobalBase;
+            pVarsBase = (char*) calloc(1, ALLOC_SIZE);
+            inp();
+            next();
+            decl(0);
+            pGen->finishCompile();
         }
-        pGen->init(&codeBuf);
-        file = new TextInputStream(text, textLength);
-        sym_stk = (intptr_t) calloc(1, ALLOC_SIZE);
-        dstk = (intptr_t) strcpy((char*) sym_stk,
-                " int if else while break return for define main ")
-                + TOK_STR_SIZE;
-        pGlobalBase = calloc(1, ALLOC_SIZE);
-        glo = (intptr_t) pGlobalBase;
-        pVarsBase = calloc(1, ALLOC_SIZE);
-        vars = (intptr_t) pVarsBase;
-        inp();
-        next();
-        decl(0);
-        pGen->finishCompile();
-        return 0;
+        return result;
     }
 
     int run(int argc, char** argv) {
         typedef int (*mainPtr)(int argc, char** argv);
-        mainPtr aMain = (mainPtr) *(int*) (vars + TOK_MAIN);
+        mainPtr aMain = (mainPtr) *(int*) (pVarsBase + TOK_MAIN);
         if (!aMain) {
             fprintf(stderr, "Could not find function \"main\".\n");
             return -1;
@@ -1706,7 +1786,7 @@
             return NULL;
         }
         size_t nameLen = strlen(name);
-        char* pSym = (char*) sym_stk;
+        char* pSym = sym_stk;
         char c;
         for(;;) {
             c = *pSym++;
@@ -1716,12 +1796,12 @@
             if (c == TAG_TOK) {
                 if (memcmp(pSym, name, nameLen) == 0
                         && pSym[nameLen] == TAG_TOK) {
-                    int tok = pSym - 1 - (char*) sym_stk;
+                    int tok = pSym - 1 - sym_stk;
                     tok = tok * 8 + TOK_IDENT;
                     if (tok <= TOK_DEFINE) {
                         return 0;
                     } else {
-                        tok = vars + tok;
+                        tok = (intptr_t) (pVarsBase + tok);
                         return * (void**) tok;
                     }
                 }
@@ -1730,6 +1810,10 @@
         return NULL;
     }
 
+    char* getErrorMessage() {
+        return mErrorBuf;
+    }
+
 };
 
 const char* Compiler::operatorChars =
@@ -1880,11 +1964,16 @@
     ACCsizei maxLength,
     ACCsizei * length,
     ACCchar * infoLog) {
+    char* message = script->compiler.getErrorMessage();
+    int messageLength = strlen(message) + 1;
     if (length) {
-        *length = 0;
+        *length = messageLength;
     }
-    if (maxLength > 0 && infoLog) {
-        *infoLog = 0;
+    if (infoLog && maxLength > 0) {
+        int trimmedLength = maxLength < messageLength ?
+                maxLength : messageLength;
+        memcpy(infoLog, message, trimmedLength);
+        infoLog[trimmedLength] = 0;
     }
 }
 
diff --git a/libacc/tests/data/error.c b/libacc/tests/data/error.c
new file mode 100644
index 0000000..2e08dcc
--- /dev/null
+++ b/libacc/tests/data/error.c
@@ -0,0 +1,2 @@
+void foo;
+
diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp
index 8cfc196..e65103e 100644
--- a/libacc/tests/main.cpp
+++ b/libacc/tests/main.cpp
@@ -81,12 +81,18 @@
     delete[] text;
 
     accCompileScript(script);
-
+    int result = accGetError(script);
     MainPtr mainPointer = 0;
+    if (result != 0) {
+        char buf[1024];
+        accGetScriptInfoLog(script, sizeof(buf), NULL, buf);
+        fprintf(stderr, "%ss", buf);
+        goto exit;
+    }
 
     accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
 
-    int result = accGetError(script);
+    result = accGetError(script);
     if (result == ACC_NO_ERROR) {
         fprintf(stderr, "Executing compiled code:\n");
         int codeArgc = argc - i + 1;
@@ -96,6 +102,8 @@
         fprintf(stderr, "result: %d\n", result);
     }
 
+exit:
+
     accDeleteScript(script);
 
     return result;