blob: 248c3822a79688070b9314d0a47f2f501fa39872 [file] [log] [blame]
Jack Palevichae54f1f2009-05-08 14:54:15 -07001/*
Jack Paleviche27bf3e2009-05-10 14:09:03 -07002 Obfuscated Tiny C Compiler
Jack Palevich88311482009-05-08 13:57:37 -07003
Jack Paleviche27bf3e2009-05-10 14:09:03 -07004 Copyright (C) 2001-2003 Fabrice Bellard
Jack Palevichae54f1f2009-05-08 14:54:15 -07005
Jack Paleviche27bf3e2009-05-10 14:09:03 -07006 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
9
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
13
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
Jack Palevichbbf8ab52009-05-11 11:54:30 -070016 in a product, an acknowledgment in the product and its documentation
Jack Paleviche27bf3e2009-05-10 14:09:03 -070017 *is* required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
21*/
22
Jack Palevich77ae76e2009-05-10 19:59:24 -070023#include <ctype.h>
24#include <dlfcn.h>
Jack Paleviche27bf3e2009-05-10 14:09:03 -070025#include <stdarg.h>
Jack Palevichae54f1f2009-05-08 14:54:15 -070026#include <stdio.h>
Jack Palevichf6b5a532009-05-10 19:16:42 -070027#include <stdlib.h>
28#include <string.h>
Jack Palevichae54f1f2009-05-08 14:54:15 -070029
Jack Palevichbbf8ab52009-05-11 11:54:30 -070030namespace acc {
31
Jack Palevich77ae76e2009-05-10 19:59:24 -070032class compiler {
Jack Palevichbbf8ab52009-05-11 11:54:30 -070033/* vars: value of variables
Jack Paleviche27bf3e2009-05-10 14:09:03 -070034 loc : local variable index
35 glo : global variable index
36 ind : output code ptr
37 rsym: return symbol
38 prog: output code
39 dstk: define stack
40 dptr, dch: macro state
41*/
Jack Palevichf6b5a532009-05-10 19:16:42 -070042int tok, tokc, tokl, ch, vars, rsym, prog, ind, loc, glo, sym_stk, dstk, dptr, dch, last_id;
43FILE* file;
Jack Palevich7448a2e2009-05-08 18:33:45 -070044
Jack Paleviche27bf3e2009-05-10 14:09:03 -070045#define ALLOC_SIZE 99999
Jack Palevichf0cbc922009-05-08 16:35:13 -070046
Jack Paleviche27bf3e2009-05-10 14:09:03 -070047/* depends on the init string */
48#define TOK_STR_SIZE 48
49#define TOK_IDENT 0x100
50#define TOK_INT 0x100
51#define TOK_IF 0x120
52#define TOK_ELSE 0x138
53#define TOK_WHILE 0x160
54#define TOK_BREAK 0x190
55#define TOK_RETURN 0x1c0
56#define TOK_FOR 0x1f8
57#define TOK_DEFINE 0x218
58#define TOK_MAIN 0x250
Jack Palevichae54f1f2009-05-08 14:54:15 -070059
Jack Paleviche27bf3e2009-05-10 14:09:03 -070060#define TOK_DUMMY 1
61#define TOK_NUM 2
Jack Palevichae54f1f2009-05-08 14:54:15 -070062
Jack Paleviche27bf3e2009-05-10 14:09:03 -070063#define LOCAL 0x200
64
65#define SYM_FORWARD 0
66#define SYM_DEFINE 1
67
68/* tokens in string heap */
69#define TAG_TOK ' '
70#define TAG_MACRO 2
71
Jack Palevich77ae76e2009-05-10 19:59:24 -070072void pdef(int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -070073{
74 *(char *)dstk++ = t;
Jack Palevich88311482009-05-08 13:57:37 -070075}
Jack Palevichae54f1f2009-05-08 14:54:15 -070076
Jack Palevich77ae76e2009-05-10 19:59:24 -070077void inp()
Jack Paleviche27bf3e2009-05-10 14:09:03 -070078{
79 if (dptr) {
80 ch = *(char *)dptr++;
81 if (ch == TAG_MACRO) {
82 dptr = 0;
83 ch = dch;
Jack Palevichae54f1f2009-05-08 14:54:15 -070084 }
85 } else
Jack Paleviche27bf3e2009-05-10 14:09:03 -070086 ch = fgetc(file);
87 /* printf("ch=%c 0x%x\n", ch, ch); */
Jack Palevich88311482009-05-08 13:57:37 -070088}
Jack Palevichae54f1f2009-05-08 14:54:15 -070089
Jack Palevich77ae76e2009-05-10 19:59:24 -070090int isid()
Jack Paleviche27bf3e2009-05-10 14:09:03 -070091{
92 return isalnum(ch) | ch == '_';
Jack Palevich88311482009-05-08 13:57:37 -070093}
Jack Palevichae54f1f2009-05-08 14:54:15 -070094
Jack Paleviche27bf3e2009-05-10 14:09:03 -070095/* read a character constant */
Jack Palevich77ae76e2009-05-10 19:59:24 -070096void getq()
Jack Paleviche27bf3e2009-05-10 14:09:03 -070097{
98 if (ch == '\\') {
99 inp();
100 if (ch == 'n')
101 ch = '\n';
Jack Palevichae54f1f2009-05-08 14:54:15 -0700102 }
Jack Palevich88311482009-05-08 13:57:37 -0700103}
Jack Palevichae54f1f2009-05-08 14:54:15 -0700104
Jack Palevich77ae76e2009-05-10 19:59:24 -0700105void next()
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700106{
Jack Palevichf6b5a532009-05-10 19:16:42 -0700107 int l, a;
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700108
109 while (isspace(ch) | ch == '#') {
110 if (ch == '#') {
111 inp();
112 next();
113 if (tok == TOK_DEFINE) {
114 next();
115 pdef(TAG_TOK); /* fill last ident tag */
116 *(int *)tok = SYM_DEFINE;
117 *(int *)(tok + 4) = dstk; /* define stack */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700118 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700119 /* well we always save the values ! */
120 while (ch != '\n') {
121 pdef(ch);
122 inp();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700123 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700124 pdef(ch);
125 pdef(TAG_MACRO);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700126 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700127 inp();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700128 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700129 tokl = 0;
130 tok = ch;
131 /* encode identifiers & numbers */
132 if (isid()) {
133 pdef(TAG_TOK);
134 last_id = dstk;
135 while (isid()) {
136 pdef(ch);
137 inp();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700138 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700139 if (isdigit(tok)) {
Jack Palevichf6b5a532009-05-10 19:16:42 -0700140 tokc = strtol((char*) last_id, 0, 0);
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700141 tok = TOK_NUM;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700142 } else {
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700143 *(char *)dstk = TAG_TOK; /* no need to mark end of string (we
144 suppose data is initied to zero */
Jack Palevichf6b5a532009-05-10 19:16:42 -0700145 tok = (int) (strstr((char*) sym_stk, (char*) (last_id - 1)) - sym_stk);
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700146 *(char *)dstk = 0; /* mark real end of ident for dlsym() */
147 tok = tok * 8 + TOK_IDENT;
148 if (tok > TOK_DEFINE) {
149 tok = vars + tok;
150 /* printf("tok=%s %x\n", last_id, tok); */
151 /* define handling */
152 if (*(int *)tok == SYM_DEFINE) {
153 dptr = *(int *)(tok + 4);
154 dch = ch;
155 inp();
156 next();
Jack Palevichae54f1f2009-05-08 14:54:15 -0700157 }
158 }
159 }
160 } else {
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700161 inp();
162 if (tok == '\'') {
163 tok = TOK_NUM;
164 getq();
165 tokc = ch;
166 inp();
167 inp();
168 } else if (tok == '/' & ch == '*') {
169 inp();
170 while (ch) {
171 while (ch != '*')
172 inp();
173 inp();
174 if (ch == '/')
175 ch = 0;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700176 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700177 inp();
178 next();
179 } else
180 {
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700181 const char* t = "++#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";
182 while (l = *t++) {
183 a = *t++;
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700184 tokc = 0;
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700185 while ((tokl = *t++ - 'b') < 0)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700186 tokc = tokc * 64 + tokl + 64;
187 if (l == tok & (a == ch | a == '@')) {
188#if 0
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700189 printf("%c%c -> tokl=%d tokc=0x%x\n",
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700190 l, a, tokl, tokc);
191#endif
192 if (a == ch) {
193 inp();
194 tok = TOK_DUMMY; /* dummy token for double tokens */
Jack Palevichae54f1f2009-05-08 14:54:15 -0700195 }
196 break;
197 }
198 }
199 }
200 }
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700201#if 0
202 {
203 int p;
Jack Palevichae54f1f2009-05-08 14:54:15 -0700204
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700205 printf("tok=0x%x ", tok);
206 if (tok >= TOK_IDENT) {
207 printf("'");
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700208 if (tok > TOK_DEFINE)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700209 p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8;
210 else
211 p = sym_stk + 1 + (tok - TOK_IDENT) / 8;
212 while (*(char *)p != TAG_TOK && *(char *)p)
213 printf("%c", *(char *)p++);
214 printf("'\n");
215 } else if (tok == TOK_NUM) {
216 printf("%d\n", tokc);
217 } else {
218 printf("'%c'\n", tok);
Jack Palevichae54f1f2009-05-08 14:54:15 -0700219 }
220 }
Jack Palevichae54f1f2009-05-08 14:54:15 -0700221#endif
Jack Palevich88311482009-05-08 13:57:37 -0700222}
223
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700224void error(const char *fmt,...)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700225{
226 va_list ap;
227
228 va_start(ap, fmt);
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700229 fprintf(stderr, "%ld: ", ftell((FILE *)file));
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700230 vfprintf(stderr, fmt, ap);
231 fprintf(stderr, "\n");
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700232 va_end(ap);
Jack Palevich77ae76e2009-05-10 19:59:24 -0700233 exit(1);
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700234}
235
Jack Palevich77ae76e2009-05-10 19:59:24 -0700236void skip(int c)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700237{
238 if (tok != c) {
239 error("'%c' expected", c);
240 }
241 next();
242}
243
Jack Palevich77ae76e2009-05-10 19:59:24 -0700244void o(int n)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700245{
246 /* cannot use unsigned, so we must do a hack */
247 while (n && n != -1) {
248 *(char *)ind++ = n;
249 n = n >> 8;
250 }
251}
252
253/* output a symbol and patch all calls to it */
Jack Palevich77ae76e2009-05-10 19:59:24 -0700254void gsym(int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700255{
256 int n;
257 while (t) {
258 n = *(int *)t; /* next value */
259 *(int *)t = ind - t - 4;
260 t = n;
261 }
262}
263
264/* psym is used to put an instruction with a data field which is a
265 reference to a symbol. It is in fact the same as oad ! */
266#define psym oad
267
268/* instruction + address */
Jack Palevich77ae76e2009-05-10 19:59:24 -0700269int oad(int n, int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700270{
271 o(n);
272 *(int *)ind = t;
273 t = ind;
274 ind = ind + 4;
275 return t;
276}
277
278/* load immediate value */
Jack Palevich77ae76e2009-05-10 19:59:24 -0700279int li(int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700280{
281 oad(0xb8, t); /* mov $xx, %eax */
282}
283
Jack Palevich77ae76e2009-05-10 19:59:24 -0700284int gjmp(int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700285{
286 return psym(0xe9, t);
287}
288
289/* l = 0: je, l == 1: jne */
Jack Palevich77ae76e2009-05-10 19:59:24 -0700290int gtst(int l, int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700291{
292 o(0x0fc085); /* test %eax, %eax, je/jne xxx */
293 return psym(0x84 + l, t);
294}
295
Jack Palevich77ae76e2009-05-10 19:59:24 -0700296int gcmp(int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700297{
298 o(0xc139); /* cmp %eax,%ecx */
299 li(0);
300 o(0x0f); /* setxx %al */
301 o(t + 0x90);
302 o(0xc0);
303}
304
Jack Palevich77ae76e2009-05-10 19:59:24 -0700305int gmov(int l, int t)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700306{
307 o(l + 0x83);
308 oad((t < LOCAL) << 7 | 5, t);
309}
310
311/* l is one if '=' parsing wanted (quick hack) */
Jack Palevich77ae76e2009-05-10 19:59:24 -0700312void unary(int l)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700313{
314 int n, t, a, c;
315
316 n = 1; /* type of expression 0 = forward, 1 = value, other =
317 lvalue */
318 if (tok == '\"') {
319 li(glo);
320 while (ch != '\"') {
321 getq();
322 *(char *)glo++ = ch;
323 inp();
324 }
325 *(char *)glo = 0;
326 glo = glo + 4 & -4; /* align heap */
327 inp();
328 next();
329 } else {
330 c = tokl;
331 a = tokc;
332 t = tok;
333 next();
334 if (t == TOK_NUM) {
335 li(a);
336 } else if (c == 2) {
337 /* -, +, !, ~ */
338 unary(0);
339 oad(0xb9, 0); /* movl $0, %ecx */
340 if (t == '!')
341 gcmp(a);
342 else
343 o(a);
344 } else if (t == '(') {
345 expr();
346 skip(')');
347 } else if (t == '*') {
348 /* parse cast */
349 skip('(');
350 t = tok; /* get type */
351 next(); /* skip int/char/void */
352 next(); /* skip '*' or '(' */
353 if (tok == '*') {
354 /* function type */
355 skip('*');
356 skip(')');
357 skip('(');
358 skip(')');
359 t = 0;
360 }
361 skip(')');
362 unary(0);
363 if (tok == '=') {
364 next();
365 o(0x50); /* push %eax */
366 expr();
367 o(0x59); /* pop %ecx */
368 o(0x0188 + (t == TOK_INT)); /* movl %eax/%al, (%ecx) */
369 } else if (t) {
370 if (t == TOK_INT)
371 o(0x8b); /* mov (%eax), %eax */
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700372 else
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700373 o(0xbe0f); /* movsbl (%eax), %eax */
374 ind++; /* add zero in code */
375 }
376 } else if (t == '&') {
377 gmov(10, *(int *)tok); /* leal EA, %eax */
378 next();
379 } else {
380 n = *(int *)t;
381 /* forward reference: try dlsym */
382 if (!n)
Jack Palevich77ae76e2009-05-10 19:59:24 -0700383 n = (int) dlsym(0, (char*) last_id);
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700384 if (tok == '=' & l) {
385 /* assignment */
386 next();
387 expr();
388 gmov(6, n); /* mov %eax, EA */
389 } else if (tok != '(') {
390 /* variable */
391 gmov(8, n); /* mov EA, %eax */
392 if (tokl == 11) {
393 gmov(0, n);
394 o(tokc);
395 next();
396 }
397 }
398 }
399 }
400
401 /* function call */
402 if (tok == '(') {
403 if (n == 1)
404 o(0x50); /* push %eax */
405
406 /* push args and invert order */
407 a = oad(0xec81, 0); /* sub $xxx, %esp */
408 next();
409 l = 0;
410 while(tok != ')') {
411 expr();
412 oad(0x248489, l); /* movl %eax, xxx(%esp) */
413 if (tok == ',')
414 next();
415 l = l + 4;
416 }
417 *(int *)a = l;
418 next();
419 if (!n) {
420 /* forward reference */
421 t = t + 4;
422 *(int *)t = psym(0xe8, *(int *)t);
423 } else if (n == 1) {
424 oad(0x2494ff, l); /* call *xxx(%esp) */
425 l = l + 4;
426 } else {
427 oad(0xe8, n - ind - 5); /* call xxx */
428 }
429 if (l)
430 oad(0xc481, l); /* add $xxx, %esp */
431 }
432}
433
Jack Palevich77ae76e2009-05-10 19:59:24 -0700434void sum(int l)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700435{
436 int t, n, a;
437
438 if (l-- == 1)
439 unary(1);
440 else {
441 sum(l);
442 a = 0;
443 while (l == tokl) {
444 n = tok;
445 t = tokc;
446 next();
447
448 if (l > 8) {
449 a = gtst(t, a); /* && and || output code generation */
450 sum(l);
451 } else {
452 o(0x50); /* push %eax */
453 sum(l);
454 o(0x59); /* pop %ecx */
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700455
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700456 if (l == 4 | l == 5) {
457 gcmp(t);
458 } else {
459 o(t);
460 if (n == '%')
461 o(0x92); /* xchg %edx, %eax */
462 }
463 }
464 }
465 /* && and || output code generation */
466 if (a && l > 8) {
467 a = gtst(t, a);
468 li(t ^ 1);
469 gjmp(5); /* jmp $ + 5 */
470 gsym(a);
471 li(t);
472 }
473 }
474}
475
Jack Palevich77ae76e2009-05-10 19:59:24 -0700476void expr()
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700477{
478 sum(11);
479}
480
481
Jack Palevich77ae76e2009-05-10 19:59:24 -0700482int test_expr()
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700483{
484 expr();
485 return gtst(0, 0);
486}
487
Jack Palevich77ae76e2009-05-10 19:59:24 -0700488
489void block(int l)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700490{
491 int a, n, t;
492
493 if (tok == TOK_IF) {
494 next();
495 skip('(');
496 a = test_expr();
497 skip(')');
498 block(l);
499 if (tok == TOK_ELSE) {
500 next();
501 n = gjmp(0); /* jmp */
502 gsym(a);
503 block(l);
504 gsym(n); /* patch else jmp */
505 } else {
506 gsym(a); /* patch if test */
507 }
508 } else if (tok == TOK_WHILE | tok == TOK_FOR) {
509 t = tok;
510 next();
511 skip('(');
512 if (t == TOK_WHILE) {
513 n = ind;
514 a = test_expr();
515 } else {
516 if (tok != ';')
517 expr();
518 skip(';');
519 n = ind;
520 a = 0;
521 if (tok != ';')
522 a = test_expr();
523 skip(';');
524 if (tok != ')') {
525 t = gjmp(0);
526 expr();
527 gjmp(n - ind - 5);
528 gsym(t);
529 n = t + 4;
530 }
531 }
532 skip(')');
Jack Palevich77ae76e2009-05-10 19:59:24 -0700533 block((int) &a);
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700534 gjmp(n - ind - 5); /* jmp */
535 gsym(a);
536 } else if (tok == '{') {
537 next();
538 /* declarations */
539 decl(1);
540 while(tok != '}')
541 block(l);
542 next();
543 } else {
544 if (tok == TOK_RETURN) {
545 next();
546 if (tok != ';')
547 expr();
548 rsym = gjmp(rsym); /* jmp */
549 } else if (tok == TOK_BREAK) {
550 next();
551 *(int *)l = gjmp(*(int *)l);
552 } else if (tok != ';')
553 expr();
554 skip(';');
555 }
556}
557
558/* 'l' is true if local declarations */
Jack Palevich77ae76e2009-05-10 19:59:24 -0700559void decl(int l)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700560{
561 int a;
562
563 while (tok == TOK_INT | tok != -1 & !l) {
564 if (tok == TOK_INT) {
565 next();
566 while (tok != ';') {
567 if (l) {
568 loc = loc + 4;
569 *(int *)tok = -loc;
570 } else {
571 *(int *)tok = glo;
572 glo = glo + 4;
573 }
574 next();
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700575 if (tok == ',')
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700576 next();
577 }
578 skip(';');
579 } else {
580 /* patch forward references (XXX: do not work for function
581 pointers) */
582 gsym(*(int *)(tok + 4));
583 /* put function address */
584 *(int *)tok = ind;
585 next();
586 skip('(');
587 a = 8;
588 while (tok != ')') {
589 /* read param name and compute offset */
590 *(int *)tok = a;
591 a = a + 4;
592 next();
593 if (tok == ',')
594 next();
595 }
596 next(); /* skip ')' */
597 rsym = loc = 0;
598 o(0xe58955); /* push %ebp, mov %esp, %ebp */
599 a = oad(0xec81, 0); /* sub $xxx, %esp */
600 block(0);
601 gsym(rsym);
602 o(0xc3c9); /* leave, ret */
603 *(int *)a = loc; /* save local variables */
604 }
605 }
606}
607
Jack Palevich77ae76e2009-05-10 19:59:24 -0700608public:
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700609compiler() :
610 tok(0), tokc(0), tokl(0), ch(0),
611 vars(0), rsym(0), prog(0), ind(0), loc(0), glo(0), sym_stk(0),
612 dstk(0), dptr(0), dch(0), last_id(0), file(0)
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700613{
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700614}
615
616int compile(FILE* in) {
617
618 file = in;
Jack Palevichf6b5a532009-05-10 19:16:42 -0700619 sym_stk = (int) calloc(1, ALLOC_SIZE);
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700620 dstk = (int) strcpy((char*) sym_stk,
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700621 " int if else while break return for define main ") + TOK_STR_SIZE;
Jack Palevichf6b5a532009-05-10 19:16:42 -0700622 glo = (int) calloc(1, ALLOC_SIZE);
623 ind = prog = (int) calloc(1, ALLOC_SIZE);
624 vars = (int) calloc(1, ALLOC_SIZE);
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700625 inp();
626 next();
627 decl(0);
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700628 return 0;
629}
630
631int run(int argc, char** argv)
632{
633 typedef int (*mainPtr)(int argc, char** argv);
634 mainPtr aMain = (mainPtr) * (int*) (vars + TOK_MAIN);
635 if (! aMain) {
636 fprintf(stderr, "Could not find main");
637 return -1;
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700638 }
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700639 return aMain(argc, argv);
640}
641
642int dump(FILE* out) {
643 fwrite((void *)prog, 1, ind - prog, out);
644 return 0;
Jack Paleviche27bf3e2009-05-10 14:09:03 -0700645}
Jack Palevich77ae76e2009-05-10 19:59:24 -0700646
647};
648
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700649
650} // namespace acc
651
Jack Palevich77ae76e2009-05-10 19:59:24 -0700652int main(int argc, char** argv) {
Jack Palevichbbf8ab52009-05-11 11:54:30 -0700653 bool doTest = false;
654 const char* inFile = NULL;
655 const char* outFile = NULL;
656 int i;
657 for(i = 1; i < argc; i++) {
658 char* arg = argv[i];
659 if (arg[0] == '-') {
660 switch (arg[1]) {
661 case 'T':
662 if (i + 1 >= argc) {
663 fprintf(stderr, "Expected filename after -T\n");
664 return 2;
665 }
666 doTest = true;
667 outFile = argv[i + 1];
668 i += 1;
669 break;
670 default:
671 fprintf(stderr, "Unrecognized flag %s\n", arg);
672 return 3;
673 }
674 } else if (inFile == NULL) {
675 inFile = arg;
676 } else {
677 break;
678 }
679 }
680
681 FILE* in = stdin;
682 if (inFile) {
683 in = fopen(inFile, "r");
684 if (! in) {
685 fprintf(stderr, "Could not open input file %s\n", inFile);
686 return 1;
687 }
688 }
689 acc::compiler compiler;
690 int compileResult = compiler.compile(in);
691 if (in != stdin) {
692 fclose(in);
693 }
694 if (compileResult) {
695 fprintf(stderr, "Compile failed: %d\n", compileResult);
696 return 6;
697 }
698 if (doTest) {
699 FILE* save = fopen(outFile, "w");
700 if (! save) {
701 fprintf(stderr, "Could not open output file %s\n", outFile);
702 return 5;
703 }
704 compiler.dump(save);
705 fclose(save);
706 } else {
707 int codeArgc = argc-i+1;
708 char** codeArgv=argv + i - 1;
709 codeArgv[0] = (char*) (inFile ? inFile : "stdin");
710 return compiler.run(codeArgc, codeArgv);
711 }
712
713 return 0;
714}