main.cpp revision 8c246a9dc294760f2a981cf5144fe4939d1554e6
1/* 2 * Android "Almost" C Compiler. 3 * This is a compiler for a small subset of the C language, intended for use 4 * in scripting environments where speed and memory footprint are important. 5 * 6 * This code is based upon the "unobfuscated" version of the 7 * Obfuscated Tiny C compiler, see the file LICENSE for details. 8 * 9 */ 10 11#include <ctype.h> 12#include <dlfcn.h> 13#include <stdarg.h> 14#include <stdint.h> 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18 19#if defined(__arm__) 20#include <unistd.h> 21#endif 22 23#include <acc/acc.h> 24 25 26typedef int (*MainPtr)(int, char**); 27// This is a separate function so it can easily be set by breakpoint in gdb. 28int run(MainPtr mainFunc, int argc, char** argv) { 29 return mainFunc(argc, argv); 30} 31 32// Private API for development: 33 34extern "C" 35void accDisassemble(ACCscript* script); 36 37ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { 38 return (ACCvoid*) dlsym(RTLD_DEFAULT, name); 39} 40 41int main(int argc, char** argv) { 42 const char* inFile = NULL; 43 bool printListing; 44 bool runResults = false; 45 FILE* in = stdin; 46 int i; 47 for (i = 1; i < argc; i++) { 48 char* arg = argv[i]; 49 if (arg[0] == '-') { 50 switch (arg[1]) { 51 case 'S': 52 printListing = true; 53 break; 54 case 'R': 55 runResults = true; 56 break; 57 default: 58 fprintf(stderr, "Unrecognized flag %s\n", arg); 59 return 3; 60 } 61 } else if (inFile == NULL) { 62 inFile = arg; 63 } else { 64 break; 65 } 66 } 67 68 if (! inFile) { 69 fprintf(stderr, "input file required\n"); 70 return 2; 71 } 72 73 if (inFile) { 74 in = fopen(inFile, "r"); 75 if (!in) { 76 fprintf(stderr, "Could not open input file %s\n", inFile); 77 return 1; 78 } 79 } 80 81 fseek(in, 0, SEEK_END); 82 size_t fileSize = (size_t) ftell(in); 83 rewind(in); 84 ACCchar* text = new ACCchar[fileSize + 1]; 85 size_t bytesRead = fread(text, 1, fileSize, in); 86 if (bytesRead != fileSize) { 87 fprintf(stderr, "Could not read all of file %s\n", inFile); 88 } 89 90 text[fileSize] = '\0'; 91 92 ACCscript* script = accCreateScript(); 93 94 const ACCchar* scriptSource[] = {text}; 95 accScriptSource(script, 1, scriptSource, NULL); 96 delete[] text; 97 98 accRegisterSymbolCallback(script, symbolLookup, NULL); 99 100 accCompileScript(script); 101 int result = accGetError(script); 102 MainPtr mainPointer = 0; 103 if (result != 0) { 104 char buf[1024]; 105 accGetScriptInfoLog(script, sizeof(buf), NULL, buf); 106 fprintf(stderr, "%s", buf); 107 goto exit; 108 } 109 110 { 111 ACCsizei numPragmaStrings; 112 accGetPragmas(script, &numPragmaStrings, 0, NULL); 113 if (numPragmaStrings) { 114 char** strings = new char*[numPragmaStrings]; 115 accGetPragmas(script, NULL, numPragmaStrings, strings); 116 for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { 117 fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); 118 } 119 delete[] strings; 120 } 121 } 122 123 if (printListing) { 124 accDisassemble(script); 125 } 126 127 if (runResults) { 128 accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); 129 130 result = accGetError(script); 131 if (result != ACC_NO_ERROR) { 132 fprintf(stderr, "Could not find main: %d\n", result); 133 } else { 134 fprintf(stderr, "Executing compiled code:\n"); 135 int codeArgc = argc - i + 1; 136 char** codeArgv = argv + i - 1; 137 codeArgv[0] = (char*) (inFile ? inFile : "stdin"); 138 result = run(mainPointer, codeArgc, codeArgv); 139 fprintf(stderr, "result: %d\n", result); 140 } 141 } 142 143exit: 144 145 accDeleteScript(script); 146 147 return result; 148} 149