1 /*
2 * Copyright (C) 2000-2005 Chris Ross and various contributors
3 * Copyright (C) 1999-2000 Chris Ross
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * o Redistributions of source code must retain the above copyright notice, this
10 * list of conditions and the following disclaimer.
11 * o Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * o Neither the name of the ferite software nor the names of its contributors may
15 * be used to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifdef HAVE_CONFIG_HEADER
32 #include "../config.h"
33 #endif
34
35 #include "ferite.h"
36
ferite_create_op()37 FeriteOp *ferite_create_op()
38 {
39 FeriteOp *ptr;
40
41 FE_ENTER_FUNCTION;
42 ptr = fmalloc( sizeof( FeriteOp ) );
43 ptr->OP_TYPE = F_OP_NOP;
44 ptr->opdata = NULL;
45 ptr->opdataf = NULL;
46 ptr->line = 0;
47 ptr->addr = 0;
48 FE_LEAVE_FUNCTION( ptr );
49 }
50
ferite_create_opcode_list(int size)51 FeriteOpcodeList *ferite_create_opcode_list( int size )
52 {
53 FeriteOpcodeList *ptr;
54
55 FE_ENTER_FUNCTION;
56 ptr = fmalloc( sizeof( FeriteOpcodeList ) );
57 ptr->size = size;
58 ptr->filename = NULL;
59 ptr->current_op_loc = -1;
60 ptr->list = fmalloc( sizeof( FeriteOp * ) * size );
61 ptr->list[0] = NULL;
62 FE_LEAVE_FUNCTION( ptr );
63 }
64
65 /*
66 * This function will grow the oplist if it needs to be grown.
67 */
ferite_oplist_grow(FeriteOpcodeList * oplist)68 void ferite_oplist_grow( FeriteOpcodeList *oplist )
69 {
70 FE_ENTER_FUNCTION;
71 if( !((oplist->current_op_loc+2) < oplist->size) )
72 {
73 /* we have run out of space
74 * - double oplist->size
75 * - realloc */
76 oplist->size *= 2;
77 oplist->list = frealloc( oplist->list, sizeof(FeriteOp *) * oplist->size );
78 oplist->list[oplist->current_op_loc+1] = NULL;
79 }
80 FE_LEAVE_FUNCTION( NOWT );
81 }
82
ferite_get_next_op(FeriteOpcodeList * oplist)83 FeriteOp *ferite_get_next_op( FeriteOpcodeList *oplist )
84 {
85 FE_ENTER_FUNCTION;
86 /* We need room for the current op and the next op to be NULL */
87 ferite_oplist_grow( oplist );
88
89 oplist->current_op_loc++;
90 if( oplist->list[oplist->current_op_loc] == NULL )
91 oplist->list[oplist->current_op_loc] = ferite_create_op();
92 /* oplist->current_op = oplist->list[oplist->current_op_loc];*/
93 if(oplist->current_op_loc < oplist->size - 1)
94 oplist->list[oplist->current_op_loc + 1] = NULL;
95 FE_LEAVE_FUNCTION( oplist->list[oplist->current_op_loc] );
96 }
97
ferite_current_op(FeriteOpcodeList * oplist)98 FeriteOp *ferite_current_op( FeriteOpcodeList *oplist )
99 {
100 FE_ENTER_FUNCTION;
101 FE_LEAVE_FUNCTION( oplist->list[oplist->current_op_loc] );
102 }
103
104 /* returns the address of the next operator with out incrmenting the internal
105 * program counter */
ferite_get_next_op_address(FeriteOpcodeList * oplist)106 FeriteOp *ferite_get_next_op_address( FeriteOpcodeList *oplist )
107 {
108 FE_ENTER_FUNCTION;
109 /* We need room for the current op and the next op to be NULL */
110 ferite_oplist_grow( oplist );
111
112 if( oplist->list[oplist->current_op_loc+1] == NULL )
113 oplist->list[oplist->current_op_loc+1] = ferite_create_op();
114 oplist->list[oplist->current_op_loc + 2] = NULL;
115 FE_LEAVE_FUNCTION( oplist->list[oplist->current_op_loc+1] );
116 }
117
118 /* returns the index of the next operator with out incrmenting the internal
119 * program counter */
ferite_get_next_op_loc(FeriteOpcodeList * oplist)120 int ferite_get_next_op_loc( FeriteOpcodeList *oplist )
121 {
122 FE_ENTER_FUNCTION;
123 /* We need room for the current op and the next op to be NULL */
124 ferite_oplist_grow( oplist );
125
126 if( oplist->list[oplist->current_op_loc+1] == NULL )
127 oplist->list[oplist->current_op_loc+1] = ferite_create_op();
128 oplist->list[oplist->current_op_loc + 2] = NULL;
129 FE_LEAVE_FUNCTION( oplist->current_op_loc+1 );
130 }
131
ferite_delete_opcode_list(FeriteScript * script,FeriteOpcodeList * oplist)132 void ferite_delete_opcode_list( FeriteScript *script, FeriteOpcodeList *oplist )
133 {
134 int i = 0, currentVar = 0, canFree = 0;
135 FeriteVariable *ptr;
136 void **freed_variables = fcalloc( sizeof(void *) * oplist->size, sizeof(char) );
137
138 /* we only free instructions and compiled in constants - eg strings and stuff */
139 FE_ENTER_FUNCTION;
140 if( oplist->filename != NULL )
141 ffree( oplist->filename );
142
143 for( i = 0; i <= oplist->current_op_loc; i++ )
144 {
145 FUD(("Freeing instruction: %d\n", i ));
146 switch( oplist->list[i]->OP_TYPE )
147 {
148 case F_OP_PUSH:
149 ptr = (FeriteVariable *)(oplist->list[i]->opdata);
150 if( ptr != NULL )
151 {
152 currentVar = 0;
153 canFree = 1;
154 while( freed_variables[currentVar] != NULL )
155 {
156 if( ptr == freed_variables[currentVar] )
157 {
158 canFree = 0;
159 break;
160 }
161 currentVar++;
162 }
163 if( FE_VAR_IS_COMPILED( ptr ) && canFree )
164 {
165 ferite_variable_destroy( script, ptr );
166 freed_variables[currentVar] = ptr;
167 }
168 else
169 {
170 printf( "CAN'T FREE DUPLICATE REFERENCE\n" );
171 }
172 }
173 ffree( oplist->list[i] );
174 break;
175 case F_OP_PUSHINDEX:
176 case F_OP_JMP:
177 case F_OP_BNE:
178 case F_OP_BIE:
179 case F_OP_ERR:
180 case F_OP_POP:
181 case F_OP_NOP:
182 case F_OP_EXIT:
183 case F_OP_UNARY:
184 case F_OP_BINARY:
185 case F_OP_NEWOBJ:
186 if( oplist->list[i]->opdataf != NULL )
187 ffree( oplist->list[i]->opdataf );
188 ffree( oplist->list[i] );
189 break;
190 case F_OP_FUNCTION:
191 case F_OP_METHOD:
192 case F_OP_PUSHVAR:
193 case F_OP_PUSHATTR:
194 case F_OP_MANY:
195 case F_OP_DELIVER:
196 if( oplist->list[i]->opdataf != NULL )
197 ffree( oplist->list[i]->opdataf );
198 if( oplist->list[i]->opdata != NULL )
199 ffree( oplist->list[i]->opdata );
200 ffree( oplist->list[i] );
201 break;
202
203 default:
204 ffree( oplist->list[i] );
205 }
206 }
207 ffree( oplist->list );
208 ffree( oplist );
209 ffree( freed_variables );
210 FE_LEAVE_FUNCTION( NOWT );
211 }
212
213 extern FeriteOpTable ferite_op_table[];
214
ferite_opcode_dump(FeriteOpcodeList * oplist)215 void ferite_opcode_dump( FeriteOpcodeList *oplist )
216 {
217 int i = 0;
218
219 FE_ENTER_FUNCTION;
220 printf( "Current Op Location: %ld\n", oplist->current_op_loc );
221 printf( "Offset\t Address\n" );
222 for( i = 0; i <= oplist->current_op_loc; i++ )
223 {
224 switch( oplist->list[i]->OP_TYPE )
225 {
226 case F_OP_PUSH:
227 printf( "[%d]\t [%p] PUSH %s\n", i, (void *)(oplist->list[i]), ((FeriteVariable *)oplist->list[i]->opdata)->name );
228 break;
229 case F_OP_POP:
230 printf( "[%d]\t [%p] POP\n", i, (void *)(oplist->list[i]) );
231 break;
232 case F_OP_NOP:
233 printf( "[%d]\t [%p] NOP\n", i, (void *)(oplist->list[i]) );
234 break;
235 case F_OP_UNARY:
236 printf( "[%d]\t [%p] UNARYOP %s\n", i, (void *)(oplist->list[i]), ferite_op_table[oplist->list[i]->addr].name );
237 break;
238 case F_OP_BINARY:
239 printf( "[%d]\t [%p] BINARYOP %s\n", i, (void *)(oplist->list[i]), ferite_op_table[oplist->list[i]->addr].name );
240 break;
241 case F_OP_MANY:
242 printf( "[%d]\t [%p] MANYOP %s\n", i, (void *)(oplist->list[i]), ferite_op_table[oplist->list[i]->addr].name );
243 break;
244 case F_OP_FUNCTION:
245 printf( "[%d]\t [%p] FUNCTION %s\n", i, (void *)(oplist->list[i]), (char *)oplist->list[i]->opdata );
246 break;
247 case F_OP_METHOD:
248 printf( "[%d]\t [%p] METHOD %s\n", i, (void *)(oplist->list[i]), (char *)oplist->list[i]->opdata );
249 break;
250 case F_OP_JMP:
251 printf( "[%d]\t [%p] JMP %ld\n", i, (void *)(oplist->list[i]), oplist->list[i]->addr );
252 break;
253 case F_OP_BNE:
254 printf( "[%d]\t [%p] BNE %ld\n", i, (void *)(oplist->list[i]), oplist->list[i]->addr );
255 break;
256 case F_OP_BIE:
257 printf( "[%d]\t [%p] BIE %ld\n", i, (void *)(oplist->list[i]), oplist->list[i]->addr );
258 break;
259 case F_OP_EXIT:
260 printf( "[%d]\t [%p] EXIT\n", i, (void *)(oplist->list[i]) );
261 break;
262 case F_OP_NEWOBJ:
263 printf( "[%d]\t [%p] NEWOBJ\n", i, (void *)(oplist->list[i]) );
264 break;
265 case F_OP_PUSHATTR:
266 printf( "[%d]\t [%p] PUSHATTR %s(%p)\n", i, (void *)(oplist->list[i]), (char *)oplist->list[i]->opdata, oplist->list[i]->opdata );
267 break;
268 case F_OP_PUSHVAR:
269 printf( "[%d]\t [%p] PUSHVAR %s(%p)\n", i, (void *)(oplist->list[i]), (char *)oplist->list[i]->opdata, oplist->list[i]->opdata );
270 break;
271 case F_OP_PUSHINDEX:
272 printf( "[%d]\t [%p] PUSHINDEX %ld\n", i, (void *)(oplist->list[i]), oplist->list[i]->addr );
273 break;
274 case F_OP_ERR:
275 printf( "[%d]\t [%p] ERR %ld\n", i, (void *)(oplist->list[i]), oplist->list[i]->addr );
276 break;
277 case F_OP_CASE:
278 printf( "[%d]\t [%p] CASE\n", i, (void *)(oplist->list[i]) );
279 break;
280 default:
281 printf( "[%d]\t [%p] UKNOWNOP(%d)\n", i, (void *)(oplist->list[i]), oplist->list[i]->OP_TYPE );
282 }
283 }
284 FE_LEAVE_FUNCTION( NOWT );
285 }
286
ferite_opcode_dup(FeriteScript * script,FeriteOpcodeList * oplist)287 FeriteOpcodeList *ferite_opcode_dup( FeriteScript *script, FeriteOpcodeList *oplist )
288 {
289 int i = 0, *value = NULL, v;
290 FeriteVariable *var = NULL;
291 FeriteOpcodeList *ptr = NULL;
292
293 FE_ENTER_FUNCTION;
294
295 if( oplist != NULL )
296 {
297 ptr = fmalloc( sizeof( FeriteOpcodeList ) );
298 ptr->size = oplist->size;
299 if( oplist->filename != NULL )
300 ptr->filename = fstrdup( oplist->filename );
301 ptr->current_op_loc = oplist->current_op_loc;
302 ptr->list = fcalloc( sizeof( FeriteOp * ) * ptr->size, sizeof(FeriteOp *) );
303
304 for( i = 0; i <= oplist->current_op_loc; i++ )
305 {
306 ptr->list[i] = fmalloc( sizeof( FeriteOp ) );
307 ptr->list[i]->OP_TYPE = oplist->list[i]->OP_TYPE;
308 ptr->list[i]->line = oplist->list[i]->line;
309 ptr->list[i]->addr = oplist->list[i]->addr;
310 if( oplist->list[i]->opdataf != NULL )
311 {
312 ptr->list[i]->opdataf = fmalloc( sizeof( FeriteOpFncData ) );
313 ptr->list[i]->opdataf->argument_count = oplist->list[i]->opdataf->argument_count;
314 ptr->list[i]->opdataf->is_autoload = 0;
315 ptr->list[i]->opdataf->function = NULL;
316 }
317 else
318 ptr->list[i]->opdataf = NULL;
319
320 switch( oplist->list[i]->OP_TYPE )
321 {
322 case F_OP_PUSH:
323 var = (FeriteVariable *)(oplist->list[i]->opdata);
324 if( var != NULL )
325 {
326 ptr->list[i]->opdata = ferite_duplicate_variable( script, var, NULL );
327 if( FE_VAR_IS_COMPILED( var ) )
328 MARK_VARIABLE_AS_COMPILED( ((FeriteVariable*)ptr->list[i]->opdata) );
329 }
330 break;
331 case F_OP_FUNCTION:
332 case F_OP_METHOD:
333 case F_OP_PUSHVAR:
334 ptr->list[i]->opdata = fstrdup( oplist->list[i]->opdata );
335 break;
336 case F_OP_MANY:
337 value = (int *)(oplist->list[i]->opdata);
338 v = *value;
339 value = fmalloc( sizeof(int) );
340 *value = v;
341 ptr->list[i]->opdata = value;
342 break;
343 }
344 }
345 }
346 FE_LEAVE_FUNCTION(ptr);
347 }
348