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;