blob: a8505cd254294eba1a5b40017bb2fbd6c1966c4f [file] [log] [blame]
Jack Palevichae54f1f2009-05-08 14:54:15 -07001/*
2 **
3 ** Copyright 2009, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
Jack Palevich88311482009-05-08 13:57:37 -070017
Jack Palevichae54f1f2009-05-08 14:54:15 -070018/* Based upon the freeware version of the Obfuscated Tiny C Compiler
Jack Palevichd1605302009-05-08 15:26:24 -070019 * by Francis Bellard. <francis@bellard.org>.
Jack Palevichae54f1f2009-05-08 14:54:15 -070020 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
Jack Palevichf0cbc922009-05-08 16:35:13 -070026#define TOKEN_OPERATOR 1
27#define TOKEN_NUMBER 2
Jack Palevich7448a2e2009-05-08 18:33:45 -070028
29#define TOKEN_SYMBOL_BASE 256
30#define TOKEN_INT 256
31#define TOKEN_IF 288
32#define TOKEN_ELSE 312
33#define TOKEN_WHILE 352
34#define TOKEN_BREAK 400
35#define TOKEN_RETURN 448
36#define TOKEN_FOR 504
37#define TOKEN_DEFINE 536
Jack Palevichf0cbc922009-05-08 16:35:13 -070038
39static int currentToken;
40static int currentTokenData;
Jack Palevich431055c2009-05-08 19:50:15 -070041static int gCurrentTokenOperatorLevel;
Jack Palevichf0cbc922009-05-08 16:35:13 -070042static int currentChar;
Jack Palevich431055c2009-05-08 19:50:15 -070043static int gEndOfFunctionTarget;
44static int gProgramCounter;
45static int gFunctionStackSize;
Jack Palevichf0cbc922009-05-08 16:35:13 -070046static int savedChar;
47static char* pInProgressMacro;
Jack Palevich50791f52009-05-08 15:44:22 -070048static char* P;
49static char* ac;
Jack Palevich431055c2009-05-08 19:50:15 -070050static char* gStringTable;
Jack Palevichf0cbc922009-05-08 16:35:13 -070051static char* pSymbolTable;
Jack Palevich50791f52009-05-08 15:44:22 -070052static char* M;
53static char* R;
Jack Palevichf0cbc922009-05-08 16:35:13 -070054static FILE* pInput;
Jack Palevichae54f1f2009-05-08 14:54:15 -070055
Jack Palevich7448a2e2009-05-08 18:33:45 -070056static void parseDeclarations (int isLocal);
57static void parseExpression();
Jack Palevichae54f1f2009-05-08 14:54:15 -070058
Jack Palevich50791f52009-05-08 15:44:22 -070059static void addToSymbolTable(char e) {
Jack Palevichf0cbc922009-05-08 16:35:13 -070060 *pSymbolTable++ = e;
Jack Palevich88311482009-05-08 13:57:37 -070061}
Jack Palevichae54f1f2009-05-08 14:54:15 -070062
Jack Palevichf0cbc922009-05-08 16:35:13 -070063static void nextChar() {
64 if (pInProgressMacro) {
65 currentChar = *(char*) pInProgressMacro++;
66 if (currentChar == 2) {
67 pInProgressMacro = NULL;
68 currentChar = savedChar;
Jack Palevichae54f1f2009-05-08 14:54:15 -070069 }
70 } else
Jack Palevichf0cbc922009-05-08 16:35:13 -070071 currentChar = fgetc(pInput);
Jack Palevich88311482009-05-08 13:57:37 -070072}
Jack Palevichae54f1f2009-05-08 14:54:15 -070073
Jack Palevichf0cbc922009-05-08 16:35:13 -070074static int isSymbolChar() {
75 return isalnum(currentChar) || currentChar == '_';
Jack Palevich88311482009-05-08 13:57:37 -070076}
Jack Palevichae54f1f2009-05-08 14:54:15 -070077
Jack Palevichf0cbc922009-05-08 16:35:13 -070078static void unescapeCurrentChar() {
79 if (currentChar == '\\') {
80 nextChar();
81 if (currentChar == 'n')
82 currentChar = '\n';
Jack Palevichae54f1f2009-05-08 14:54:15 -070083 }
Jack Palevich88311482009-05-08 13:57:37 -070084}
Jack Palevichae54f1f2009-05-08 14:54:15 -070085
Jack Palevichf0cbc922009-05-08 16:35:13 -070086static void nextToken() {
Jack Palevichae54f1f2009-05-08 14:54:15 -070087 int j, m;
Jack Palevichf0cbc922009-05-08 16:35:13 -070088 while (isspace(currentChar) || currentChar == '#') {
89 if (currentChar == '#') {
90 nextChar();
91 nextToken();
92 if (currentToken == TOKEN_DEFINE) {
93 nextToken();
94 addToSymbolTable(' ');
95 *(int*) currentToken = 1;
96 *(int*) (currentToken + 4) = (int) pSymbolTable;
Jack Palevichae54f1f2009-05-08 14:54:15 -070097 }
Jack Palevichf0cbc922009-05-08 16:35:13 -070098 while (currentChar != '\n') {
99 addToSymbolTable(currentChar);
100 nextChar();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700101 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700102 addToSymbolTable(currentChar);
Jack Palevich50791f52009-05-08 15:44:22 -0700103 addToSymbolTable(2);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700104 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700105 nextChar();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700106 }
Jack Palevich431055c2009-05-08 19:50:15 -0700107 gCurrentTokenOperatorLevel = 0;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700108 currentToken = currentChar;
109 if (isSymbolChar()) {
110 addToSymbolTable(' ');
111 M = pSymbolTable;
112 while (isSymbolChar()) {
113 addToSymbolTable(currentChar);
114 nextChar();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700115 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700116 if (isdigit(currentToken)) {
117 currentTokenData = strtol(M, 0, 0);
118 currentToken = TOKEN_NUMBER;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700119 } else {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700120 *(char*) pSymbolTable = ' ';
121 currentToken = strstr(R, M - 1) - R;
122 *(char*) pSymbolTable = 0;
Jack Palevich7448a2e2009-05-08 18:33:45 -0700123 currentToken = currentToken * 8 + TOKEN_SYMBOL_BASE;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700124 if (currentToken > TOKEN_DEFINE) {
125 currentToken = ((int) P) + currentToken;
126 if (*(int*) currentToken == 1) {
127 pInProgressMacro = (char*) (*(int*) (currentToken + 4));
128 savedChar = currentChar;
129 nextChar();
130 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700131 }
132 }
133 }
134 } else {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700135 nextChar();
136 if (currentToken == '\'') {
137 currentToken = TOKEN_NUMBER;
138 unescapeCurrentChar();
139 currentTokenData = currentChar;
140 nextChar();
141 nextChar();
142 } else if (currentToken == '/' & currentChar == '*') {
143 nextChar();
144 while (currentChar) {
145 while (currentChar != '*')
146 nextChar();
147 nextChar();
148 if (currentChar == '/')
149 currentChar = 0;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700150 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700151 nextChar();
152 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700153 } else {
154 char* e = "++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b";
155 while (j = *(char*) e++) {
156 m = *(char*) e++;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700157 currentTokenData = 0;
Jack Palevich431055c2009-05-08 19:50:15 -0700158 while ((gCurrentTokenOperatorLevel = *(char*) e++ - 98) < 0)
159 currentTokenData = currentTokenData * 64 + gCurrentTokenOperatorLevel + 64;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700160 if (j == currentToken && (m == currentChar || m == 64)) {
161 if (m == currentChar) {
162 nextChar();
163 currentToken = TOKEN_OPERATOR;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700164 }
165 break;
166 }
167 }
168 }
169 }
Jack Palevich88311482009-05-08 13:57:37 -0700170}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700171
Jack Palevich7448a2e2009-05-08 18:33:45 -0700172/*
173 * Emit 1 to 4 bytes of code. Little-endian, doesn't emit high bytes that
Jack Palevich431055c2009-05-08 19:50:15 -0700174 * are 0x00 or 0xff
Jack Palevich7448a2e2009-05-08 18:33:45 -0700175 */
176static void emitCode(int g) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700177 while( g && g != -1) {
Jack Palevich431055c2009-05-08 19:50:15 -0700178 *(char*) gProgramCounter++=g;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700179 g=g>>8;
180 }
Jack Palevich88311482009-05-08 13:57:37 -0700181}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700182
Jack Palevich7448a2e2009-05-08 18:33:45 -0700183static void fixupAddress(e) {
Jack Palevichae54f1f2009-05-08 14:54:15 -0700184 int g;
185 while( e) {
186 g=*(int*) e;
Jack Palevich431055c2009-05-08 19:50:15 -0700187 *(int*) e=gProgramCounter-e-4;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700188 e=g;
189 }
Jack Palevich88311482009-05-08 13:57:37 -0700190}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700191
Jack Palevich7448a2e2009-05-08 18:33:45 -0700192static int emitCodeWithImmediate( g, e) {
193 emitCode(g);
Jack Palevich431055c2009-05-08 19:50:15 -0700194 *(int*) gProgramCounter = e;
195 e = gProgramCounter;
196 gProgramCounter = gProgramCounter + 4;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700197 return e;
Jack Palevich88311482009-05-08 13:57:37 -0700198}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700199
Jack Palevich7448a2e2009-05-08 18:33:45 -0700200static int emitLoadAccumulatorImmediate(e) {
201 emitCodeWithImmediate(0xb8,e); /* Move immediate a, e */
Jack Palevich88311482009-05-08 13:57:37 -0700202}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700203
Jack Palevich7448a2e2009-05-08 18:33:45 -0700204static int emitBranch(e) {
205 return emitCodeWithImmediate(0xe9,e); /* Jump relative */
Jack Palevich88311482009-05-08 13:57:37 -0700206}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700207
Jack Palevich431055c2009-05-08 19:50:15 -0700208static int emitTest( j, e) {
209 emitCode(0x0FC085); /* 85 C0 FC TEST */
Jack Palevich7448a2e2009-05-08 18:33:45 -0700210 return emitCodeWithImmediate(0x84 + j, e); /* TEST */
Jack Palevich88311482009-05-08 13:57:37 -0700211}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700212
Jack Palevich431055c2009-05-08 19:50:15 -0700213static void emitSetCC(int condition) {
214 emitCode( 0xC139); /* 39 C1 CMP */
Jack Palevich7448a2e2009-05-08 18:33:45 -0700215 emitLoadAccumulatorImmediate(0);
Jack Palevich431055c2009-05-08 19:50:15 -0700216 emitCode( 0x0F); /* Two byte opcode prefix */
217 emitCode( condition+0x90); /* Set byte on condition (controlled by e) */
218 emitCode( 0xC0); /* I think this is part of the SETcc instruction */
Jack Palevich88311482009-05-08 13:57:37 -0700219}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700220
Jack Palevich431055c2009-05-08 19:50:15 -0700221static void emitNumericOp( int op, int e) {
222 emitCode(op + 0x83);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700223 emitCodeWithImmediate((e < 512) << 7 | 5, e);
Jack Palevich88311482009-05-08 13:57:37 -0700224}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700225
Jack Palevich431055c2009-05-08 19:50:15 -0700226static void parseTerminal (int level) {
Jack Palevichae54f1f2009-05-08 14:54:15 -0700227 int g,e,m,aa;
228 g=1;
Jack Palevich7448a2e2009-05-08 18:33:45 -0700229 if( currentToken == '"') {
Jack Palevich431055c2009-05-08 19:50:15 -0700230 emitLoadAccumulatorImmediate(gStringTable);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700231 while( currentChar != '"') {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700232 unescapeCurrentChar ();
Jack Palevich431055c2009-05-08 19:50:15 -0700233 *(char*) gStringTable++=currentChar;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700234 nextChar ();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700235 }
Jack Palevich431055c2009-05-08 19:50:15 -0700236 *(char*) gStringTable=0;
237 gStringTable= (char*) (((int)gStringTable) +4&-4);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700238 nextChar();
Jack Palevichf0cbc922009-05-08 16:35:13 -0700239 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700240 }
241 else {
Jack Palevich431055c2009-05-08 19:50:15 -0700242 aa=gCurrentTokenOperatorLevel;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700243 m= currentTokenData;
244 e=currentToken;
245 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700246 if( e == TOKEN_NUMBER) {
247 emitLoadAccumulatorImmediate(m);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700248 }
249 else if( aa == 2) {
Jack Palevich431055c2009-05-08 19:50:15 -0700250 parseTerminal(0);
251 emitCodeWithImmediate(0xB9,0); /* MOV r1, immediate */
252 if( e == '!')emitSetCC(m);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700253 else emitCode( m);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700254 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700255 else if( e == '(') {
256 parseExpression ();
Jack Palevichf0cbc922009-05-08 16:35:13 -0700257 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700258 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700259 else if( e == '*') {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700260 nextToken();
261 e=currentToken;
262 nextToken();
263 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700264 if( currentToken == '*') {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700265 nextToken();
266 nextToken();
267 nextToken();
268 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700269 e=0;
270 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700271 nextToken();
Jack Palevich431055c2009-05-08 19:50:15 -0700272 parseTerminal(0);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700273 if( currentToken == '=') {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700274 nextToken();
Jack Palevich431055c2009-05-08 19:50:15 -0700275 emitCode( 0x50); /* PUSH r0 */
Jack Palevich7448a2e2009-05-08 18:33:45 -0700276 parseExpression ();
Jack Palevich431055c2009-05-08 19:50:15 -0700277 emitCode( 0x59); /* POP r1 */
278 emitCode( 0x188 + (e == TOKEN_INT)); /* 88 01 MOV */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700279 }
280 else if( e) {
Jack Palevich431055c2009-05-08 19:50:15 -0700281 if( e == TOKEN_INT)emitCode( 0x8B); /* MOV */
282 else emitCode( 0xBE0F); /* 0F BE MOVSX move with sign extension */
283 gProgramCounter++;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700284 }
285 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700286 else if( e == '&') {
Jack Palevich431055c2009-05-08 19:50:15 -0700287 emitNumericOp(10,*(int*) currentToken); /* 8D LEA */
Jack Palevichf0cbc922009-05-08 16:35:13 -0700288 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700289 }
290 else {
291 g=*(int*) e;
292 if(!g)g=dlsym(0,M);
Jack Palevich431055c2009-05-08 19:50:15 -0700293 if( currentToken == '=' & level) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700294 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700295 parseExpression ();
Jack Palevich431055c2009-05-08 19:50:15 -0700296 emitNumericOp(6,g); /* 89 MOV */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700297 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700298 else if( currentToken!= '(') {
Jack Palevich431055c2009-05-08 19:50:15 -0700299 emitNumericOp(8,g); /* 8B MOV sreg */
300 if( gCurrentTokenOperatorLevel == 11) {
301 emitNumericOp(0,g); /* 83 ADD */
Jack Palevich7448a2e2009-05-08 18:33:45 -0700302 emitCode( currentTokenData);
Jack Palevichf0cbc922009-05-08 16:35:13 -0700303 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700304 }
305 }
306 }
307 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700308 if( currentToken == '(') {
Jack Palevich431055c2009-05-08 19:50:15 -0700309 if( g == 1)emitCode( 0x50); /* push */
310 m= emitCodeWithImmediate(0xEC81,0); /* 81 EC Cmp ?? */
Jack Palevichf0cbc922009-05-08 16:35:13 -0700311 nextToken();
Jack Palevich431055c2009-05-08 19:50:15 -0700312 level=0;
Jack Palevich7448a2e2009-05-08 18:33:45 -0700313 while( currentToken!= ')') {
314 parseExpression ();
Jack Palevich431055c2009-05-08 19:50:15 -0700315 emitCodeWithImmediate(0x248489,level); /* 89 84 24 MOV sp + level*/
Jack Palevich7448a2e2009-05-08 18:33:45 -0700316 if( currentToken == ',')nextToken();
Jack Palevich431055c2009-05-08 19:50:15 -0700317 level=level +4;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700318 }
Jack Palevich431055c2009-05-08 19:50:15 -0700319 *(int*) m= level;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700320 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700321 if(!g) {
322 e=e +4;
Jack Palevich431055c2009-05-08 19:50:15 -0700323 *(int*) e=emitCodeWithImmediate(0xE8,*(int*) e); /* Call */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700324 }
325 else if( g == 1) {
Jack Palevich431055c2009-05-08 19:50:15 -0700326 emitCodeWithImmediate(0x2494FF,level); /* FF 94 24 */
327 level=level +4;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700328 }
329 else {
Jack Palevich431055c2009-05-08 19:50:15 -0700330 emitCodeWithImmediate(0xE8,g-gProgramCounter-5); /* CALL */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700331 }
Jack Palevich431055c2009-05-08 19:50:15 -0700332 if( level)emitCodeWithImmediate(0xC481,level); /* 81 C4 adjust stack pointer */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700333 }
Jack Palevich88311482009-05-08 13:57:37 -0700334}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700335
Jack Palevich7448a2e2009-05-08 18:33:45 -0700336static void parseBinaryOp (int level) {
Jack Palevichae54f1f2009-05-08 14:54:15 -0700337 int e,g,m;
Jack Palevich431055c2009-05-08 19:50:15 -0700338 if( level--== 1)parseTerminal(1);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700339 else {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700340 parseBinaryOp (level);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700341 m= 0;
Jack Palevich431055c2009-05-08 19:50:15 -0700342 while( level == gCurrentTokenOperatorLevel) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700343 g=currentToken;
344 e=currentTokenData;
345 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700346 if( level>8) {
Jack Palevich431055c2009-05-08 19:50:15 -0700347 m= emitTest(e,m);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700348 parseBinaryOp (level);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700349 }
350 else {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700351 emitCode( 0x50);
352 parseBinaryOp (level);
353 emitCode( 0x59);
354 if( level == 4 | level == 5) {
Jack Palevich431055c2009-05-08 19:50:15 -0700355 emitSetCC(e);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700356 }
357 else {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700358 emitCode( e);
Jack Palevich431055c2009-05-08 19:50:15 -0700359 if( g == '%')emitCode( 0x92); /* XCHG */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700360 }
361 }
362 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700363 if( m&&level>8) {
Jack Palevich431055c2009-05-08 19:50:15 -0700364 m= emitTest(e,m);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700365 emitLoadAccumulatorImmediate(e^1);
Jack Palevich431055c2009-05-08 19:50:15 -0700366 emitBranch(5); /* Jump relative +5 */
Jack Palevich7448a2e2009-05-08 18:33:45 -0700367 fixupAddress(m);
368 emitLoadAccumulatorImmediate(e);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700369 }
370 }
Jack Palevich88311482009-05-08 13:57:37 -0700371}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700372
Jack Palevich7448a2e2009-05-08 18:33:45 -0700373static void parseExpression() {
374 parseBinaryOp(11);
Jack Palevich88311482009-05-08 13:57:37 -0700375}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700376
Jack Palevich431055c2009-05-08 19:50:15 -0700377static int parseExpressionEmitTest() {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700378 parseExpression();
Jack Palevich431055c2009-05-08 19:50:15 -0700379 return emitTest(0, 0);
Jack Palevich88311482009-05-08 13:57:37 -0700380}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700381
Jack Palevich7448a2e2009-05-08 18:33:45 -0700382static void parseStatement (int* pBreakTarget) {
Jack Palevichae54f1f2009-05-08 14:54:15 -0700383 int m,g,e;
Jack Palevich7448a2e2009-05-08 18:33:45 -0700384 if( currentToken == TOKEN_IF) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700385 nextToken();
386 nextToken();
Jack Palevich431055c2009-05-08 19:50:15 -0700387 m= parseExpressionEmitTest ();
Jack Palevichf0cbc922009-05-08 16:35:13 -0700388 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700389 parseStatement (pBreakTarget);
390 if( currentToken == TOKEN_ELSE) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700391 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700392 g=emitBranch(0);
393 fixupAddress(m);
394 parseStatement (pBreakTarget);
395 fixupAddress(g);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700396 }
397 else {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700398 fixupAddress(m);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700399 }
400 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700401 else if ( currentToken == TOKEN_WHILE || currentToken == TOKEN_FOR) {
402 e = currentToken;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700403 nextToken();
404 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700405 if( e == TOKEN_WHILE) {
Jack Palevich431055c2009-05-08 19:50:15 -0700406 g=gProgramCounter;
407 m= parseExpressionEmitTest ();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700408 }
409 else {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700410 if( currentToken != ';')parseExpression ();
Jack Palevichf0cbc922009-05-08 16:35:13 -0700411 nextToken();
Jack Palevich431055c2009-05-08 19:50:15 -0700412 g=gProgramCounter;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700413 m= 0;
Jack Palevich431055c2009-05-08 19:50:15 -0700414 if( currentToken != ';')m= parseExpressionEmitTest ();
Jack Palevichf0cbc922009-05-08 16:35:13 -0700415 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700416 if( currentToken!= ')') {
417 e=emitBranch(0);
418 parseExpression ();
Jack Palevich431055c2009-05-08 19:50:15 -0700419 emitBranch(g-gProgramCounter-5);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700420 fixupAddress(e);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700421 g=e +4;
422 }
423 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700424 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700425 parseStatement(&m);
Jack Palevich431055c2009-05-08 19:50:15 -0700426 emitBranch(g-gProgramCounter-5);
Jack Palevich7448a2e2009-05-08 18:33:45 -0700427 fixupAddress(m);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700428 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700429 else if( currentToken == '{') {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700430 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700431 parseDeclarations(1);
432 while( currentToken != '}') parseStatement(pBreakTarget);
Jack Palevichf0cbc922009-05-08 16:35:13 -0700433 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700434 }
435 else {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700436 if( currentToken == TOKEN_RETURN) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700437 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700438 if( currentToken != ';') parseExpression();
Jack Palevich431055c2009-05-08 19:50:15 -0700439 gEndOfFunctionTarget=emitBranch(gEndOfFunctionTarget);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700440 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700441 else if( currentToken == TOKEN_BREAK) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700442 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700443 *pBreakTarget = emitBranch(*pBreakTarget);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700444 }
Jack Palevich7448a2e2009-05-08 18:33:45 -0700445 else if( currentToken != ';') parseExpression();
Jack Palevichf0cbc922009-05-08 16:35:13 -0700446 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700447 }
Jack Palevich88311482009-05-08 13:57:37 -0700448}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700449
Jack Palevich7448a2e2009-05-08 18:33:45 -0700450static void parseDeclarations (int isLocal) {
Jack Palevichae54f1f2009-05-08 14:54:15 -0700451 int m;
Jack Palevich7448a2e2009-05-08 18:33:45 -0700452 while( currentToken == TOKEN_INT | currentToken != -1 & !isLocal ) {
453 if( currentToken == TOKEN_INT) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700454 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700455 while( currentToken != ';') {
456 if( isLocal ) {
Jack Palevich431055c2009-05-08 19:50:15 -0700457 gFunctionStackSize=gFunctionStackSize +4;
458 *(int*) currentToken=-gFunctionStackSize;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700459 }
460 else {
Jack Palevich431055c2009-05-08 19:50:15 -0700461 *(char**) currentToken = gStringTable;
462 gStringTable=gStringTable +4;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700463 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700464 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700465 if( currentToken == ',')nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700466 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700467 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700468 }
469 else {
Jack Palevich7448a2e2009-05-08 18:33:45 -0700470 fixupAddress(*(int*)(currentToken + 4));
Jack Palevich431055c2009-05-08 19:50:15 -0700471 *(int*) currentToken=gProgramCounter;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700472 nextToken();
473 nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700474 m= 8;
Jack Palevich7448a2e2009-05-08 18:33:45 -0700475 while( currentToken != ')') {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700476 *(int*) currentToken=m;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700477 m= m +4;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700478 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700479 if( currentToken == ',')nextToken();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700480 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700481 nextToken();
Jack Palevich431055c2009-05-08 19:50:15 -0700482 gEndOfFunctionTarget=gFunctionStackSize=0;
483 emitCode( 0xE58955); /* 55 89 E5 PUSH */
484 m= emitCodeWithImmediate(0xEC81,0); /* 81 EC */
Jack Palevich7448a2e2009-05-08 18:33:45 -0700485 parseStatement(0);
Jack Palevich431055c2009-05-08 19:50:15 -0700486 fixupAddress(gEndOfFunctionTarget);
487 emitCode( 0xC3C9); /* C9 C3 LEAVE */
488 *(int*) m= gFunctionStackSize;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700489 }
490 }
Jack Palevich88311482009-05-08 13:57:37 -0700491}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700492
493int main( int argc, char** argv) {
Jack Palevichf0cbc922009-05-08 16:35:13 -0700494 pInput = stdin;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700495 if (argc-- > 1) {
496 char* file = argv[1];
497 argv += 1;
Jack Palevichf0cbc922009-05-08 16:35:13 -0700498 pInput = fopen(file, "r");
499 if (pInput == NULL) {
Jack Palevichae54f1f2009-05-08 14:54:15 -0700500 fprintf(stderr, "Could not open file \"%s\"\n", file);
501 return -1;
502 }
503 }
Jack Palevichf0cbc922009-05-08 16:35:13 -0700504 pSymbolTable = strcpy(R = calloc(1, 99999),
Jack Palevichae54f1f2009-05-08 14:54:15 -0700505 " int if else while break return for define main ") + 48;
Jack Palevich431055c2009-05-08 19:50:15 -0700506 gStringTable = calloc(1, 99999);
Jack Palevichd1605302009-05-08 15:26:24 -0700507 ac = calloc(1, 99999);
Jack Palevich431055c2009-05-08 19:50:15 -0700508 gProgramCounter = (int) ac;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700509 P = calloc(1, 99999);
Jack Palevichf0cbc922009-05-08 16:35:13 -0700510 nextChar();
511 nextToken();
Jack Palevich7448a2e2009-05-08 18:33:45 -0700512 parseDeclarations(0);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700513#if 1
514 fwrite(R, 1, 99999, stdout);
515 fwrite(ac, 1, 99999, stdout);
516 fwrite(P, 1, 99999, stdout);
517 return 0;
518#else
Jack Palevich431055c2009-05-08 19:50:15 -0700519 /* Look up the address of "main" in the symbol table and call it.
520 * We put main in at a known offset, so we know the address.
521 */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700522 return (*(int(*)()) *(int*) (P + 592))(argc, argv);
523#endif
Jack Palevich88311482009-05-08 13:57:37 -0700524}
525