diff options
Diffstat (limited to 'libacc/tests/main.cpp')
-rw-r--r-- | libacc/tests/main.cpp | 207 |
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; +} |