blob: 5e9e816bb59eba02b672f744c29782e32f47f28e [file] [log] [blame]
Jack Palevich1cdef202009-05-22 12:06:27 -07001/*
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
-b master422972c2009-06-17 19:13:52 -070032// Private API for development:
33
34extern "C"
35void accDisassemble(ACCscript* script);
36
Jack Palevich8c246a92009-07-14 21:14:10 -070037ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
38 return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
39}
40
Jack Palevich1cdef202009-05-22 12:06:27 -070041int main(int argc, char** argv) {
42 const char* inFile = NULL;
43 bool printListing;
Jack Palevich36d94142009-06-08 15:55:32 -070044 bool runResults = false;
Jack Palevich1cdef202009-05-22 12:06:27 -070045 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;
Jack Palevich36d94142009-06-08 15:55:32 -070054 case 'R':
55 runResults = true;
56 break;
Jack Palevich1cdef202009-05-22 12:06:27 -070057 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);
Jack Palevichb7c81e92009-06-04 19:56:13 -070084 ACCchar* text = new ACCchar[fileSize + 1];
Jack Palevich1cdef202009-05-22 12:06:27 -070085 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
Jack Palevichb7c81e92009-06-04 19:56:13 -070090 text[fileSize] = '\0';
91
Jack Palevich1cdef202009-05-22 12:06:27 -070092 ACCscript* script = accCreateScript();
93
94 const ACCchar* scriptSource[] = {text};
95 accScriptSource(script, 1, scriptSource, NULL);
96 delete[] text;
97
Jack Palevich8c246a92009-07-14 21:14:10 -070098 accRegisterSymbolCallback(script, symbolLookup, NULL);
99
Jack Palevich1cdef202009-05-22 12:06:27 -0700100 accCompileScript(script);
Jack Palevichac0e95e2009-05-29 13:53:44 -0700101 int result = accGetError(script);
Jack Palevich1cdef202009-05-22 12:06:27 -0700102 MainPtr mainPointer = 0;
Jack Palevichac0e95e2009-05-29 13:53:44 -0700103 if (result != 0) {
104 char buf[1024];
105 accGetScriptInfoLog(script, sizeof(buf), NULL, buf);
Jack Palevicheedf9d22009-06-04 16:23:40 -0700106 fprintf(stderr, "%s", buf);
Jack Palevichac0e95e2009-05-29 13:53:44 -0700107 goto exit;
108 }
Jack Palevich1cdef202009-05-22 12:06:27 -0700109
Jack Palevicheedf9d22009-06-04 16:23:40 -0700110 {
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
-b master422972c2009-06-17 19:13:52 -0700123 if (printListing) {
124 accDisassemble(script);
125 }
126
Jack Palevich2db168f2009-06-11 14:29:47 -0700127 if (runResults) {
128 accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer);
Jack Palevich1cdef202009-05-22 12:06:27 -0700129
Jack Palevich2db168f2009-06-11 14:29:47 -0700130 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 }
Jack Palevich1cdef202009-05-22 12:06:27 -0700141 }
142
Jack Palevichac0e95e2009-05-29 13:53:44 -0700143exit:
144
Jack Palevich1cdef202009-05-22 12:06:27 -0700145 accDeleteScript(script);
146
147 return result;
148}