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