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