summaryrefslogtreecommitdiffstats
path: root/libacc/tests/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libacc/tests/main.cpp')
-rw-r--r--libacc/tests/main.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp
new file mode 100644
index 000000000..e4e386fc2
--- /dev/null
+++ b/libacc/tests/main.cpp
@@ -0,0 +1,207 @@
+/*
+ * Android "Almost" C Compiler.
+ * This is a compiler for a small subset of the C language, intended for use
+ * in scripting environments where speed and memory footprint are important.
+ *
+ * This code is based upon the "unobfuscated" version of the
+ * Obfuscated Tiny C compiler, see the file LICENSE for details.
+ *
+ */
+
+#include <ctype.h>
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__arm__)
+#include <unistd.h>
+#endif
+
+#if defined(__arm__)
+#define PROVIDE_ARM_DISASSEMBLY
+#endif
+
+#ifdef PROVIDE_ARM_DISASSEMBLY
+#include "disassem.h"
+#endif
+
+#include <acc/acc.h>
+
+
+typedef int (*MainPtr)(int, char**);
+// This is a separate function so it can easily be set by breakpoint in gdb.
+int run(MainPtr mainFunc, int argc, char** argv) {
+ return mainFunc(argc, argv);
+}
+
+ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
+ return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
+}
+
+#ifdef PROVIDE_ARM_DISASSEMBLY
+
+static FILE* disasmOut;
+
+static u_int
+disassemble_readword(u_int address)
+{
+ return(*((u_int *)address));
+}
+
+static void
+disassemble_printaddr(u_int address)
+{
+ fprintf(disasmOut, "0x%08x", address);
+}
+
+static void
+disassemble_printf(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(disasmOut, fmt, ap);
+ va_end(ap);
+}
+
+static int disassemble(ACCscript* script, FILE* out) {
+ disasmOut = out;
+ disasm_interface_t di;
+ di.di_readword = disassemble_readword;
+ di.di_printaddr = disassemble_printaddr;
+ di.di_printf = disassemble_printf;
+
+ ACCvoid* base;
+ ACCsizei length;
+
+ accGetProgramBinary(script, &base, &length);
+ unsigned long* pBase = (unsigned long*) base;
+ unsigned long* pEnd = (unsigned long*) (((unsigned char*) base) + length);
+
+ for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) {
+ fprintf(out, "%08x: %08x ", (int) pInstruction, (int) *pInstruction);
+ ::disasm(&di, (uint) pInstruction, 0);
+ }
+ return 0;
+}
+
+#endif // PROVIDE_ARM_DISASSEMBLY
+
+int main(int argc, char** argv) {
+ const char* inFile = NULL;
+ bool printListing;
+ bool runResults = false;
+ FILE* in = stdin;
+ int i;
+ for (i = 1; i < argc; i++) {
+ char* arg = argv[i];
+ if (arg[0] == '-') {
+ switch (arg[1]) {
+ case 'S':
+ printListing = true;
+ break;
+ case 'R':
+ runResults = true;
+ break;
+ default:
+ fprintf(stderr, "Unrecognized flag %s\n", arg);
+ return 3;
+ }
+ } else if (inFile == NULL) {
+ inFile = arg;
+ } else {
+ break;
+ }
+ }
+
+ if (! inFile) {
+ fprintf(stderr, "input file required\n");
+ return 2;
+ }
+
+ if (inFile) {
+ in = fopen(inFile, "r");
+ if (!in) {
+ fprintf(stderr, "Could not open input file %s\n", inFile);
+ return 1;
+ }
+ }
+
+ fseek(in, 0, SEEK_END);
+ size_t fileSize = (size_t) ftell(in);
+ rewind(in);
+ 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};
+ accScriptSource(script, 1, scriptSource, NULL);
+ delete[] text;
+
+ accRegisterSymbolCallback(script, symbolLookup, NULL);
+
+ accCompileScript(script);
+ int result = accGetError(script);
+ MainPtr mainPointer = 0;
+ if (result != 0) {
+ ACCsizei bufferLength;
+ accGetScriptInfoLog(script, 0, &bufferLength, NULL);
+ char* buf = (char*) malloc(bufferLength + 1);
+ if (buf != NULL) {
+ accGetScriptInfoLog(script, bufferLength + 1, NULL, buf);
+ fprintf(stderr, "%s", buf);
+ free(buf);
+ } else {
+ fprintf(stderr, "Out of memory.\n");
+ }
+ 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;
+ }
+ }
+
+ if (printListing) {
+#ifdef PROVIDE_ARM_DISASSEMBLY
+ disassemble(script, stderr);
+#endif
+ }
+
+ if (runResults) {
+ accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
+
+ result = accGetError(script);
+ if (result != ACC_NO_ERROR) {
+ fprintf(stderr, "Could not find main: %d\n", result);
+ } else {
+ fprintf(stderr, "Executing compiled code:\n");
+ int codeArgc = argc - i + 1;
+ char** codeArgv = argv + i - 1;
+ codeArgv[0] = (char*) (inFile ? inFile : "stdin");
+ result = run(mainPointer, codeArgc, codeArgv);
+ fprintf(stderr, "result: %d\n", result);
+ }
+ }
+
+exit:
+
+ accDeleteScript(script);
+
+ return result;
+}