system/corennnnn
修订版 | e27bf3eb290c75704549b4a5eedda56079bac86e (tree) |
---|---|
时间 | 2009-05-11 06:09:03 |
作者 | Jack Palevich <jackpal@goog...> |
Commiter | Jack Palevich |
Replace acc.c with the contents of otccn.c, update tests.
We are no longer checking if the constant data is the same, just the
generated code.
@@ -1,525 +1,625 @@ | ||
1 | 1 | /* |
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 | - */ | |
17 | - | |
18 | -/* Based upon the freeware version of the Obfuscated Tiny C Compiler | |
19 | - * by Francis Bellard. <francis@bellard.org>. | |
20 | - */ | |
2 | + Obfuscated Tiny C Compiler | |
21 | 3 | |
4 | + Copyright (C) 2001-2003 Fabrice Bellard | |
5 | + | |
6 | + 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 | |
16 | + in a product, an acknowledgment in the product and its documentation | |
17 | + *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 | + | |
23 | +#include <stdarg.h> | |
22 | 24 | #include <stdio.h> |
23 | -#include <stdlib.h> | |
24 | -#include <string.h> | |
25 | - | |
26 | -#define TOKEN_OPERATOR 1 | |
27 | -#define TOKEN_NUMBER 2 | |
28 | - | |
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 | |
38 | - | |
39 | -static int currentToken; | |
40 | -static int currentTokenData; | |
41 | -static int gCurrentTokenOperatorLevel; | |
42 | -static int currentChar; | |
43 | -static int gEndOfFunctionTarget; | |
44 | -static int gProgramCounter; | |
45 | -static int gFunctionStackSize; | |
46 | -static int savedChar; | |
47 | -static char* pInProgressMacro; | |
48 | -static char* P; | |
49 | -static char* ac; | |
50 | -static char* gStringTable; | |
51 | -static char* pSymbolTable; | |
52 | -static char* M; | |
53 | -static char* R; | |
54 | -static FILE* pInput; | |
55 | - | |
56 | -static void parseDeclarations (int isLocal); | |
57 | -static void parseExpression(); | |
58 | - | |
59 | -static void addToSymbolTable(char e) { | |
60 | - *pSymbolTable++ = e; | |
25 | + | |
26 | +/* vars: value of variables | |
27 | + loc : local variable index | |
28 | + glo : global variable index | |
29 | + ind : output code ptr | |
30 | + rsym: return symbol | |
31 | + prog: output code | |
32 | + dstk: define stack | |
33 | + dptr, dch: macro state | |
34 | +*/ | |
35 | +int tok, tokc, tokl, ch, vars, rsym, prog, ind, loc, glo, file, sym_stk, dstk, dptr, dch, last_id; | |
36 | + | |
37 | +#define ALLOC_SIZE 99999 | |
38 | + | |
39 | +/* depends on the init string */ | |
40 | +#define TOK_STR_SIZE 48 | |
41 | +#define TOK_IDENT 0x100 | |
42 | +#define TOK_INT 0x100 | |
43 | +#define TOK_IF 0x120 | |
44 | +#define TOK_ELSE 0x138 | |
45 | +#define TOK_WHILE 0x160 | |
46 | +#define TOK_BREAK 0x190 | |
47 | +#define TOK_RETURN 0x1c0 | |
48 | +#define TOK_FOR 0x1f8 | |
49 | +#define TOK_DEFINE 0x218 | |
50 | +#define TOK_MAIN 0x250 | |
51 | + | |
52 | +#define TOK_DUMMY 1 | |
53 | +#define TOK_NUM 2 | |
54 | + | |
55 | +#define LOCAL 0x200 | |
56 | + | |
57 | +#define SYM_FORWARD 0 | |
58 | +#define SYM_DEFINE 1 | |
59 | + | |
60 | +/* tokens in string heap */ | |
61 | +#define TAG_TOK ' ' | |
62 | +#define TAG_MACRO 2 | |
63 | + | |
64 | +pdef(t) | |
65 | +{ | |
66 | + *(char *)dstk++ = t; | |
61 | 67 | } |
62 | 68 | |
63 | -static void nextChar() { | |
64 | - if (pInProgressMacro) { | |
65 | - currentChar = *(char*) pInProgressMacro++; | |
66 | - if (currentChar == 2) { | |
67 | - pInProgressMacro = NULL; | |
68 | - currentChar = savedChar; | |
69 | +inp() | |
70 | +{ | |
71 | + if (dptr) { | |
72 | + ch = *(char *)dptr++; | |
73 | + if (ch == TAG_MACRO) { | |
74 | + dptr = 0; | |
75 | + ch = dch; | |
69 | 76 | } |
70 | 77 | } else |
71 | - currentChar = fgetc(pInput); | |
78 | + ch = fgetc(file); | |
79 | + /* printf("ch=%c 0x%x\n", ch, ch); */ | |
72 | 80 | } |
73 | 81 | |
74 | -static int isSymbolChar() { | |
75 | - return isalnum(currentChar) || currentChar == '_'; | |
82 | +isid() | |
83 | +{ | |
84 | + return isalnum(ch) | ch == '_'; | |
76 | 85 | } |
77 | 86 | |
78 | -static void unescapeCurrentChar() { | |
79 | - if (currentChar == '\\') { | |
80 | - nextChar(); | |
81 | - if (currentChar == 'n') | |
82 | - currentChar = '\n'; | |
87 | +/* read a character constant */ | |
88 | +getq() | |
89 | +{ | |
90 | + if (ch == '\\') { | |
91 | + inp(); | |
92 | + if (ch == 'n') | |
93 | + ch = '\n'; | |
83 | 94 | } |
84 | 95 | } |
85 | 96 | |
86 | -static void nextToken() { | |
87 | - int j, m; | |
88 | - 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; | |
97 | +next() | |
98 | +{ | |
99 | + int t, l, a; | |
100 | + | |
101 | + while (isspace(ch) | ch == '#') { | |
102 | + if (ch == '#') { | |
103 | + inp(); | |
104 | + next(); | |
105 | + if (tok == TOK_DEFINE) { | |
106 | + next(); | |
107 | + pdef(TAG_TOK); /* fill last ident tag */ | |
108 | + *(int *)tok = SYM_DEFINE; | |
109 | + *(int *)(tok + 4) = dstk; /* define stack */ | |
97 | 110 | } |
98 | - while (currentChar != '\n') { | |
99 | - addToSymbolTable(currentChar); | |
100 | - nextChar(); | |
111 | + /* well we always save the values ! */ | |
112 | + while (ch != '\n') { | |
113 | + pdef(ch); | |
114 | + inp(); | |
101 | 115 | } |
102 | - addToSymbolTable(currentChar); | |
103 | - addToSymbolTable(2); | |
116 | + pdef(ch); | |
117 | + pdef(TAG_MACRO); | |
104 | 118 | } |
105 | - nextChar(); | |
119 | + inp(); | |
106 | 120 | } |
107 | - gCurrentTokenOperatorLevel = 0; | |
108 | - currentToken = currentChar; | |
109 | - if (isSymbolChar()) { | |
110 | - addToSymbolTable(' '); | |
111 | - M = pSymbolTable; | |
112 | - while (isSymbolChar()) { | |
113 | - addToSymbolTable(currentChar); | |
114 | - nextChar(); | |
121 | + tokl = 0; | |
122 | + tok = ch; | |
123 | + /* encode identifiers & numbers */ | |
124 | + if (isid()) { | |
125 | + pdef(TAG_TOK); | |
126 | + last_id = dstk; | |
127 | + while (isid()) { | |
128 | + pdef(ch); | |
129 | + inp(); | |
115 | 130 | } |
116 | - if (isdigit(currentToken)) { | |
117 | - currentTokenData = strtol(M, 0, 0); | |
118 | - currentToken = TOKEN_NUMBER; | |
131 | + if (isdigit(tok)) { | |
132 | + tokc = strtol(last_id, 0, 0); | |
133 | + tok = TOK_NUM; | |
119 | 134 | } else { |
120 | - *(char*) pSymbolTable = ' '; | |
121 | - currentToken = strstr(R, M - 1) - R; | |
122 | - *(char*) pSymbolTable = 0; | |
123 | - currentToken = currentToken * 8 + TOKEN_SYMBOL_BASE; | |
124 | - 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(); | |
135 | + *(char *)dstk = TAG_TOK; /* no need to mark end of string (we | |
136 | + suppose data is initied to zero */ | |
137 | + tok = strstr(sym_stk, last_id - 1) - sym_stk; | |
138 | + *(char *)dstk = 0; /* mark real end of ident for dlsym() */ | |
139 | + tok = tok * 8 + TOK_IDENT; | |
140 | + if (tok > TOK_DEFINE) { | |
141 | + tok = vars + tok; | |
142 | + /* printf("tok=%s %x\n", last_id, tok); */ | |
143 | + /* define handling */ | |
144 | + if (*(int *)tok == SYM_DEFINE) { | |
145 | + dptr = *(int *)(tok + 4); | |
146 | + dch = ch; | |
147 | + inp(); | |
148 | + next(); | |
131 | 149 | } |
132 | 150 | } |
133 | 151 | } |
134 | 152 | } else { |
135 | - 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; | |
153 | + inp(); | |
154 | + if (tok == '\'') { | |
155 | + tok = TOK_NUM; | |
156 | + getq(); | |
157 | + tokc = ch; | |
158 | + inp(); | |
159 | + inp(); | |
160 | + } else if (tok == '/' & ch == '*') { | |
161 | + inp(); | |
162 | + while (ch) { | |
163 | + while (ch != '*') | |
164 | + inp(); | |
165 | + inp(); | |
166 | + if (ch == '/') | |
167 | + ch = 0; | |
150 | 168 | } |
151 | - nextChar(); | |
152 | - nextToken(); | |
153 | - } 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++; | |
157 | - currentTokenData = 0; | |
158 | - while ((gCurrentTokenOperatorLevel = *(char*) e++ - 98) < 0) | |
159 | - currentTokenData = currentTokenData * 64 + gCurrentTokenOperatorLevel + 64; | |
160 | - if (j == currentToken && (m == currentChar || m == 64)) { | |
161 | - if (m == currentChar) { | |
162 | - nextChar(); | |
163 | - currentToken = TOKEN_OPERATOR; | |
169 | + inp(); | |
170 | + next(); | |
171 | + } else | |
172 | + { | |
173 | + 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"; | |
174 | + while (l = *(char *)t++) { | |
175 | + a = *(char *)t++; | |
176 | + tokc = 0; | |
177 | + while ((tokl = *(char *)t++ - 'b') < 0) | |
178 | + tokc = tokc * 64 + tokl + 64; | |
179 | + if (l == tok & (a == ch | a == '@')) { | |
180 | +#if 0 | |
181 | + printf("%c%c -> tokl=%d tokc=0x%x\n", | |
182 | + l, a, tokl, tokc); | |
183 | +#endif | |
184 | + if (a == ch) { | |
185 | + inp(); | |
186 | + tok = TOK_DUMMY; /* dummy token for double tokens */ | |
164 | 187 | } |
165 | 188 | break; |
166 | 189 | } |
167 | 190 | } |
168 | 191 | } |
169 | 192 | } |
193 | +#if 0 | |
194 | + { | |
195 | + int p; | |
196 | + | |
197 | + printf("tok=0x%x ", tok); | |
198 | + if (tok >= TOK_IDENT) { | |
199 | + printf("'"); | |
200 | + if (tok > TOK_DEFINE) | |
201 | + p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8; | |
202 | + else | |
203 | + p = sym_stk + 1 + (tok - TOK_IDENT) / 8; | |
204 | + while (*(char *)p != TAG_TOK && *(char *)p) | |
205 | + printf("%c", *(char *)p++); | |
206 | + printf("'\n"); | |
207 | + } else if (tok == TOK_NUM) { | |
208 | + printf("%d\n", tokc); | |
209 | + } else { | |
210 | + printf("'%c'\n", tok); | |
211 | + } | |
212 | + } | |
213 | +#endif | |
170 | 214 | } |
171 | 215 | |
172 | -/* | |
173 | - * Emit 1 to 4 bytes of code. Little-endian, doesn't emit high bytes that | |
174 | - * are 0x00 or 0xff | |
175 | - */ | |
176 | -static void emitCode(int g) { | |
177 | - while( g && g != -1) { | |
178 | - *(char*) gProgramCounter++=g; | |
179 | - g=g>>8; | |
216 | +void error(char *fmt,...) | |
217 | +{ | |
218 | + va_list ap; | |
219 | + | |
220 | + va_start(ap, fmt); | |
221 | + fprintf(stderr, "%d: ", ftell((FILE *)file)); | |
222 | + vfprintf(stderr, fmt, ap); | |
223 | + fprintf(stderr, "\n"); | |
224 | + exit(1); | |
225 | + va_end(ap); | |
226 | +} | |
227 | + | |
228 | +void skip(c) | |
229 | +{ | |
230 | + if (tok != c) { | |
231 | + error("'%c' expected", c); | |
180 | 232 | } |
233 | + next(); | |
181 | 234 | } |
182 | 235 | |
183 | -static void fixupAddress(e) { | |
184 | - int g; | |
185 | - while( e) { | |
186 | - g=*(int*) e; | |
187 | - *(int*) e=gProgramCounter-e-4; | |
188 | - e=g; | |
236 | +o(n) | |
237 | +{ | |
238 | + /* cannot use unsigned, so we must do a hack */ | |
239 | + while (n && n != -1) { | |
240 | + *(char *)ind++ = n; | |
241 | + n = n >> 8; | |
189 | 242 | } |
190 | 243 | } |
191 | 244 | |
192 | -static int emitCodeWithImmediate( g, e) { | |
193 | - emitCode(g); | |
194 | - *(int*) gProgramCounter = e; | |
195 | - e = gProgramCounter; | |
196 | - gProgramCounter = gProgramCounter + 4; | |
197 | - return e; | |
245 | +/* output a symbol and patch all calls to it */ | |
246 | +gsym(t) | |
247 | +{ | |
248 | + int n; | |
249 | + while (t) { | |
250 | + n = *(int *)t; /* next value */ | |
251 | + *(int *)t = ind - t - 4; | |
252 | + t = n; | |
253 | + } | |
198 | 254 | } |
199 | 255 | |
200 | -static int emitLoadAccumulatorImmediate(e) { | |
201 | - emitCodeWithImmediate(0xb8,e); /* Move immediate a, e */ | |
256 | +/* psym is used to put an instruction with a data field which is a | |
257 | + reference to a symbol. It is in fact the same as oad ! */ | |
258 | +#define psym oad | |
259 | + | |
260 | +/* instruction + address */ | |
261 | +oad(n, t) | |
262 | +{ | |
263 | + o(n); | |
264 | + *(int *)ind = t; | |
265 | + t = ind; | |
266 | + ind = ind + 4; | |
267 | + return t; | |
202 | 268 | } |
203 | 269 | |
204 | -static int emitBranch(e) { | |
205 | - return emitCodeWithImmediate(0xe9,e); /* Jump relative */ | |
270 | +/* load immediate value */ | |
271 | +li(t) | |
272 | +{ | |
273 | + oad(0xb8, t); /* mov $xx, %eax */ | |
206 | 274 | } |
207 | 275 | |
208 | -static int emitTest( j, e) { | |
209 | - emitCode(0x0FC085); /* 85 C0 FC TEST */ | |
210 | - return emitCodeWithImmediate(0x84 + j, e); /* TEST */ | |
276 | +gjmp(t) | |
277 | +{ | |
278 | + return psym(0xe9, t); | |
211 | 279 | } |
212 | 280 | |
213 | -static void emitSetCC(int condition) { | |
214 | - emitCode( 0xC139); /* 39 C1 CMP */ | |
215 | - emitLoadAccumulatorImmediate(0); | |
216 | - 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 */ | |
281 | +/* l = 0: je, l == 1: jne */ | |
282 | +gtst(l, t) | |
283 | +{ | |
284 | + o(0x0fc085); /* test %eax, %eax, je/jne xxx */ | |
285 | + return psym(0x84 + l, t); | |
219 | 286 | } |
220 | 287 | |
221 | -static void emitNumericOp( int op, int e) { | |
222 | - emitCode(op + 0x83); | |
223 | - emitCodeWithImmediate((e < 512) << 7 | 5, e); | |
288 | +gcmp(t) | |
289 | +{ | |
290 | + o(0xc139); /* cmp %eax,%ecx */ | |
291 | + li(0); | |
292 | + o(0x0f); /* setxx %al */ | |
293 | + o(t + 0x90); | |
294 | + o(0xc0); | |
224 | 295 | } |
225 | 296 | |
226 | -static void parseTerminal (int level) { | |
227 | - int g,e,m,aa; | |
228 | - g=1; | |
229 | - if( currentToken == '"') { | |
230 | - emitLoadAccumulatorImmediate(gStringTable); | |
231 | - while( currentChar != '"') { | |
232 | - unescapeCurrentChar (); | |
233 | - *(char*) gStringTable++=currentChar; | |
234 | - nextChar (); | |
235 | - } | |
236 | - *(char*) gStringTable=0; | |
237 | - gStringTable= (char*) (((int)gStringTable) +4&-4); | |
238 | - nextChar(); | |
239 | - nextToken(); | |
240 | - } | |
241 | - else { | |
242 | - aa=gCurrentTokenOperatorLevel; | |
243 | - m= currentTokenData; | |
244 | - e=currentToken; | |
245 | - nextToken(); | |
246 | - if( e == TOKEN_NUMBER) { | |
247 | - emitLoadAccumulatorImmediate(m); | |
248 | - } | |
249 | - else if( aa == 2) { | |
250 | - parseTerminal(0); | |
251 | - emitCodeWithImmediate(0xB9,0); /* MOV r1, immediate */ | |
252 | - if( e == '!')emitSetCC(m); | |
253 | - else emitCode( m); | |
254 | - } | |
255 | - else if( e == '(') { | |
256 | - parseExpression (); | |
257 | - nextToken(); | |
297 | +gmov(l, t) | |
298 | +{ | |
299 | + o(l + 0x83); | |
300 | + oad((t < LOCAL) << 7 | 5, t); | |
301 | +} | |
302 | + | |
303 | +/* l is one if '=' parsing wanted (quick hack) */ | |
304 | +unary(l) | |
305 | +{ | |
306 | + int n, t, a, c; | |
307 | + | |
308 | + n = 1; /* type of expression 0 = forward, 1 = value, other = | |
309 | + lvalue */ | |
310 | + if (tok == '\"') { | |
311 | + li(glo); | |
312 | + while (ch != '\"') { | |
313 | + getq(); | |
314 | + *(char *)glo++ = ch; | |
315 | + inp(); | |
258 | 316 | } |
259 | - else if( e == '*') { | |
260 | - nextToken(); | |
261 | - e=currentToken; | |
262 | - nextToken(); | |
263 | - nextToken(); | |
264 | - if( currentToken == '*') { | |
265 | - nextToken(); | |
266 | - nextToken(); | |
267 | - nextToken(); | |
268 | - nextToken(); | |
269 | - e=0; | |
270 | - } | |
271 | - nextToken(); | |
272 | - parseTerminal(0); | |
273 | - if( currentToken == '=') { | |
274 | - nextToken(); | |
275 | - emitCode( 0x50); /* PUSH r0 */ | |
276 | - parseExpression (); | |
277 | - emitCode( 0x59); /* POP r1 */ | |
278 | - emitCode( 0x188 + (e == TOKEN_INT)); /* 88 01 MOV */ | |
317 | + *(char *)glo = 0; | |
318 | + glo = glo + 4 & -4; /* align heap */ | |
319 | + inp(); | |
320 | + next(); | |
321 | + } else { | |
322 | + c = tokl; | |
323 | + a = tokc; | |
324 | + t = tok; | |
325 | + next(); | |
326 | + if (t == TOK_NUM) { | |
327 | + li(a); | |
328 | + } else if (c == 2) { | |
329 | + /* -, +, !, ~ */ | |
330 | + unary(0); | |
331 | + oad(0xb9, 0); /* movl $0, %ecx */ | |
332 | + if (t == '!') | |
333 | + gcmp(a); | |
334 | + else | |
335 | + o(a); | |
336 | + } else if (t == '(') { | |
337 | + expr(); | |
338 | + skip(')'); | |
339 | + } else if (t == '*') { | |
340 | + /* parse cast */ | |
341 | + skip('('); | |
342 | + t = tok; /* get type */ | |
343 | + next(); /* skip int/char/void */ | |
344 | + next(); /* skip '*' or '(' */ | |
345 | + if (tok == '*') { | |
346 | + /* function type */ | |
347 | + skip('*'); | |
348 | + skip(')'); | |
349 | + skip('('); | |
350 | + skip(')'); | |
351 | + t = 0; | |
279 | 352 | } |
280 | - else if( e) { | |
281 | - if( e == TOKEN_INT)emitCode( 0x8B); /* MOV */ | |
282 | - else emitCode( 0xBE0F); /* 0F BE MOVSX move with sign extension */ | |
283 | - gProgramCounter++; | |
353 | + skip(')'); | |
354 | + unary(0); | |
355 | + if (tok == '=') { | |
356 | + next(); | |
357 | + o(0x50); /* push %eax */ | |
358 | + expr(); | |
359 | + o(0x59); /* pop %ecx */ | |
360 | + o(0x0188 + (t == TOK_INT)); /* movl %eax/%al, (%ecx) */ | |
361 | + } else if (t) { | |
362 | + if (t == TOK_INT) | |
363 | + o(0x8b); /* mov (%eax), %eax */ | |
364 | + else | |
365 | + o(0xbe0f); /* movsbl (%eax), %eax */ | |
366 | + ind++; /* add zero in code */ | |
284 | 367 | } |
285 | - } | |
286 | - else if( e == '&') { | |
287 | - emitNumericOp(10,*(int*) currentToken); /* 8D LEA */ | |
288 | - nextToken(); | |
289 | - } | |
290 | - else { | |
291 | - g=*(int*) e; | |
292 | - if(!g)g=dlsym(0,M); | |
293 | - if( currentToken == '=' & level) { | |
294 | - nextToken(); | |
295 | - parseExpression (); | |
296 | - emitNumericOp(6,g); /* 89 MOV */ | |
297 | - } | |
298 | - else if( currentToken!= '(') { | |
299 | - emitNumericOp(8,g); /* 8B MOV sreg */ | |
300 | - if( gCurrentTokenOperatorLevel == 11) { | |
301 | - emitNumericOp(0,g); /* 83 ADD */ | |
302 | - emitCode( currentTokenData); | |
303 | - nextToken(); | |
368 | + } else if (t == '&') { | |
369 | + gmov(10, *(int *)tok); /* leal EA, %eax */ | |
370 | + next(); | |
371 | + } else { | |
372 | + n = *(int *)t; | |
373 | + /* forward reference: try dlsym */ | |
374 | + if (!n) | |
375 | + n = dlsym(0, last_id); | |
376 | + if (tok == '=' & l) { | |
377 | + /* assignment */ | |
378 | + next(); | |
379 | + expr(); | |
380 | + gmov(6, n); /* mov %eax, EA */ | |
381 | + } else if (tok != '(') { | |
382 | + /* variable */ | |
383 | + gmov(8, n); /* mov EA, %eax */ | |
384 | + if (tokl == 11) { | |
385 | + gmov(0, n); | |
386 | + o(tokc); | |
387 | + next(); | |
304 | 388 | } |
305 | 389 | } |
306 | 390 | } |
307 | 391 | } |
308 | - if( currentToken == '(') { | |
309 | - if( g == 1)emitCode( 0x50); /* push */ | |
310 | - m= emitCodeWithImmediate(0xEC81,0); /* 81 EC Cmp ?? */ | |
311 | - nextToken(); | |
312 | - level=0; | |
313 | - while( currentToken!= ')') { | |
314 | - parseExpression (); | |
315 | - emitCodeWithImmediate(0x248489,level); /* 89 84 24 MOV sp + level*/ | |
316 | - if( currentToken == ',')nextToken(); | |
317 | - level=level +4; | |
318 | - } | |
319 | - *(int*) m= level; | |
320 | - nextToken(); | |
321 | - if(!g) { | |
322 | - e=e +4; | |
323 | - *(int*) e=emitCodeWithImmediate(0xE8,*(int*) e); /* Call */ | |
324 | - } | |
325 | - else if( g == 1) { | |
326 | - emitCodeWithImmediate(0x2494FF,level); /* FF 94 24 */ | |
327 | - level=level +4; | |
392 | + | |
393 | + /* function call */ | |
394 | + if (tok == '(') { | |
395 | + if (n == 1) | |
396 | + o(0x50); /* push %eax */ | |
397 | + | |
398 | + /* push args and invert order */ | |
399 | + a = oad(0xec81, 0); /* sub $xxx, %esp */ | |
400 | + next(); | |
401 | + l = 0; | |
402 | + while(tok != ')') { | |
403 | + expr(); | |
404 | + oad(0x248489, l); /* movl %eax, xxx(%esp) */ | |
405 | + if (tok == ',') | |
406 | + next(); | |
407 | + l = l + 4; | |
328 | 408 | } |
329 | - else { | |
330 | - emitCodeWithImmediate(0xE8,g-gProgramCounter-5); /* CALL */ | |
409 | + *(int *)a = l; | |
410 | + next(); | |
411 | + if (!n) { | |
412 | + /* forward reference */ | |
413 | + t = t + 4; | |
414 | + *(int *)t = psym(0xe8, *(int *)t); | |
415 | + } else if (n == 1) { | |
416 | + oad(0x2494ff, l); /* call *xxx(%esp) */ | |
417 | + l = l + 4; | |
418 | + } else { | |
419 | + oad(0xe8, n - ind - 5); /* call xxx */ | |
331 | 420 | } |
332 | - if( level)emitCodeWithImmediate(0xC481,level); /* 81 C4 adjust stack pointer */ | |
421 | + if (l) | |
422 | + oad(0xc481, l); /* add $xxx, %esp */ | |
333 | 423 | } |
334 | 424 | } |
335 | 425 | |
336 | -static void parseBinaryOp (int level) { | |
337 | - int e,g,m; | |
338 | - if( level--== 1)parseTerminal(1); | |
426 | +sum(l) | |
427 | +{ | |
428 | + int t, n, a; | |
429 | + | |
430 | + if (l-- == 1) | |
431 | + unary(1); | |
339 | 432 | else { |
340 | - parseBinaryOp (level); | |
341 | - m= 0; | |
342 | - while( level == gCurrentTokenOperatorLevel) { | |
343 | - g=currentToken; | |
344 | - e=currentTokenData; | |
345 | - nextToken(); | |
346 | - if( level>8) { | |
347 | - m= emitTest(e,m); | |
348 | - parseBinaryOp (level); | |
349 | - } | |
350 | - else { | |
351 | - emitCode( 0x50); | |
352 | - parseBinaryOp (level); | |
353 | - emitCode( 0x59); | |
354 | - if( level == 4 | level == 5) { | |
355 | - emitSetCC(e); | |
356 | - } | |
357 | - else { | |
358 | - emitCode( e); | |
359 | - if( g == '%')emitCode( 0x92); /* XCHG */ | |
433 | + sum(l); | |
434 | + a = 0; | |
435 | + while (l == tokl) { | |
436 | + n = tok; | |
437 | + t = tokc; | |
438 | + next(); | |
439 | + | |
440 | + if (l > 8) { | |
441 | + a = gtst(t, a); /* && and || output code generation */ | |
442 | + sum(l); | |
443 | + } else { | |
444 | + o(0x50); /* push %eax */ | |
445 | + sum(l); | |
446 | + o(0x59); /* pop %ecx */ | |
447 | + | |
448 | + if (l == 4 | l == 5) { | |
449 | + gcmp(t); | |
450 | + } else { | |
451 | + o(t); | |
452 | + if (n == '%') | |
453 | + o(0x92); /* xchg %edx, %eax */ | |
360 | 454 | } |
361 | 455 | } |
362 | 456 | } |
363 | - if( m&&level>8) { | |
364 | - m= emitTest(e,m); | |
365 | - emitLoadAccumulatorImmediate(e^1); | |
366 | - emitBranch(5); /* Jump relative +5 */ | |
367 | - fixupAddress(m); | |
368 | - emitLoadAccumulatorImmediate(e); | |
457 | + /* && and || output code generation */ | |
458 | + if (a && l > 8) { | |
459 | + a = gtst(t, a); | |
460 | + li(t ^ 1); | |
461 | + gjmp(5); /* jmp $ + 5 */ | |
462 | + gsym(a); | |
463 | + li(t); | |
369 | 464 | } |
370 | 465 | } |
371 | 466 | } |
372 | 467 | |
373 | -static void parseExpression() { | |
374 | - parseBinaryOp(11); | |
468 | +expr() | |
469 | +{ | |
470 | + sum(11); | |
375 | 471 | } |
376 | 472 | |
377 | -static int parseExpressionEmitTest() { | |
378 | - parseExpression(); | |
379 | - return emitTest(0, 0); | |
473 | + | |
474 | +test_expr() | |
475 | +{ | |
476 | + expr(); | |
477 | + return gtst(0, 0); | |
380 | 478 | } |
381 | 479 | |
382 | -static void parseStatement (int* pBreakTarget) { | |
383 | - int m,g,e; | |
384 | - if( currentToken == TOKEN_IF) { | |
385 | - nextToken(); | |
386 | - nextToken(); | |
387 | - m= parseExpressionEmitTest (); | |
388 | - nextToken(); | |
389 | - parseStatement (pBreakTarget); | |
390 | - if( currentToken == TOKEN_ELSE) { | |
391 | - nextToken(); | |
392 | - g=emitBranch(0); | |
393 | - fixupAddress(m); | |
394 | - parseStatement (pBreakTarget); | |
395 | - fixupAddress(g); | |
396 | - } | |
397 | - else { | |
398 | - fixupAddress(m); | |
399 | - } | |
400 | - } | |
401 | - else if ( currentToken == TOKEN_WHILE || currentToken == TOKEN_FOR) { | |
402 | - e = currentToken; | |
403 | - nextToken(); | |
404 | - nextToken(); | |
405 | - if( e == TOKEN_WHILE) { | |
406 | - g=gProgramCounter; | |
407 | - m= parseExpressionEmitTest (); | |
480 | +block(l) | |
481 | +{ | |
482 | + int a, n, t; | |
483 | + | |
484 | + if (tok == TOK_IF) { | |
485 | + next(); | |
486 | + skip('('); | |
487 | + a = test_expr(); | |
488 | + skip(')'); | |
489 | + block(l); | |
490 | + if (tok == TOK_ELSE) { | |
491 | + next(); | |
492 | + n = gjmp(0); /* jmp */ | |
493 | + gsym(a); | |
494 | + block(l); | |
495 | + gsym(n); /* patch else jmp */ | |
496 | + } else { | |
497 | + gsym(a); /* patch if test */ | |
408 | 498 | } |
409 | - else { | |
410 | - if( currentToken != ';')parseExpression (); | |
411 | - nextToken(); | |
412 | - g=gProgramCounter; | |
413 | - m= 0; | |
414 | - if( currentToken != ';')m= parseExpressionEmitTest (); | |
415 | - nextToken(); | |
416 | - if( currentToken!= ')') { | |
417 | - e=emitBranch(0); | |
418 | - parseExpression (); | |
419 | - emitBranch(g-gProgramCounter-5); | |
420 | - fixupAddress(e); | |
421 | - g=e +4; | |
499 | + } else if (tok == TOK_WHILE | tok == TOK_FOR) { | |
500 | + t = tok; | |
501 | + next(); | |
502 | + skip('('); | |
503 | + if (t == TOK_WHILE) { | |
504 | + n = ind; | |
505 | + a = test_expr(); | |
506 | + } else { | |
507 | + if (tok != ';') | |
508 | + expr(); | |
509 | + skip(';'); | |
510 | + n = ind; | |
511 | + a = 0; | |
512 | + if (tok != ';') | |
513 | + a = test_expr(); | |
514 | + skip(';'); | |
515 | + if (tok != ')') { | |
516 | + t = gjmp(0); | |
517 | + expr(); | |
518 | + gjmp(n - ind - 5); | |
519 | + gsym(t); | |
520 | + n = t + 4; | |
422 | 521 | } |
423 | 522 | } |
424 | - nextToken(); | |
425 | - parseStatement(&m); | |
426 | - emitBranch(g-gProgramCounter-5); | |
427 | - fixupAddress(m); | |
428 | - } | |
429 | - else if( currentToken == '{') { | |
430 | - nextToken(); | |
431 | - parseDeclarations(1); | |
432 | - while( currentToken != '}') parseStatement(pBreakTarget); | |
433 | - nextToken(); | |
434 | - } | |
435 | - else { | |
436 | - if( currentToken == TOKEN_RETURN) { | |
437 | - nextToken(); | |
438 | - if( currentToken != ';') parseExpression(); | |
439 | - gEndOfFunctionTarget=emitBranch(gEndOfFunctionTarget); | |
440 | - } | |
441 | - else if( currentToken == TOKEN_BREAK) { | |
442 | - nextToken(); | |
443 | - *pBreakTarget = emitBranch(*pBreakTarget); | |
444 | - } | |
445 | - else if( currentToken != ';') parseExpression(); | |
446 | - nextToken(); | |
523 | + skip(')'); | |
524 | + block(&a); | |
525 | + gjmp(n - ind - 5); /* jmp */ | |
526 | + gsym(a); | |
527 | + } else if (tok == '{') { | |
528 | + next(); | |
529 | + /* declarations */ | |
530 | + decl(1); | |
531 | + while(tok != '}') | |
532 | + block(l); | |
533 | + next(); | |
534 | + } else { | |
535 | + if (tok == TOK_RETURN) { | |
536 | + next(); | |
537 | + if (tok != ';') | |
538 | + expr(); | |
539 | + rsym = gjmp(rsym); /* jmp */ | |
540 | + } else if (tok == TOK_BREAK) { | |
541 | + next(); | |
542 | + *(int *)l = gjmp(*(int *)l); | |
543 | + } else if (tok != ';') | |
544 | + expr(); | |
545 | + skip(';'); | |
447 | 546 | } |
448 | 547 | } |
449 | 548 | |
450 | -static void parseDeclarations (int isLocal) { | |
451 | - int m; | |
452 | - while( currentToken == TOKEN_INT | currentToken != -1 & !isLocal ) { | |
453 | - if( currentToken == TOKEN_INT) { | |
454 | - nextToken(); | |
455 | - while( currentToken != ';') { | |
456 | - if( isLocal ) { | |
457 | - gFunctionStackSize=gFunctionStackSize +4; | |
458 | - *(int*) currentToken=-gFunctionStackSize; | |
459 | - } | |
460 | - else { | |
461 | - *(char**) currentToken = gStringTable; | |
462 | - gStringTable=gStringTable +4; | |
549 | +/* 'l' is true if local declarations */ | |
550 | +decl(l) | |
551 | +{ | |
552 | + int a; | |
553 | + | |
554 | + while (tok == TOK_INT | tok != -1 & !l) { | |
555 | + if (tok == TOK_INT) { | |
556 | + next(); | |
557 | + while (tok != ';') { | |
558 | + if (l) { | |
559 | + loc = loc + 4; | |
560 | + *(int *)tok = -loc; | |
561 | + } else { | |
562 | + *(int *)tok = glo; | |
563 | + glo = glo + 4; | |
463 | 564 | } |
464 | - nextToken(); | |
465 | - if( currentToken == ',')nextToken(); | |
565 | + next(); | |
566 | + if (tok == ',') | |
567 | + next(); | |
466 | 568 | } |
467 | - nextToken(); | |
468 | - } | |
469 | - else { | |
470 | - fixupAddress(*(int*)(currentToken + 4)); | |
471 | - *(int*) currentToken=gProgramCounter; | |
472 | - nextToken(); | |
473 | - nextToken(); | |
474 | - m= 8; | |
475 | - while( currentToken != ')') { | |
476 | - *(int*) currentToken=m; | |
477 | - m= m +4; | |
478 | - nextToken(); | |
479 | - if( currentToken == ',')nextToken(); | |
569 | + skip(';'); | |
570 | + } else { | |
571 | + /* patch forward references (XXX: do not work for function | |
572 | + pointers) */ | |
573 | + gsym(*(int *)(tok + 4)); | |
574 | + /* put function address */ | |
575 | + *(int *)tok = ind; | |
576 | + next(); | |
577 | + skip('('); | |
578 | + a = 8; | |
579 | + while (tok != ')') { | |
580 | + /* read param name and compute offset */ | |
581 | + *(int *)tok = a; | |
582 | + a = a + 4; | |
583 | + next(); | |
584 | + if (tok == ',') | |
585 | + next(); | |
480 | 586 | } |
481 | - nextToken(); | |
482 | - gEndOfFunctionTarget=gFunctionStackSize=0; | |
483 | - emitCode( 0xE58955); /* 55 89 E5 PUSH */ | |
484 | - m= emitCodeWithImmediate(0xEC81,0); /* 81 EC */ | |
485 | - parseStatement(0); | |
486 | - fixupAddress(gEndOfFunctionTarget); | |
487 | - emitCode( 0xC3C9); /* C9 C3 LEAVE */ | |
488 | - *(int*) m= gFunctionStackSize; | |
587 | + next(); /* skip ')' */ | |
588 | + rsym = loc = 0; | |
589 | + o(0xe58955); /* push %ebp, mov %esp, %ebp */ | |
590 | + a = oad(0xec81, 0); /* sub $xxx, %esp */ | |
591 | + block(0); | |
592 | + gsym(rsym); | |
593 | + o(0xc3c9); /* leave, ret */ | |
594 | + *(int *)a = loc; /* save local variables */ | |
489 | 595 | } |
490 | 596 | } |
491 | 597 | } |
492 | 598 | |
493 | -int main( int argc, char** argv) { | |
494 | - pInput = stdin; | |
495 | - if (argc-- > 1) { | |
496 | - char* file = argv[1]; | |
497 | - argv += 1; | |
498 | - pInput = fopen(file, "r"); | |
499 | - if (pInput == NULL) { | |
500 | - fprintf(stderr, "Could not open file \"%s\"\n", file); | |
501 | - return -1; | |
502 | - } | |
599 | +main(n, t) | |
600 | +{ | |
601 | + file = stdin; | |
602 | + if (n-- > 1) { | |
603 | + t = t + 4; | |
604 | + file = fopen(*(int *)t, "r"); | |
605 | + } | |
606 | + dstk = strcpy(sym_stk = calloc(1, ALLOC_SIZE), | |
607 | + " int if else while break return for define main ") + TOK_STR_SIZE; | |
608 | + glo = calloc(1, ALLOC_SIZE); | |
609 | + ind = prog = calloc(1, ALLOC_SIZE); | |
610 | + vars = calloc(1, ALLOC_SIZE); | |
611 | + inp(); | |
612 | + next(); | |
613 | + decl(0); | |
614 | +#ifdef TEST | |
615 | + { | |
616 | + FILE *f; | |
617 | + f = fopen(*(char **)(t + 4), "w"); | |
618 | + fwrite((void *)prog, 1, ind - prog, f); | |
619 | + fclose(f); | |
620 | + return 0; | |
503 | 621 | } |
504 | - pSymbolTable = strcpy(R = calloc(1, 99999), | |
505 | - " int if else while break return for define main ") + 48; | |
506 | - gStringTable = calloc(1, 99999); | |
507 | - ac = calloc(1, 99999); | |
508 | - gProgramCounter = (int) ac; | |
509 | - P = calloc(1, 99999); | |
510 | - nextChar(); | |
511 | - nextToken(); | |
512 | - parseDeclarations(0); | |
513 | -#if 1 | |
514 | - fwrite(R, 1, 99999, stdout); | |
515 | - fwrite(ac, 1, 99999, stdout); | |
516 | - fwrite(P, 1, 99999, stdout); | |
517 | - return 0; | |
518 | 622 | #else |
519 | - /* 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 | - */ | |
522 | - return (*(int(*)()) *(int*) (P + 592))(argc, argv); | |
623 | + return (*(int (*)())*(int *)(vars + TOK_MAIN)) (n, t); | |
523 | 624 | #endif |
524 | 625 | } |
525 | - |
@@ -1,632 +0,0 @@ | ||
1 | -/* | |
2 | - Obfuscated Tiny C Compiler | |
3 | - | |
4 | - Copyright (C) 2001-2003 Fabrice Bellard | |
5 | - | |
6 | - 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 | |
16 | - in a product, an acknowledgment in the product and its documentation | |
17 | - *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 | -#ifndef TINY | |
23 | -#include <stdarg.h> | |
24 | -#endif | |
25 | -#include <stdio.h> | |
26 | - | |
27 | -/* vars: value of variables | |
28 | - loc : local variable index | |
29 | - glo : global variable index | |
30 | - ind : output code ptr | |
31 | - rsym: return symbol | |
32 | - prog: output code | |
33 | - dstk: define stack | |
34 | - dptr, dch: macro state | |
35 | -*/ | |
36 | -int tok, tokc, tokl, ch, vars, rsym, prog, ind, loc, glo, file, sym_stk, dstk, dptr, dch, last_id; | |
37 | - | |
38 | -#define ALLOC_SIZE 99999 | |
39 | - | |
40 | -/* depends on the init string */ | |
41 | -#define TOK_STR_SIZE 48 | |
42 | -#define TOK_IDENT 0x100 | |
43 | -#define TOK_INT 0x100 | |
44 | -#define TOK_IF 0x120 | |
45 | -#define TOK_ELSE 0x138 | |
46 | -#define TOK_WHILE 0x160 | |
47 | -#define TOK_BREAK 0x190 | |
48 | -#define TOK_RETURN 0x1c0 | |
49 | -#define TOK_FOR 0x1f8 | |
50 | -#define TOK_DEFINE 0x218 | |
51 | -#define TOK_MAIN 0x250 | |
52 | - | |
53 | -#define TOK_DUMMY 1 | |
54 | -#define TOK_NUM 2 | |
55 | - | |
56 | -#define LOCAL 0x200 | |
57 | - | |
58 | -#define SYM_FORWARD 0 | |
59 | -#define SYM_DEFINE 1 | |
60 | - | |
61 | -/* tokens in string heap */ | |
62 | -#define TAG_TOK ' ' | |
63 | -#define TAG_MACRO 2 | |
64 | - | |
65 | -pdef(t) | |
66 | -{ | |
67 | - *(char *)dstk++ = t; | |
68 | -} | |
69 | - | |
70 | -inp() | |
71 | -{ | |
72 | - if (dptr) { | |
73 | - ch = *(char *)dptr++; | |
74 | - if (ch == TAG_MACRO) { | |
75 | - dptr = 0; | |
76 | - ch = dch; | |
77 | - } | |
78 | - } else | |
79 | - ch = fgetc(file); | |
80 | - /* printf("ch=%c 0x%x\n", ch, ch); */ | |
81 | -} | |
82 | - | |
83 | -isid() | |
84 | -{ | |
85 | - return isalnum(ch) | ch == '_'; | |
86 | -} | |
87 | - | |
88 | -/* read a character constant */ | |
89 | -getq() | |
90 | -{ | |
91 | - if (ch == '\\') { | |
92 | - inp(); | |
93 | - if (ch == 'n') | |
94 | - ch = '\n'; | |
95 | - } | |
96 | -} | |
97 | - | |
98 | -next() | |
99 | -{ | |
100 | - int t, l, a; | |
101 | - | |
102 | - while (isspace(ch) | ch == '#') { | |
103 | - if (ch == '#') { | |
104 | - inp(); | |
105 | - next(); | |
106 | - if (tok == TOK_DEFINE) { | |
107 | - next(); | |
108 | - pdef(TAG_TOK); /* fill last ident tag */ | |
109 | - *(int *)tok = SYM_DEFINE; | |
110 | - *(int *)(tok + 4) = dstk; /* define stack */ | |
111 | - } | |
112 | - /* well we always save the values ! */ | |
113 | - while (ch != '\n') { | |
114 | - pdef(ch); | |
115 | - inp(); | |
116 | - } | |
117 | - pdef(ch); | |
118 | - pdef(TAG_MACRO); | |
119 | - } | |
120 | - inp(); | |
121 | - } | |
122 | - tokl = 0; | |
123 | - tok = ch; | |
124 | - /* encode identifiers & numbers */ | |
125 | - if (isid()) { | |
126 | - pdef(TAG_TOK); | |
127 | - last_id = dstk; | |
128 | - while (isid()) { | |
129 | - pdef(ch); | |
130 | - inp(); | |
131 | - } | |
132 | - if (isdigit(tok)) { | |
133 | - tokc = strtol(last_id, 0, 0); | |
134 | - tok = TOK_NUM; | |
135 | - } else { | |
136 | - *(char *)dstk = TAG_TOK; /* no need to mark end of string (we | |
137 | - suppose data is initied to zero */ | |
138 | - tok = strstr(sym_stk, last_id - 1) - sym_stk; | |
139 | - *(char *)dstk = 0; /* mark real end of ident for dlsym() */ | |
140 | - tok = tok * 8 + TOK_IDENT; | |
141 | - if (tok > TOK_DEFINE) { | |
142 | - tok = vars + tok; | |
143 | - /* printf("tok=%s %x\n", last_id, tok); */ | |
144 | - /* define handling */ | |
145 | - if (*(int *)tok == SYM_DEFINE) { | |
146 | - dptr = *(int *)(tok + 4); | |
147 | - dch = ch; | |
148 | - inp(); | |
149 | - next(); | |
150 | - } | |
151 | - } | |
152 | - } | |
153 | - } else { | |
154 | - inp(); | |
155 | - if (tok == '\'') { | |
156 | - tok = TOK_NUM; | |
157 | - getq(); | |
158 | - tokc = ch; | |
159 | - inp(); | |
160 | - inp(); | |
161 | - } else if (tok == '/' & ch == '*') { | |
162 | - inp(); | |
163 | - while (ch) { | |
164 | - while (ch != '*') | |
165 | - inp(); | |
166 | - inp(); | |
167 | - if (ch == '/') | |
168 | - ch = 0; | |
169 | - } | |
170 | - inp(); | |
171 | - next(); | |
172 | - } else | |
173 | - { | |
174 | - 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"; | |
175 | - while (l = *(char *)t++) { | |
176 | - a = *(char *)t++; | |
177 | - tokc = 0; | |
178 | - while ((tokl = *(char *)t++ - 'b') < 0) | |
179 | - tokc = tokc * 64 + tokl + 64; | |
180 | - if (l == tok & (a == ch | a == '@')) { | |
181 | -#if 0 | |
182 | - printf("%c%c -> tokl=%d tokc=0x%x\n", | |
183 | - l, a, tokl, tokc); | |
184 | -#endif | |
185 | - if (a == ch) { | |
186 | - inp(); | |
187 | - tok = TOK_DUMMY; /* dummy token for double tokens */ | |
188 | - } | |
189 | - break; | |
190 | - } | |
191 | - } | |
192 | - } | |
193 | - } | |
194 | -#if 0 | |
195 | - { | |
196 | - int p; | |
197 | - | |
198 | - printf("tok=0x%x ", tok); | |
199 | - if (tok >= TOK_IDENT) { | |
200 | - printf("'"); | |
201 | - if (tok > TOK_DEFINE) | |
202 | - p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8; | |
203 | - else | |
204 | - p = sym_stk + 1 + (tok - TOK_IDENT) / 8; | |
205 | - while (*(char *)p != TAG_TOK && *(char *)p) | |
206 | - printf("%c", *(char *)p++); | |
207 | - printf("'\n"); | |
208 | - } else if (tok == TOK_NUM) { | |
209 | - printf("%d\n", tokc); | |
210 | - } else { | |
211 | - printf("'%c'\n", tok); | |
212 | - } | |
213 | - } | |
214 | -#endif | |
215 | -} | |
216 | - | |
217 | -#ifdef TINY | |
218 | -#define skip(c) next() | |
219 | -#else | |
220 | - | |
221 | -void error(char *fmt,...) | |
222 | -{ | |
223 | - va_list ap; | |
224 | - | |
225 | - va_start(ap, fmt); | |
226 | - fprintf(stderr, "%d: ", ftell((FILE *)file)); | |
227 | - vfprintf(stderr, fmt, ap); | |
228 | - fprintf(stderr, "\n"); | |
229 | - exit(1); | |
230 | - va_end(ap); | |
231 | -} | |
232 | - | |
233 | -void skip(c) | |
234 | -{ | |
235 | - if (tok != c) { | |
236 | - error("'%c' expected", c); | |
237 | - } | |
238 | - next(); | |
239 | -} | |
240 | - | |
241 | -#endif | |
242 | - | |
243 | -o(n) | |
244 | -{ | |
245 | - /* cannot use unsigned, so we must do a hack */ | |
246 | - while (n && n != -1) { | |
247 | - *(char *)ind++ = n; | |
248 | - n = n >> 8; | |
249 | - } | |
250 | -} | |
251 | - | |
252 | -/* output a symbol and patch all calls to it */ | |
253 | -gsym(t) | |
254 | -{ | |
255 | - int n; | |
256 | - while (t) { | |
257 | - n = *(int *)t; /* next value */ | |
258 | - *(int *)t = ind - t - 4; | |
259 | - t = n; | |
260 | - } | |
261 | -} | |
262 | - | |
263 | -/* psym is used to put an instruction with a data field which is a | |
264 | - reference to a symbol. It is in fact the same as oad ! */ | |
265 | -#define psym oad | |
266 | - | |
267 | -/* instruction + address */ | |
268 | -oad(n, t) | |
269 | -{ | |
270 | - o(n); | |
271 | - *(int *)ind = t; | |
272 | - t = ind; | |
273 | - ind = ind + 4; | |
274 | - return t; | |
275 | -} | |
276 | - | |
277 | -/* load immediate value */ | |
278 | -li(t) | |
279 | -{ | |
280 | - oad(0xb8, t); /* mov $xx, %eax */ | |
281 | -} | |
282 | - | |
283 | -gjmp(t) | |
284 | -{ | |
285 | - return psym(0xe9, t); | |
286 | -} | |
287 | - | |
288 | -/* l = 0: je, l == 1: jne */ | |
289 | -gtst(l, t) | |
290 | -{ | |
291 | - o(0x0fc085); /* test %eax, %eax, je/jne xxx */ | |
292 | - return psym(0x84 + l, t); | |
293 | -} | |
294 | - | |
295 | -gcmp(t) | |
296 | -{ | |
297 | - o(0xc139); /* cmp %eax,%ecx */ | |
298 | - li(0); | |
299 | - o(0x0f); /* setxx %al */ | |
300 | - o(t + 0x90); | |
301 | - o(0xc0); | |
302 | -} | |
303 | - | |
304 | -gmov(l, t) | |
305 | -{ | |
306 | - o(l + 0x83); | |
307 | - oad((t < LOCAL) << 7 | 5, t); | |
308 | -} | |
309 | - | |
310 | -/* l is one if '=' parsing wanted (quick hack) */ | |
311 | -unary(l) | |
312 | -{ | |
313 | - int n, t, a, c; | |
314 | - | |
315 | - n = 1; /* type of expression 0 = forward, 1 = value, other = | |
316 | - lvalue */ | |
317 | - if (tok == '\"') { | |
318 | - li(glo); | |
319 | - while (ch != '\"') { | |
320 | - getq(); | |
321 | - *(char *)glo++ = ch; | |
322 | - inp(); | |
323 | - } | |
324 | - *(char *)glo = 0; | |
325 | - glo = glo + 4 & -4; /* align heap */ | |
326 | - inp(); | |
327 | - next(); | |
328 | - } else { | |
329 | - c = tokl; | |
330 | - a = tokc; | |
331 | - t = tok; | |
332 | - next(); | |
333 | - if (t == TOK_NUM) { | |
334 | - li(a); | |
335 | - } else if (c == 2) { | |
336 | - /* -, +, !, ~ */ | |
337 | - unary(0); | |
338 | - oad(0xb9, 0); /* movl $0, %ecx */ | |
339 | - if (t == '!') | |
340 | - gcmp(a); | |
341 | - else | |
342 | - o(a); | |
343 | - } else if (t == '(') { | |
344 | - expr(); | |
345 | - skip(')'); | |
346 | - } else if (t == '*') { | |
347 | - /* parse cast */ | |
348 | - skip('('); | |
349 | - t = tok; /* get type */ | |
350 | - next(); /* skip int/char/void */ | |
351 | - next(); /* skip '*' or '(' */ | |
352 | - if (tok == '*') { | |
353 | - /* function type */ | |
354 | - skip('*'); | |
355 | - skip(')'); | |
356 | - skip('('); | |
357 | - skip(')'); | |
358 | - t = 0; | |
359 | - } | |
360 | - skip(')'); | |
361 | - unary(0); | |
362 | - if (tok == '=') { | |
363 | - next(); | |
364 | - o(0x50); /* push %eax */ | |
365 | - expr(); | |
366 | - o(0x59); /* pop %ecx */ | |
367 | - o(0x0188 + (t == TOK_INT)); /* movl %eax/%al, (%ecx) */ | |
368 | - } else if (t) { | |
369 | - if (t == TOK_INT) | |
370 | - o(0x8b); /* mov (%eax), %eax */ | |
371 | - else | |
372 | - o(0xbe0f); /* movsbl (%eax), %eax */ | |
373 | - ind++; /* add zero in code */ | |
374 | - } | |
375 | - } else if (t == '&') { | |
376 | - gmov(10, *(int *)tok); /* leal EA, %eax */ | |
377 | - next(); | |
378 | - } else { | |
379 | - n = *(int *)t; | |
380 | - /* forward reference: try dlsym */ | |
381 | - if (!n) | |
382 | - n = dlsym(0, last_id); | |
383 | - if (tok == '=' & l) { | |
384 | - /* assignment */ | |
385 | - next(); | |
386 | - expr(); | |
387 | - gmov(6, n); /* mov %eax, EA */ | |
388 | - } else if (tok != '(') { | |
389 | - /* variable */ | |
390 | - gmov(8, n); /* mov EA, %eax */ | |
391 | - if (tokl == 11) { | |
392 | - gmov(0, n); | |
393 | - o(tokc); | |
394 | - next(); | |
395 | - } | |
396 | - } | |
397 | - } | |
398 | - } | |
399 | - | |
400 | - /* function call */ | |
401 | - if (tok == '(') { | |
402 | - if (n == 1) | |
403 | - o(0x50); /* push %eax */ | |
404 | - | |
405 | - /* push args and invert order */ | |
406 | - a = oad(0xec81, 0); /* sub $xxx, %esp */ | |
407 | - next(); | |
408 | - l = 0; | |
409 | - while(tok != ')') { | |
410 | - expr(); | |
411 | - oad(0x248489, l); /* movl %eax, xxx(%esp) */ | |
412 | - if (tok == ',') | |
413 | - next(); | |
414 | - l = l + 4; | |
415 | - } | |
416 | - *(int *)a = l; | |
417 | - next(); | |
418 | - if (!n) { | |
419 | - /* forward reference */ | |
420 | - t = t + 4; | |
421 | - *(int *)t = psym(0xe8, *(int *)t); | |
422 | - } else if (n == 1) { | |
423 | - oad(0x2494ff, l); /* call *xxx(%esp) */ | |
424 | - l = l + 4; | |
425 | - } else { | |
426 | - oad(0xe8, n - ind - 5); /* call xxx */ | |
427 | - } | |
428 | - if (l) | |
429 | - oad(0xc481, l); /* add $xxx, %esp */ | |
430 | - } | |
431 | -} | |
432 | - | |
433 | -sum(l) | |
434 | -{ | |
435 | - int t, n, a; | |
436 | - | |
437 | - if (l-- == 1) | |
438 | - unary(1); | |
439 | - else { | |
440 | - sum(l); | |
441 | - a = 0; | |
442 | - while (l == tokl) { | |
443 | - n = tok; | |
444 | - t = tokc; | |
445 | - next(); | |
446 | - | |
447 | - if (l > 8) { | |
448 | - a = gtst(t, a); /* && and || output code generation */ | |
449 | - sum(l); | |
450 | - } else { | |
451 | - o(0x50); /* push %eax */ | |
452 | - sum(l); | |
453 | - o(0x59); /* pop %ecx */ | |
454 | - | |
455 | - if (l == 4 | l == 5) { | |
456 | - gcmp(t); | |
457 | - } else { | |
458 | - o(t); | |
459 | - if (n == '%') | |
460 | - o(0x92); /* xchg %edx, %eax */ | |
461 | - } | |
462 | - } | |
463 | - } | |
464 | - /* && and || output code generation */ | |
465 | - if (a && l > 8) { | |
466 | - a = gtst(t, a); | |
467 | - li(t ^ 1); | |
468 | - gjmp(5); /* jmp $ + 5 */ | |
469 | - gsym(a); | |
470 | - li(t); | |
471 | - } | |
472 | - } | |
473 | -} | |
474 | - | |
475 | -expr() | |
476 | -{ | |
477 | - sum(11); | |
478 | -} | |
479 | - | |
480 | - | |
481 | -test_expr() | |
482 | -{ | |
483 | - expr(); | |
484 | - return gtst(0, 0); | |
485 | -} | |
486 | - | |
487 | -block(l) | |
488 | -{ | |
489 | - int a, n, t; | |
490 | - | |
491 | - if (tok == TOK_IF) { | |
492 | - next(); | |
493 | - skip('('); | |
494 | - a = test_expr(); | |
495 | - skip(')'); | |
496 | - block(l); | |
497 | - if (tok == TOK_ELSE) { | |
498 | - next(); | |
499 | - n = gjmp(0); /* jmp */ | |
500 | - gsym(a); | |
501 | - block(l); | |
502 | - gsym(n); /* patch else jmp */ | |
503 | - } else { | |
504 | - gsym(a); /* patch if test */ | |
505 | - } | |
506 | - } else if (tok == TOK_WHILE | tok == TOK_FOR) { | |
507 | - t = tok; | |
508 | - next(); | |
509 | - skip('('); | |
510 | - if (t == TOK_WHILE) { | |
511 | - n = ind; | |
512 | - a = test_expr(); | |
513 | - } else { | |
514 | - if (tok != ';') | |
515 | - expr(); | |
516 | - skip(';'); | |
517 | - n = ind; | |
518 | - a = 0; | |
519 | - if (tok != ';') | |
520 | - a = test_expr(); | |
521 | - skip(';'); | |
522 | - if (tok != ')') { | |
523 | - t = gjmp(0); | |
524 | - expr(); | |
525 | - gjmp(n - ind - 5); | |
526 | - gsym(t); | |
527 | - n = t + 4; | |
528 | - } | |
529 | - } | |
530 | - skip(')'); | |
531 | - block(&a); | |
532 | - gjmp(n - ind - 5); /* jmp */ | |
533 | - gsym(a); | |
534 | - } else if (tok == '{') { | |
535 | - next(); | |
536 | - /* declarations */ | |
537 | - decl(1); | |
538 | - while(tok != '}') | |
539 | - block(l); | |
540 | - next(); | |
541 | - } else { | |
542 | - if (tok == TOK_RETURN) { | |
543 | - next(); | |
544 | - if (tok != ';') | |
545 | - expr(); | |
546 | - rsym = gjmp(rsym); /* jmp */ | |
547 | - } else if (tok == TOK_BREAK) { | |
548 | - next(); | |
549 | - *(int *)l = gjmp(*(int *)l); | |
550 | - } else if (tok != ';') | |
551 | - expr(); | |
552 | - skip(';'); | |
553 | - } | |
554 | -} | |
555 | - | |
556 | -/* 'l' is true if local declarations */ | |
557 | -decl(l) | |
558 | -{ | |
559 | - int a; | |
560 | - | |
561 | - while (tok == TOK_INT | tok != -1 & !l) { | |
562 | - if (tok == TOK_INT) { | |
563 | - next(); | |
564 | - while (tok != ';') { | |
565 | - if (l) { | |
566 | - loc = loc + 4; | |
567 | - *(int *)tok = -loc; | |
568 | - } else { | |
569 | - *(int *)tok = glo; | |
570 | - glo = glo + 4; | |
571 | - } | |
572 | - next(); | |
573 | - if (tok == ',') | |
574 | - next(); | |
575 | - } | |
576 | - skip(';'); | |
577 | - } else { | |
578 | - /* patch forward references (XXX: do not work for function | |
579 | - pointers) */ | |
580 | - gsym(*(int *)(tok + 4)); | |
581 | - /* put function address */ | |
582 | - *(int *)tok = ind; | |
583 | - next(); | |
584 | - skip('('); | |
585 | - a = 8; | |
586 | - while (tok != ')') { | |
587 | - /* read param name and compute offset */ | |
588 | - *(int *)tok = a; | |
589 | - a = a + 4; | |
590 | - next(); | |
591 | - if (tok == ',') | |
592 | - next(); | |
593 | - } | |
594 | - next(); /* skip ')' */ | |
595 | - rsym = loc = 0; | |
596 | - o(0xe58955); /* push %ebp, mov %esp, %ebp */ | |
597 | - a = oad(0xec81, 0); /* sub $xxx, %esp */ | |
598 | - block(0); | |
599 | - gsym(rsym); | |
600 | - o(0xc3c9); /* leave, ret */ | |
601 | - *(int *)a = loc; /* save local variables */ | |
602 | - } | |
603 | - } | |
604 | -} | |
605 | - | |
606 | -main(n, t) | |
607 | -{ | |
608 | - file = stdin; | |
609 | - if (n-- > 1) { | |
610 | - t = t + 4; | |
611 | - file = fopen(*(int *)t, "r"); | |
612 | - } | |
613 | - dstk = strcpy(sym_stk = calloc(1, ALLOC_SIZE), | |
614 | - " int if else while break return for define main ") + TOK_STR_SIZE; | |
615 | - glo = calloc(1, ALLOC_SIZE); | |
616 | - ind = prog = calloc(1, ALLOC_SIZE); | |
617 | - vars = calloc(1, ALLOC_SIZE); | |
618 | - inp(); | |
619 | - next(); | |
620 | - decl(0); | |
621 | -#ifdef TEST | |
622 | - { | |
623 | - FILE *f; | |
624 | - f = fopen(*(char **)(t + 4), "w"); | |
625 | - fwrite((void *)prog, 1, ind - prog, f); | |
626 | - fclose(f); | |
627 | - return 0; | |
628 | - } | |
629 | -#else | |
630 | - return (*(int (*)())*(int *)(vars + TOK_MAIN)) (n, t); | |
631 | -#endif | |
632 | -} |
@@ -1,2 +1,2 @@ | ||
1 | 1 | #!/bin/sh |
2 | -gcc acc.c -ldl -o tests/acc && tests/acc tests/otcc.c >tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig | |
2 | +gcc acc.c -DTEST -ldl -o tests/acc && tests/acc tests/otcc.c tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig |