diff options
| author | Android (Google) Code Review <android-gerrit@google.com> | 2009-05-11 10:00:27 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-05-11 10:00:27 -0700 |
| commit | bdb4d40e48fd56be84a9b93271a3443a0e10c22a (patch) | |
| tree | b4d73eb53f0bb1b8926decb7b8acb895ed2a1c89 | |
| parent | ca5feb26171a03fdf700d39d9c0a5e511c5cef87 (diff) | |
| parent | e27bf3eb290c75704549b4a5eedda56079bac86e (diff) | |
| download | system_core-bdb4d40e48fd56be84a9b93271a3443a0e10c22a.zip system_core-bdb4d40e48fd56be84a9b93271a3443a0e10c22a.tar.gz system_core-bdb4d40e48fd56be84a9b93271a3443a0e10c22a.tar.bz2 | |
Merge change 1364
* changes:
Replace acc.c with the contents of otccn.c, update tests.
| -rw-r--r-- | libacc/acc.c | 966 | ||||
| -rw-r--r-- | libacc/otccn.c | 632 | ||||
| -rwxr-xr-x | libacc/test | 2 | ||||
| -rw-r--r-- | libacc/tests/hello.out-orig | bin | 299997 -> 40 bytes | |||
| -rw-r--r-- | libacc/tests/otcc.out-orig | bin | 299997 -> 8591 bytes |
5 files changed, 534 insertions, 1066 deletions
diff --git a/libacc/acc.c b/libacc/acc.c index a8505cd..7fa376f 100644 --- a/libacc/acc.c +++ b/libacc/acc.c @@ -1,525 +1,625 @@ /* - ** - ** Copyright 2009, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -/* Based upon the freeware version of the Obfuscated Tiny C Compiler - * by Francis Bellard. <francis@bellard.org>. - */ + Obfuscated Tiny C Compiler + Copyright (C) 2001-2003 Fabrice Bellard + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product and its documentation + *is* required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include <stdarg.h> #include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define TOKEN_OPERATOR 1 -#define TOKEN_NUMBER 2 - -#define TOKEN_SYMBOL_BASE 256 -#define TOKEN_INT 256 -#define TOKEN_IF 288 -#define TOKEN_ELSE 312 -#define TOKEN_WHILE 352 -#define TOKEN_BREAK 400 -#define TOKEN_RETURN 448 -#define TOKEN_FOR 504 -#define TOKEN_DEFINE 536 - -static int currentToken; -static int currentTokenData; -static int gCurrentTokenOperatorLevel; -static int currentChar; -static int gEndOfFunctionTarget; -static int gProgramCounter; -static int gFunctionStackSize; -static int savedChar; -static char* pInProgressMacro; -static char* P; -static char* ac; -static char* gStringTable; -static char* pSymbolTable; -static char* M; -static char* R; -static FILE* pInput; - -static void parseDeclarations (int isLocal); -static void parseExpression(); - -static void addToSymbolTable(char e) { - *pSymbolTable++ = e; + +/* vars: value of variables + loc : local variable index + glo : global variable index + ind : output code ptr + rsym: return symbol + prog: output code + dstk: define stack + dptr, dch: macro state +*/ +int tok, tokc, tokl, ch, vars, rsym, prog, ind, loc, glo, file, sym_stk, dstk, dptr, dch, last_id; + +#define ALLOC_SIZE 99999 + +/* depends on the init string */ +#define TOK_STR_SIZE 48 +#define TOK_IDENT 0x100 +#define TOK_INT 0x100 +#define TOK_IF 0x120 +#define TOK_ELSE 0x138 +#define TOK_WHILE 0x160 +#define TOK_BREAK 0x190 +#define TOK_RETURN 0x1c0 +#define TOK_FOR 0x1f8 +#define TOK_DEFINE 0x218 +#define TOK_MAIN 0x250 + +#define TOK_DUMMY 1 +#define TOK_NUM 2 + +#define LOCAL 0x200 + +#define SYM_FORWARD 0 +#define SYM_DEFINE 1 + +/* tokens in string heap */ +#define TAG_TOK ' ' +#define TAG_MACRO 2 + +pdef(t) +{ + *(char *)dstk++ = t; } -static void nextChar() { - if (pInProgressMacro) { - currentChar = *(char*) pInProgressMacro++; - if (currentChar == 2) { - pInProgressMacro = NULL; - currentChar = savedChar; +inp() +{ + if (dptr) { + ch = *(char *)dptr++; + if (ch == TAG_MACRO) { + dptr = 0; + ch = dch; } } else - currentChar = fgetc(pInput); + ch = fgetc(file); + /* printf("ch=%c 0x%x\n", ch, ch); */ } -static int isSymbolChar() { - return isalnum(currentChar) || currentChar == '_'; +isid() +{ + return isalnum(ch) | ch == '_'; } -static void unescapeCurrentChar() { - if (currentChar == '\\') { - nextChar(); - if (currentChar == 'n') - currentChar = '\n'; +/* read a character constant */ +getq() +{ + if (ch == '\\') { + inp(); + if (ch == 'n') + ch = '\n'; } } -static void nextToken() { - int j, m; - while (isspace(currentChar) || currentChar == '#') { - if (currentChar == '#') { - nextChar(); - nextToken(); - if (currentToken == TOKEN_DEFINE) { - nextToken(); - addToSymbolTable(' '); - *(int*) currentToken = 1; - *(int*) (currentToken + 4) = (int) pSymbolTable; +next() +{ + int t, l, a; + + while (isspace(ch) | ch == '#') { + if (ch == '#') { + inp(); + next(); + if (tok == TOK_DEFINE) { + next(); + pdef(TAG_TOK); /* fill last ident tag */ + *(int *)tok = SYM_DEFINE; + *(int *)(tok + 4) = dstk; /* define stack */ } - while (currentChar != '\n') { - addToSymbolTable(currentChar); - nextChar(); + /* well we always save the values ! */ + while (ch != '\n') { + pdef(ch); + inp(); } - addToSymbolTable(currentChar); - addToSymbolTable(2); + pdef(ch); + pdef(TAG_MACRO); } - nextChar(); + inp(); } - gCurrentTokenOperatorLevel = 0; - currentToken = currentChar; - if (isSymbolChar()) { - addToSymbolTable(' '); - M = pSymbolTable; - while (isSymbolChar()) { - addToSymbolTable(currentChar); - nextChar(); + tokl = 0; + tok = ch; + /* encode identifiers & numbers */ + if (isid()) { + pdef(TAG_TOK); + last_id = dstk; + while (isid()) { + pdef(ch); + inp(); } - if (isdigit(currentToken)) { - currentTokenData = strtol(M, 0, 0); - currentToken = TOKEN_NUMBER; + if (isdigit(tok)) { + tokc = strtol(last_id, 0, 0); + tok = TOK_NUM; } else { - *(char*) pSymbolTable = ' '; - currentToken = strstr(R, M - 1) - R; - *(char*) pSymbolTable = 0; - currentToken = currentToken * 8 + TOKEN_SYMBOL_BASE; - if (currentToken > TOKEN_DEFINE) { - currentToken = ((int) P) + currentToken; - if (*(int*) currentToken == 1) { - pInProgressMacro = (char*) (*(int*) (currentToken + 4)); - savedChar = currentChar; - nextChar(); - nextToken(); + *(char *)dstk = TAG_TOK; /* no need to mark end of string (we + suppose data is initied to zero */ + tok = strstr(sym_stk, last_id - 1) - sym_stk; + *(char *)dstk = 0; /* mark real end of ident for dlsym() */ + tok = tok * 8 + TOK_IDENT; + if (tok > TOK_DEFINE) { + tok = vars + tok; + /* printf("tok=%s %x\n", last_id, tok); */ + /* define handling */ + if (*(int *)tok == SYM_DEFINE) { + dptr = *(int *)(tok + 4); + dch = ch; + inp(); + next(); } } } } else { - nextChar(); - if (currentToken == '\'') { - currentToken = TOKEN_NUMBER; - unescapeCurrentChar(); - currentTokenData = currentChar; - nextChar(); - nextChar(); - } else if (currentToken == '/' & currentChar == '*') { - nextChar(); - while (currentChar) { - while (currentChar != '*') - nextChar(); - nextChar(); - if (currentChar == '/') - currentChar = 0; + inp(); + if (tok == '\'') { + tok = TOK_NUM; + getq(); + tokc = ch; + inp(); + inp(); + } else if (tok == '/' & ch == '*') { + inp(); + while (ch) { + while (ch != '*') + inp(); + inp(); + if (ch == '/') + ch = 0; } - nextChar(); - nextToken(); - } else { - 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"; - while (j = *(char*) e++) { - m = *(char*) e++; - currentTokenData = 0; - while ((gCurrentTokenOperatorLevel = *(char*) e++ - 98) < 0) - currentTokenData = currentTokenData * 64 + gCurrentTokenOperatorLevel + 64; - if (j == currentToken && (m == currentChar || m == 64)) { - if (m == currentChar) { - nextChar(); - currentToken = TOKEN_OPERATOR; + inp(); + next(); + } else + { + 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"; + while (l = *(char *)t++) { + a = *(char *)t++; + tokc = 0; + while ((tokl = *(char *)t++ - 'b') < 0) + tokc = tokc * 64 + tokl + 64; + if (l == tok & (a == ch | a == '@')) { +#if 0 + printf("%c%c -> tokl=%d tokc=0x%x\n", + l, a, tokl, tokc); +#endif + if (a == ch) { + inp(); + tok = TOK_DUMMY; /* dummy token for double tokens */ } break; } } } } +#if 0 + { + int p; + + printf("tok=0x%x ", tok); + if (tok >= TOK_IDENT) { + printf("'"); + if (tok > TOK_DEFINE) + p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8; + else + p = sym_stk + 1 + (tok - TOK_IDENT) / 8; + while (*(char *)p != TAG_TOK && *(char *)p) + printf("%c", *(char *)p++); + printf("'\n"); + } else if (tok == TOK_NUM) { + printf("%d\n", tokc); + } else { + printf("'%c'\n", tok); + } + } +#endif } -/* - * Emit 1 to 4 bytes of code. Little-endian, doesn't emit high bytes that - * are 0x00 or 0xff - */ -static void emitCode(int g) { - while( g && g != -1) { - *(char*) gProgramCounter++=g; - g=g>>8; +void error(char *fmt,...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "%d: ", ftell((FILE *)file)); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + exit(1); + va_end(ap); +} + +void skip(c) +{ + if (tok != c) { + error("'%c' expected", c); } + next(); } -static void fixupAddress(e) { - int g; - while( e) { - g=*(int*) e; - *(int*) e=gProgramCounter-e-4; - e=g; +o(n) +{ + /* cannot use unsigned, so we must do a hack */ + while (n && n != -1) { + *(char *)ind++ = n; + n = n >> 8; } } -static int emitCodeWithImmediate( g, e) { - emitCode(g); - *(int*) gProgramCounter = e; - e = gProgramCounter; - gProgramCounter = gProgramCounter + 4; - return e; +/* output a symbol and patch all calls to it */ +gsym(t) +{ + int n; + while (t) { + n = *(int *)t; /* next value */ + *(int *)t = ind - t - 4; + t = n; + } } -static int emitLoadAccumulatorImmediate(e) { - emitCodeWithImmediate(0xb8,e); /* Move immediate a, e */ +/* psym is used to put an instruction with a data field which is a + reference to a symbol. It is in fact the same as oad ! */ +#define psym oad + +/* instruction + address */ +oad(n, t) +{ + o(n); + *(int *)ind = t; + t = ind; + ind = ind + 4; + return t; } -static int emitBranch(e) { - return emitCodeWithImmediate(0xe9,e); /* Jump relative */ +/* load immediate value */ +li(t) +{ + oad(0xb8, t); /* mov $xx, %eax */ } -static int emitTest( j, e) { - emitCode(0x0FC085); /* 85 C0 FC TEST */ - return emitCodeWithImmediate(0x84 + j, e); /* TEST */ +gjmp(t) +{ + return psym(0xe9, t); } -static void emitSetCC(int condition) { - emitCode( 0xC139); /* 39 C1 CMP */ - emitLoadAccumulatorImmediate(0); - emitCode( 0x0F); /* Two byte opcode prefix */ - emitCode( condition+0x90); /* Set byte on condition (controlled by e) */ - emitCode( 0xC0); /* I think this is part of the SETcc instruction */ +/* l = 0: je, l == 1: jne */ +gtst(l, t) +{ + o(0x0fc085); /* test %eax, %eax, je/jne xxx */ + return psym(0x84 + l, t); } -static void emitNumericOp( int op, int e) { - emitCode(op + 0x83); - emitCodeWithImmediate((e < 512) << 7 | 5, e); +gcmp(t) +{ + o(0xc139); /* cmp %eax,%ecx */ + li(0); + o(0x0f); /* setxx %al */ + o(t + 0x90); + o(0xc0); } -static void parseTerminal (int level) { - int g,e,m,aa; - g=1; - if( currentToken == '"') { - emitLoadAccumulatorImmediate(gStringTable); - while( currentChar != '"') { - unescapeCurrentChar (); - *(char*) gStringTable++=currentChar; - nextChar (); - } - *(char*) gStringTable=0; - gStringTable= (char*) (((int)gStringTable) +4&-4); - nextChar(); - nextToken(); - } - else { - aa=gCurrentTokenOperatorLevel; - m= currentTokenData; - e=currentToken; - nextToken(); - if( e == TOKEN_NUMBER) { - emitLoadAccumulatorImmediate(m); - } - else if( aa == 2) { - parseTerminal(0); - emitCodeWithImmediate(0xB9,0); /* MOV r1, immediate */ - if( e == '!')emitSetCC(m); - else emitCode( m); - } - else if( e == '(') { - parseExpression (); - nextToken(); +gmov(l, t) +{ + o(l + 0x83); + oad((t < LOCAL) << 7 | 5, t); +} + +/* l is one if '=' parsing wanted (quick hack) */ +unary(l) +{ + int n, t, a, c; + + n = 1; /* type of expression 0 = forward, 1 = value, other = + lvalue */ + if (tok == '\"') { + li(glo); + while (ch != '\"') { + getq(); + *(char *)glo++ = ch; + inp(); } - else if( e == '*') { - nextToken(); - e=currentToken; - nextToken(); - nextToken(); - if( currentToken == '*') { - nextToken(); - nextToken(); - nextToken(); - nextToken(); - e=0; - } - nextToken(); - parseTerminal(0); - if( currentToken == '=') { - nextToken(); - emitCode( 0x50); /* PUSH r0 */ - parseExpression (); - emitCode( 0x59); /* POP r1 */ - emitCode( 0x188 + (e == TOKEN_INT)); /* 88 01 MOV */ + *(char *)glo = 0; + glo = glo + 4 & -4; /* align heap */ + inp(); + next(); + } else { + c = tokl; + a = tokc; + t = tok; + next(); + if (t == TOK_NUM) { + li(a); + } else if (c == 2) { + /* -, +, !, ~ */ + unary(0); + oad(0xb9, 0); /* movl $0, %ecx */ + if (t == '!') + gcmp(a); + else + o(a); + } else if (t == '(') { + expr(); + skip(')'); + } else if (t == '*') { + /* parse cast */ + skip('('); + t = tok; /* get type */ + next(); /* skip int/char/void */ + next(); /* skip '*' or '(' */ + if (tok == '*') { + /* function type */ + skip('*'); + skip(')'); + skip('('); + skip(')'); + t = 0; } - else if( e) { - if( e == TOKEN_INT)emitCode( 0x8B); /* MOV */ - else emitCode( 0xBE0F); /* 0F BE MOVSX move with sign extension */ - gProgramCounter++; + skip(')'); + unary(0); + if (tok == '=') { + next(); + o(0x50); /* push %eax */ + expr(); + o(0x59); /* pop %ecx */ + o(0x0188 + (t == TOK_INT)); /* movl %eax/%al, (%ecx) */ + } else if (t) { + if (t == TOK_INT) + o(0x8b); /* mov (%eax), %eax */ + else + o(0xbe0f); /* movsbl (%eax), %eax */ + ind++; /* add zero in code */ } - } - else if( e == '&') { - emitNumericOp(10,*(int*) currentToken); /* 8D LEA */ - nextToken(); - } - else { - g=*(int*) e; - if(!g)g=dlsym(0,M); - if( currentToken == '=' & level) { - nextToken(); - parseExpression (); - emitNumericOp(6,g); /* 89 MOV */ - } - else if( currentToken!= '(') { - emitNumericOp(8,g); /* 8B MOV sreg */ - if( gCurrentTokenOperatorLevel == 11) { - emitNumericOp(0,g); /* 83 ADD */ - emitCode( currentTokenData); - nextToken(); + } else if (t == '&') { + gmov(10, *(int *)tok); /* leal EA, %eax */ + next(); + } else { + n = *(int *)t; + /* forward reference: try dlsym */ + if (!n) + n = dlsym(0, last_id); + if (tok == '=' & l) { + /* assignment */ + next(); + expr(); + gmov(6, n); /* mov %eax, EA */ + } else if (tok != '(') { + /* variable */ + gmov(8, n); /* mov EA, %eax */ + if (tokl == 11) { + gmov(0, n); + o(tokc); + next(); } } } } - if( currentToken == '(') { - if( g == 1)emitCode( 0x50); /* push */ - m= emitCodeWithImmediate(0xEC81,0); /* 81 EC Cmp ?? */ - nextToken(); - level=0; - while( currentToken!= ')') { - parseExpression (); - emitCodeWithImmediate(0x248489,level); /* 89 84 24 MOV sp + level*/ - if( currentToken == ',')nextToken(); - level=level +4; - } - *(int*) m= level; - nextToken(); - if(!g) { - e=e +4; - *(int*) e=emitCodeWithImmediate(0xE8,*(int*) e); /* Call */ - } - else if( g == 1) { - emitCodeWithImmediate(0x2494FF,level); /* FF 94 24 */ - level=level +4; + + /* function call */ + if (tok == '(') { + if (n == 1) + o(0x50); /* push %eax */ + + /* push args and invert order */ + a = oad(0xec81, 0); /* sub $xxx, %esp */ + next(); + l = 0; + while(tok != ')') { + expr(); + oad(0x248489, l); /* movl %eax, xxx(%esp) */ + if (tok == ',') + next(); + l = l + 4; } - else { - emitCodeWithImmediate(0xE8,g-gProgramCounter-5); /* CALL */ + *(int *)a = l; + next(); + if (!n) { + /* forward reference */ + t = t + 4; + *(int *)t = psym(0xe8, *(int *)t); + } else if (n == 1) { + oad(0x2494ff, l); /* call *xxx(%esp) */ + l = l + 4; + } else { + oad(0xe8, n - ind - 5); /* call xxx */ } - if( level)emitCodeWithImmediate(0xC481,level); /* 81 C4 adjust stack pointer */ + if (l) + oad(0xc481, l); /* add $xxx, %esp */ } } -static void parseBinaryOp (int level) { - int e,g,m; - if( level--== 1)parseTerminal(1); +sum(l) +{ + int t, n, a; + + if (l-- == 1) + unary(1); else { - parseBinaryOp (level); - m= 0; - while( level == gCurrentTokenOperatorLevel) { - g=currentToken; - e=currentTokenData; - nextToken(); - if( level>8) { - m= emitTest(e,m); - parseBinaryOp (level); - } - else { - emitCode( 0x50); - parseBinaryOp (level); - emitCode( 0x59); - if( level == 4 | level == 5) { - emitSetCC(e); - } - else { - emitCode( e); - if( g == '%')emitCode( 0x92); /* XCHG */ + sum(l); + a = 0; + while (l == tokl) { + n = tok; + t = tokc; + next(); + + if (l > 8) { + a = gtst(t, a); /* && and || output code generation */ + sum(l); + } else { + o(0x50); /* push %eax */ + sum(l); + o(0x59); /* pop %ecx */ + + if (l == 4 | l == 5) { + gcmp(t); + } else { + o(t); + if (n == '%') + o(0x92); /* xchg %edx, %eax */ } } } - if( m&&level>8) { - m= emitTest(e,m); - emitLoadAccumulatorImmediate(e^1); - emitBranch(5); /* Jump relative +5 */ - fixupAddress(m); - emitLoadAccumulatorImmediate(e); + /* && and || output code generation */ + if (a && l > 8) { + a = gtst(t, a); + li(t ^ 1); + gjmp(5); /* jmp $ + 5 */ + gsym(a); + li(t); } } } -static void parseExpression() { - parseBinaryOp(11); +expr() +{ + sum(11); } -static int parseExpressionEmitTest() { - parseExpression(); - return emitTest(0, 0); + +test_expr() +{ + expr(); + return gtst(0, 0); } -static void parseStatement (int* pBreakTarget) { - int m,g,e; - if( currentToken == TOKEN_IF) { - nextToken(); - nextToken(); - m= parseExpressionEmitTest (); - nextToken(); - parseStatement (pBreakTarget); - if( currentToken == TOKEN_ELSE) { - nextToken(); - g=emitBranch(0); - fixupAddress(m); - parseStatement (pBreakTarget); - fixupAddress(g); - } - else { - fixupAddress(m); - } - } - else if ( currentToken == TOKEN_WHILE || currentToken == TOKEN_FOR) { - e = currentToken; - nextToken(); - nextToken(); - if( e == TOKEN_WHILE) { - g=gProgramCounter; - m= parseExpressionEmitTest (); +block(l) +{ + int a, n, t; + + if (tok == TOK_IF) { + next(); + skip('('); + a = test_expr(); + skip(')'); + block(l); + if (tok == TOK_ELSE) { + next(); + n = gjmp(0); /* jmp */ + gsym(a); + block(l); + gsym(n); /* patch else jmp */ + } else { + gsym(a); /* patch if test */ } - else { - if( currentToken != ';')parseExpression (); - nextToken(); - g=gProgramCounter; - m= 0; - if( currentToken != ';')m= parseExpressionEmitTest (); - nextToken(); - if( currentToken!= ')') { - e=emitBranch(0); - parseExpression (); - emitBranch(g-gProgramCounter-5); - fixupAddress(e); - g=e +4; + } else if (tok == TOK_WHILE | tok == TOK_FOR) { + t = tok; + next(); + skip('('); + if (t == TOK_WHILE) { + n = ind; + a = test_expr(); + } else { + if (tok != ';') + expr(); + skip(';'); + n = ind; + a = 0; + if (tok != ';') + a = test_expr(); + skip(';'); + if (tok != ')') { + t = gjmp(0); + expr(); + gjmp(n - ind - 5); + gsym(t); + n = t + 4; } } - nextToken(); - parseStatement(&m); - emitBranch(g-gProgramCounter-5); - fixupAddress(m); - } - else if( currentToken == '{') { - nextToken(); - parseDeclarations(1); - while( currentToken != '}') parseStatement(pBreakTarget); - nextToken(); - } - else { - if( currentToken == TOKEN_RETURN) { - nextToken(); - if( currentToken != ';') parseExpression(); - gEndOfFunctionTarget=emitBranch(gEndOfFunctionTarget); - } - else if( currentToken == TOKEN_BREAK) { - nextToken(); - *pBreakTarget = emitBranch(*pBreakTarget); - } - else if( currentToken != ';') parseExpression(); - nextToken(); + skip(')'); + block(&a); + gjmp(n - ind - 5); /* jmp */ + gsym(a); + } else if (tok == '{') { + next(); + /* declarations */ + decl(1); + while(tok != '}') + block(l); + next(); + } else { + if (tok == TOK_RETURN) { + next(); + if (tok != ';') + expr(); + rsym = gjmp(rsym); /* jmp */ + } else if (tok == TOK_BREAK) { + next(); + *(int *)l = gjmp(*(int *)l); + } else if (tok != ';') + expr(); + skip(';'); } } -static void parseDeclarations (int isLocal) { - int m; - while( currentToken == TOKEN_INT | currentToken != -1 & !isLocal ) { - if( currentToken == TOKEN_INT) { - nextToken(); - while( currentToken != ';') { - if( isLocal ) { - gFunctionStackSize=gFunctionStackSize +4; - *(int*) currentToken=-gFunctionStackSize; - } - else { - *(char**) currentToken = gStringTable; - gStringTable=gStringTable +4; +/* 'l' is true if local declarations */ +decl(l) +{ + int a; + + while (tok == TOK_INT | tok != -1 & !l) { + if (tok == TOK_INT) { + next(); + while (tok != ';') { + if (l) { + loc = loc + 4; + *(int *)tok = -loc; + } else { + *(int *)tok = glo; + glo = glo + 4; } - nextToken(); - if( currentToken == ',')nextToken(); + next(); + if (tok == ',') + next(); } - nextToken(); - } - else { - fixupAddress(*(int*)(currentToken + 4)); - *(int*) currentToken=gProgramCounter; - nextToken(); - nextToken(); - m= 8; - while( currentToken != ')') { - *(int*) currentToken=m; - m= m +4; - nextToken(); - if( currentToken == ',')nextToken(); + skip(';'); + } else { + /* patch forward references (XXX: do not work for function + pointers) */ + gsym(*(int *)(tok + 4)); + /* put function address */ + *(int *)tok = ind; + next(); + skip('('); + a = 8; + while (tok != ')') { + /* read param name and compute offset */ + *(int *)tok = a; + a = a + 4; + next(); + if (tok == ',') + next(); } - nextToken(); - gEndOfFunctionTarget=gFunctionStackSize=0; - emitCode( 0xE58955); /* 55 89 E5 PUSH */ - m= emitCodeWithImmediate(0xEC81,0); /* 81 EC */ - parseStatement(0); - fixupAddress(gEndOfFunctionTarget); - emitCode( 0xC3C9); /* C9 C3 LEAVE */ - *(int*) m= gFunctionStackSize; + next(); /* skip ')' */ + rsym = loc = 0; + o(0xe58955); /* push %ebp, mov %esp, %ebp */ + a = oad(0xec81, 0); /* sub $xxx, %esp */ + block(0); + gsym(rsym); + o(0xc3c9); /* leave, ret */ + *(int *)a = loc; /* save local variables */ } } } -int main( int argc, char** argv) { - pInput = stdin; - if (argc-- > 1) { - char* file = argv[1]; - argv += 1; - pInput = fopen(file, "r"); - if (pInput == NULL) { - fprintf(stderr, "Could not open file \"%s\"\n", file); - return -1; - } +main(n, t) +{ + file = stdin; + if (n-- > 1) { + t = t + 4; + file = fopen(*(int *)t, "r"); + } + dstk = strcpy(sym_stk = calloc(1, ALLOC_SIZE), + " int if else while break return for define main ") + TOK_STR_SIZE; + glo = calloc(1, ALLOC_SIZE); + ind = prog = calloc(1, ALLOC_SIZE); + vars = calloc(1, ALLOC_SIZE); + inp(); + next(); + decl(0); +#ifdef TEST + { + FILE *f; + f = fopen(*(char **)(t + 4), "w"); + fwrite((void *)prog, 1, ind - prog, f); + fclose(f); + return 0; } - pSymbolTable = strcpy(R = calloc(1, 99999), - " int if else while break return for define main ") + 48; - gStringTable = calloc(1, 99999); - ac = calloc(1, 99999); - gProgramCounter = (int) ac; - P = calloc(1, 99999); - nextChar(); - nextToken(); - parseDeclarations(0); -#if 1 - fwrite(R, 1, 99999, stdout); - fwrite(ac, 1, 99999, stdout); - fwrite(P, 1, 99999, stdout); - return 0; #else - /* Look up the address of "main" in the symbol table and call it. - * We put main in at a known offset, so we know the address. - */ - return (*(int(*)()) *(int*) (P + 592))(argc, argv); + return (*(int (*)())*(int *)(vars + TOK_MAIN)) (n, t); #endif } - diff --git a/libacc/otccn.c b/libacc/otccn.c deleted file mode 100644 index d8eb4cc..0000000 --- a/libacc/otccn.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - Obfuscated Tiny C Compiler - - Copyright (C) 2001-2003 Fabrice Bellard - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product and its documentation - *is* required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#ifndef TINY -#include <stdarg.h> -#endif -#include <stdio.h> - -/* vars: value of variables - loc : local variable index - glo : global variable index - ind : output code ptr - rsym: return symbol - prog: output code - dstk: define stack - dptr, dch: macro state -*/ -int tok, tokc, tokl, ch, vars, rsym, prog, ind, loc, glo, file, sym_stk, dstk, dptr, dch, last_id; - -#define ALLOC_SIZE 99999 - -/* depends on the init string */ -#define TOK_STR_SIZE 48 -#define TOK_IDENT 0x100 -#define TOK_INT 0x100 -#define TOK_IF 0x120 -#define TOK_ELSE 0x138 -#define TOK_WHILE 0x160 -#define TOK_BREAK 0x190 -#define TOK_RETURN 0x1c0 -#define TOK_FOR 0x1f8 -#define TOK_DEFINE 0x218 -#define TOK_MAIN 0x250 - -#define TOK_DUMMY 1 -#define TOK_NUM 2 - -#define LOCAL 0x200 - -#define SYM_FORWARD 0 -#define SYM_DEFINE 1 - -/* tokens in string heap */ -#define TAG_TOK ' ' -#define TAG_MACRO 2 - -pdef(t) -{ - *(char *)dstk++ = t; -} - -inp() -{ - if (dptr) { - ch = *(char *)dptr++; - if (ch == TAG_MACRO) { - dptr = 0; - ch = dch; - } - } else - ch = fgetc(file); - /* printf("ch=%c 0x%x\n", ch, ch); */ -} - -isid() -{ - return isalnum(ch) | ch == '_'; -} - -/* read a character constant */ -getq() -{ - if (ch == '\\') { - inp(); - if (ch == 'n') - ch = '\n'; - } -} - -next() -{ - int t, l, a; - - while (isspace(ch) | ch == '#') { - if (ch == '#') { - inp(); - next(); - if (tok == TOK_DEFINE) { - next(); - pdef(TAG_TOK); /* fill last ident tag */ - *(int *)tok = SYM_DEFINE; - *(int *)(tok + 4) = dstk; /* define stack */ - } - /* well we always save the values ! */ - while (ch != '\n') { - pdef(ch); - inp(); - } - pdef(ch); - pdef(TAG_MACRO); - } - inp(); - } - tokl = 0; - tok = ch; - /* encode identifiers & numbers */ - if (isid()) { - pdef(TAG_TOK); - last_id = dstk; - while (isid()) { - pdef(ch); - inp(); - } - if (isdigit(tok)) { - tokc = strtol(last_id, 0, 0); - tok = TOK_NUM; - } else { - *(char *)dstk = TAG_TOK; /* no need to mark end of string (we - suppose data is initied to zero */ - tok = strstr(sym_stk, last_id - 1) - sym_stk; - *(char *)dstk = 0; /* mark real end of ident for dlsym() */ - tok = tok * 8 + TOK_IDENT; - if (tok > TOK_DEFINE) { - tok = vars + tok; - /* printf("tok=%s %x\n", last_id, tok); */ - /* define handling */ - if (*(int *)tok == SYM_DEFINE) { - dptr = *(int *)(tok + 4); - dch = ch; - inp(); - next(); - } - } - } - } else { - inp(); - if (tok == '\'') { - tok = TOK_NUM; - getq(); - tokc = ch; - inp(); - inp(); - } else if (tok == '/' & ch == '*') { - inp(); - while (ch) { - while (ch != '*') - inp(); - inp(); - if (ch == '/') - ch = 0; - } - inp(); - next(); - } else - { - 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"; - while (l = *(char *)t++) { - a = *(char *)t++; - tokc = 0; - while ((tokl = *(char *)t++ - 'b') < 0) - tokc = tokc * 64 + tokl + 64; - if (l == tok & (a == ch | a == '@')) { -#if 0 - printf("%c%c -> tokl=%d tokc=0x%x\n", - l, a, tokl, tokc); -#endif - if (a == ch) { - inp(); - tok = TOK_DUMMY; /* dummy token for double tokens */ - } - break; - } - } - } - } -#if 0 - { - int p; - - printf("tok=0x%x ", tok); - if (tok >= TOK_IDENT) { - printf("'"); - if (tok > TOK_DEFINE) - p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8; - else - p = sym_stk + 1 + (tok - TOK_IDENT) / 8; - while (*(char *)p != TAG_TOK && *(char *)p) - printf("%c", *(char *)p++); - printf("'\n"); - } else if (tok == TOK_NUM) { - printf("%d\n", tokc); - } else { - printf("'%c'\n", tok); - } - } -#endif -} - -#ifdef TINY -#define skip(c) next() -#else - -void error(char *fmt,...) -{ - va_list ap; - - va_start(ap, fmt); - fprintf(stderr, "%d: ", ftell((FILE *)file)); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - exit(1); - va_end(ap); -} - -void skip(c) -{ - if (tok != c) { - error("'%c' expected", c); - } - next(); -} - -#endif - -o(n) -{ - /* cannot use unsigned, so we must do a hack */ - while (n && n != -1) { - *(char *)ind++ = n; - n = n >> 8; - } -} - -/* output a symbol and patch all calls to it */ -gsym(t) -{ - int n; - while (t) { - n = *(int *)t; /* next value */ - *(int *)t = ind - t - 4; - t = n; - } -} - -/* psym is used to put an instruction with a data field which is a - reference to a symbol. It is in fact the same as oad ! */ -#define psym oad - -/* instruction + address */ -oad(n, t) -{ - o(n); - *(int *)ind = t; - t = ind; - ind = ind + 4; - return t; -} - -/* load immediate value */ -li(t) -{ - oad(0xb8, t); /* mov $xx, %eax */ -} - -gjmp(t) -{ - return psym(0xe9, t); -} - -/* l = 0: je, l == 1: jne */ -gtst(l, t) -{ - o(0x0fc085); /* test %eax, %eax, je/jne xxx */ - return psym(0x84 + l, t); -} - -gcmp(t) -{ - o(0xc139); /* cmp %eax,%ecx */ - li(0); - o(0x0f); /* setxx %al */ - o(t + 0x90); - o(0xc0); -} - -gmov(l, t) -{ - o(l + 0x83); - oad((t < LOCAL) << 7 | 5, t); -} - -/* l is one if '=' parsing wanted (quick hack) */ -unary(l) -{ - int n, t, a, c; - - n = 1; /* type of expression 0 = forward, 1 = value, other = - lvalue */ - if (tok == '\"') { - li(glo); - while (ch != '\"') { - getq(); - *(char *)glo++ = ch; - inp(); - } - *(char *)glo = 0; - glo = glo + 4 & -4; /* align heap */ - inp(); - next(); - } else { - c = tokl; - a = tokc; - t = tok; - next(); - if (t == TOK_NUM) { - li(a); - } else if (c == 2) { - /* -, +, !, ~ */ - unary(0); - oad(0xb9, 0); /* movl $0, %ecx */ - if (t == '!') - gcmp(a); - else - o(a); - } else if (t == '(') { - expr(); - skip(')'); - } else if (t == '*') { - /* parse cast */ - skip('('); - t = tok; /* get type */ - next(); /* skip int/char/void */ - next(); /* skip '*' or '(' */ - if (tok == '*') { - /* function type */ - skip('*'); - skip(')'); - skip('('); - skip(')'); - t = 0; - } - skip(')'); - unary(0); - if (tok == '=') { - next(); - o(0x50); /* push %eax */ - expr(); - o(0x59); /* pop %ecx */ - o(0x0188 + (t == TOK_INT)); /* movl %eax/%al, (%ecx) */ - } else if (t) { - if (t == TOK_INT) - o(0x8b); /* mov (%eax), %eax */ - else - o(0xbe0f); /* movsbl (%eax), %eax */ - ind++; /* add zero in code */ - } - } else if (t == '&') { - gmov(10, *(int *)tok); /* leal EA, %eax */ - next(); - } else { - n = *(int *)t; - /* forward reference: try dlsym */ - if (!n) - n = dlsym(0, last_id); - if (tok == '=' & l) { - /* assignment */ - next(); - expr(); - gmov(6, n); /* mov %eax, EA */ - } else if (tok != '(') { - /* variable */ - gmov(8, n); /* mov EA, %eax */ - if (tokl == 11) { - gmov(0, n); - o(tokc); - next(); - } - } - } - } - - /* function call */ - if (tok == '(') { - if (n == 1) - o(0x50); /* push %eax */ - - /* push args and invert order */ - a = oad(0xec81, 0); /* sub $xxx, %esp */ - next(); - l = 0; - while(tok != ')') { - expr(); - oad(0x248489, l); /* movl %eax, xxx(%esp) */ - if (tok == ',') - next(); - l = l + 4; - } - *(int *)a = l; - next(); - if (!n) { - /* forward reference */ - t = t + 4; - *(int *)t = psym(0xe8, *(int *)t); - } else if (n == 1) { - oad(0x2494ff, l); /* call *xxx(%esp) */ - l = l + 4; - } else { - oad(0xe8, n - ind - 5); /* call xxx */ - } - if (l) - oad(0xc481, l); /* add $xxx, %esp */ - } -} - -sum(l) -{ - int t, n, a; - - if (l-- == 1) - unary(1); - else { - sum(l); - a = 0; - while (l == tokl) { - n = tok; - t = tokc; - next(); - - if (l > 8) { - a = gtst(t, a); /* && and || output code generation */ - sum(l); - } else { - o(0x50); /* push %eax */ - sum(l); - o(0x59); /* pop %ecx */ - - if (l == 4 | l == 5) { - gcmp(t); - } else { - o(t); - if (n == '%') - o(0x92); /* xchg %edx, %eax */ - } - } - } - /* && and || output code generation */ - if (a && l > 8) { - a = gtst(t, a); - li(t ^ 1); - gjmp(5); /* jmp $ + 5 */ - gsym(a); - li(t); - } - } -} - -expr() -{ - sum(11); -} - - -test_expr() -{ - expr(); - return gtst(0, 0); -} - -block(l) -{ - int a, n, t; - - if (tok == TOK_IF) { - next(); - skip('('); - a = test_expr(); - skip(')'); - block(l); - if (tok == TOK_ELSE) { - next(); - n = gjmp(0); /* jmp */ - gsym(a); - block(l); - gsym(n); /* patch else jmp */ - } else { - gsym(a); /* patch if test */ - } - } else if (tok == TOK_WHILE | tok == TOK_FOR) { - t = tok; - next(); - skip('('); - if (t == TOK_WHILE) { - n = ind; - a = test_expr(); - } else { - if (tok != ';') - expr(); - skip(';'); - n = ind; - a = 0; - if (tok != ';') - a = test_expr(); - skip(';'); - if (tok != ')') { - t = gjmp(0); - expr(); - gjmp(n - ind - 5); - gsym(t); - n = t + 4; - } - } - skip(')'); - block(&a); - gjmp(n - ind - 5); /* jmp */ - gsym(a); - } else if (tok == '{') { - next(); - /* declarations */ - decl(1); - while(tok != '}') - block(l); - next(); - } else { - if (tok == TOK_RETURN) { - next(); - if (tok != ';') - expr(); - rsym = gjmp(rsym); /* jmp */ - } else if (tok == TOK_BREAK) { - next(); - *(int *)l = gjmp(*(int *)l); - } else if (tok != ';') - expr(); - skip(';'); - } -} - -/* 'l' is true if local declarations */ -decl(l) -{ - int a; - - while (tok == TOK_INT | tok != -1 & !l) { - if (tok == TOK_INT) { - next(); - while (tok != ';') { - if (l) { - loc = loc + 4; - *(int *)tok = -loc; - } else { - *(int *)tok = glo; - glo = glo + 4; - } - next(); - if (tok == ',') - next(); - } - skip(';'); - } else { - /* patch forward references (XXX: do not work for function - pointers) */ - gsym(*(int *)(tok + 4)); - /* put function address */ - *(int *)tok = ind; - next(); - skip('('); - a = 8; - while (tok != ')') { - /* read param name and compute offset */ - *(int *)tok = a; - a = a + 4; - next(); - if (tok == ',') - next(); - } - next(); /* skip ')' */ - rsym = loc = 0; - o(0xe58955); /* push %ebp, mov %esp, %ebp */ - a = oad(0xec81, 0); /* sub $xxx, %esp */ - block(0); - gsym(rsym); - o(0xc3c9); /* leave, ret */ - *(int *)a = loc; /* save local variables */ - } - } -} - -main(n, t) -{ - file = stdin; - if (n-- > 1) { - t = t + 4; - file = fopen(*(int *)t, "r"); - } - dstk = strcpy(sym_stk = calloc(1, ALLOC_SIZE), - " int if else while break return for define main ") + TOK_STR_SIZE; - glo = calloc(1, ALLOC_SIZE); - ind = prog = calloc(1, ALLOC_SIZE); - vars = calloc(1, ALLOC_SIZE); - inp(); - next(); - decl(0); -#ifdef TEST - { - FILE *f; - f = fopen(*(char **)(t + 4), "w"); - fwrite((void *)prog, 1, ind - prog, f); - fclose(f); - return 0; - } -#else - return (*(int (*)())*(int *)(vars + TOK_MAIN)) (n, t); -#endif -} diff --git a/libacc/test b/libacc/test index 2f999c1..eb4f383 100755 --- a/libacc/test +++ b/libacc/test @@ -1,2 +1,2 @@ #!/bin/sh -gcc acc.c -ldl -o tests/acc && tests/acc tests/otcc.c >tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig +gcc acc.c -DTEST -ldl -o tests/acc && tests/acc tests/otcc.c tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig diff --git a/libacc/tests/hello.out-orig b/libacc/tests/hello.out-orig Binary files differindex b71181a..bb178c0 100644 --- a/libacc/tests/hello.out-orig +++ b/libacc/tests/hello.out-orig diff --git a/libacc/tests/otcc.out-orig b/libacc/tests/otcc.out-orig Binary files differindex db2ac83..ea32bc8 100644 --- a/libacc/tests/otcc.out-orig +++ b/libacc/tests/otcc.out-orig |
