1 /******************************************************************************
2 *
3 * Copyright (C) 2006, The Gentee Group. All rights reserved.
4 * This file is part of the Gentee open source project - http://www.gentee.com.
5 *
6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
8 * ACCEPTANCE OF THE AGREEMENT.
9 *
10 * ID: vmload 28.12.06 0.0.A.
11 *
12 * Author: Alexey Krivonogov ( gentee )
13 *
14 * Summary:
15 *
16 ******************************************************************************/
17
18 #include "types.h"
19 #include "common.h"
20 #include "vm.h"
21 #include "gefile.h"
22 #include "bytecode.h"
23
24
25 /*-----------------------------------------------------------------------------
26 *
27 * ID: load_bwd 26.12.06 0.0.A.
28 *
29 * Summary: Unpacking bwd number.
30 * byte < 188 returns byte
31 * byte from 188 to 253 returns 256 * ( byte - 188 ) + [ byte + 1 ]
32 * byte == 254 returns next ushort
33 * byte == 255 returns next uint
34 *
35 -----------------------------------------------------------------------------*/
36
37 uint STDCALL load_bwd( pvmEngine pThis, pubyte * ptr )
38 {
39 uint ret;
40 pubyte cur = *ptr;
41
42 if ( pThis->_vm.ipack )
43 {
44 ret = *cur++;
45 if ( ret > 187 )
46 if ( ret == MAX_BYTE - 1 )
47 {
48 ret = *( pushort )cur;
49 cur += 2; // пропускаем word
50 }
51 else
52 if ( ret == MAX_BYTE )
53 {
54 ret = *( puint )cur;
55 cur += 4; // пропускаем dword
56 }
57 else
58 ret = 0xFF * ( ret - 188 ) + *cur++;
59 }
60 else
61 {
62 ret = *( puint )cur;
63 cur += sizeof( uint );
64 }
65 *ptr = cur;
66 return ret;
67 }
68
69 /*-----------------------------------------------------------------------------
70 *
71 * ID: load_convert 26.12.06 0.0.A.
72 *
73 * Summary: Unpacking bwd number and convert.
74 *
75 -----------------------------------------------------------------------------*/
76
77 uint STDCALL load_convert( pvmEngine pThis, pubyte * ptr )
78 {
79 uint ret = load_bwd( pThis, ptr );
80
81 if ( ret >= KERNEL_COUNT )
82 ret += pThis->_vm.icnv;
83
84 return ret;
85 }
86
87 /*-----------------------------------------------------------------------------
88 *
89 * ID: load_addobj 19.10.06 0.0.A.
90 *
91 * Summary: Add an object to VM.
92 *
93 -----------------------------------------------------------------------------*/
94
95 pvmobj STDCALL load_addobj( pvmEngine pThis, uint over )
96 {
97 pvmobj obj, pover = NULL;
98 pvmfunc curobj = NULL;
99 uint idname = 0; // previous object
100 phashitem phi = NULL;
101 puint pidphi;
102
103 obj = ( pvmobj )pThis->_vm.pmng->top;
104
105 if ( obj->name && *obj->name )
106 { // Looking for an existing object with the same name
107 // and adding name if it is required
108 phi = hash_create( pThis, &pThis->_vm.objname, obj->name );
109 pidphi = ( puint )( phi + 1 );
110
111 if ( pThis->_vm.loadmode && ( idname = *pidphi)) // Object has already existed
112 {
113 uint curcount, objcount, i;
114
115 if ( !( obj->flag & GHRT_MAYCALL ))
116 goto error;
117
118 objcount = (( pvmfunc )obj)->parcount - ( obj->flag & GHBC_RESULT ? 1 : 0 );
119 while ( idname )
120 {
121 curobj = ( pvmfunc )PCMD( idname );
122 if ( !( curobj->vmo.flag & GHRT_MAYCALL ))
123 goto error;
124 // Compare parameters
125 curcount = curobj->parcount - ( curobj->vmo.flag & GHBC_RESULT ? 1 : 0 );
126
127 if ( curcount == objcount )
128 {
129 for ( i = 0; i < curcount; i++ )
130 {
131 if ( curobj->params[ i ].type !=
132 (( pvmfunc )obj )->params[ i ].type )
133 break;
134 }
135 if ( i == curcount ) // There is the same function
136 {
137 // Уходит впустую - реально не добавляем если у нас
138 // предварительное описание функции
139 if ( pThis->_vm.loadmode == VMLOAD_EXTERN )
140 return ( pvmobj )curobj;
141 // Байт код для данной функции уже есть - ошибка
142 if ( curobj->func )
143 goto error;
144 // idname == the found object
145 // over = idname;
146 break;
147 }
148 }
149 idname = curobj->vmo.nextname;
150 }
151 }
152 }
153 // Object not found
154 if ( !idname && !over )
155 {
156 arr_appendnum( pThis, &pThis->_vm.objtbl, ( uint )obj );
157 obj->id = pThis->_vm.count++;
158 over = obj->id;
159 }
160 else
161 {
162 if ( !over )
163 over = idname;
164
165 pover = ( pvmobj )PCMD( over );
166 obj->id = over;
167 arr_setuint( pThis, &pThis->_vm.objtbl, over, ( uint )obj );
168 }
169 if ( phi )
170 {
171 if ( pover && pover->nextname )
172 obj->nextname = pover->nextname;
173 else
174 if (( obj->id != *pidphi && obj->id < KERNEL_COUNT ) ||
175 obj->id > *pidphi )//( obj->id != *pidphi ) // fix: От зацикливания
176 {
177 obj->nextname = ( ushort )*pidphi;
178 *pidphi = obj->id;
179 }
180 }
181
182 // Checking @init @delete @array @oftype =%{}
183 if ( obj->flag & GHRT_MAYCALL && obj->name )
184 {
185 uint ftype;
186 uint flag = 0;
187
188 pvmfunc pfunc = ( pvmfunc )obj;
189
190 if ( obj->flag & GHBC_METHOD )
191 {
192 if ( pfunc->parcount == 1 && !mem_cmp( pThis, obj->name, "@init", 6 ))
193 {
194 flag = GHTY_INITDEL;
195 ftype = FTYPE_INIT;
196 }
197 if ( pfunc->parcount == 1 && !mem_cmp( pThis, obj->name, "@delete", 8 ))
198 {
199 flag = GHTY_INITDEL;
200 ftype = FTYPE_DELETE;
201 }
202 if ( pfunc->parcount == 2 && !mem_cmp( pThis, obj->name, "@oftype", 8 ))
203 {
204 flag = GHTY_EXTFUNC;
205 ftype = FTYPE_OFTYPE;
206 }
207 // + 1 на главный тип
208 if ( pfunc->parcount > 1 && pfunc->parcount <= MAX_MSR &&
209 !mem_cmp( pThis, obj->name, "@array", 7 ))
210 {
211 ftype = FTYPE_ARRAY + pfunc->parcount - 2;
212 flag = GHTY_ARRAY;
213 }
214 }
215 if ( obj->flag & GHBC_OPERATOR )
216 {
217 if ( pfunc->parcount == 2 && pfunc->params[1].type == TCollection &&
218 mem_cmp( pThis, obj->name, "#=", 4 ))
219 {
220 flag = GHTY_EXTFUNC;
221 ftype = FTYPE_COLLECTION;
222 }
223 }
224 if ( flag )
225 {
226 povmtype ptype = ( povmtype )PCMD( pfunc->params->type );
227 ptype->ftype[ ftype ] = obj->id;
228 ptype->vmo.flag |= flag;
229 }
230 }
231 return obj;
232
233 error:
234 longjmp( pThis->stack_state, -1 );//msg( pThis, MNameexist | MSG_VALSTRERR, obj->name, idname );
235 return NULL;
236 }
237
238 /*-----------------------------------------------------------------------------
239 *
240 * ID: load_common 19.10.06 0.0.A.
241 *
242 * Summary: Common load an object to VM.
243 *
244 -----------------------------------------------------------------------------*/
245
246 pubyte STDCALL load_common( pvmEngine pThis, pubyte input, pubyte* out, uint structsize )
247 {
248 pvmobj obj;
249 ubyte type = *input++;
250 uint flag = *( puint )input & 0x20FFFFFF; // ??? GHRT_ to zero
251 // except GHRT_PRIVATE
252 uint len;
253
254 input += sizeof( uint );
255
256 pThis->_vm.ipack = flag & GHCOM_PACK ? 1 : 0;
257
258 pThis->_vm.isize = load_bwd( pThis, &input );
259
260 obj = ( pvmobj )vmmng_begin( pThis, ( pThis->_vm.ipack ? 2 : 1 ) * pThis->_vm.isize );
261 mem_zero( pThis, obj, structsize );
262
263 obj->type = type;
264 obj->flag = flag;
265 *out = ( pubyte )obj + structsize;
266
267 if ( flag & GHCOM_NAME )
268 {
269 // считываем опционально имя
270 len = mem_copyuntilzero( pThis, *out, input );
271 obj->name = *out;
272
273 input += len;
274 *out += len;
275 }
276
277 return input;
278 }
279
280 /*-----------------------------------------------------------------------------
281 *
282 * ID: load_var 19.10.06 0.0.A.
283 *
284 * Summary: Load subtypes or variable
285 *
286 -----------------------------------------------------------------------------*/
287
288 pvartype STDCALL load_var( pvmEngine pThis, pubyte* input, pubyte* output, uint count,
289 puint size, uint align )
290 {
291 pvartype psub;
292 povmtype newtype;
293 pubyte out = *output;
294 pubyte ptr = *input;
295 pvartype ret;
296 uint i, off = 0, flag, len, k;
297
298 ret = psub = ( pvartype )out;
299
300 out += count * sizeof( vartype );
301 for ( i = 0; i < count; i++ )
302 {
303 mem_zero( pThis, psub, sizeof( vartype ));
304
305 psub->type = load_convert( pThis, &ptr );
306 psub->off = align ? ( off >> 2 ) : off;
307 flag = *ptr++;
308 psub->flag = ( ubyte )flag;
309
310 if ( flag & VAR_NAME )
311 {
312 len = mem_copyuntilzero( pThis, out, ptr );
313 psub->name = out;
314 ptr += len;
315 out += len;
316 }
317 newtype = ( povmtype )PCMD( psub->type );
318 off += flag & VAR_PARAM ? ( newtype->stsize << 2 ) : newtype->size;
319
320 if ( flag & VAR_OFTYPE )
321 psub->oftype = load_convert( pThis, &ptr );
322
323 psub->ptr = ( puint )out;
324
325 if ( flag & VAR_DIM )
326 {
327 len = 1;
328 psub->dim = *ptr++;
329
330 for ( k = 0; k < psub->dim; k++ )
331 {
332 *( puint )out = load_bwd( pThis, &ptr );
333 len *= *( puint )out;
334 out += sizeof( uint );
335 }
336 // Если reserved < 4 удаляем лишнее
337 if ( psub->type == TReserved )
338 off += len - 4;
339 }
340 if ( flag & VAR_DATA )
341 {
342 psub->data = 1;
343 if ( newtype->vmo.flag & GHTY_STACK )
344 len = newtype->size;
345 else
346 {
347 if ( psub->type == TStr )
348 {
349 len = mem_len( pThis, ptr ) + 1;
350 }
351 else
352 {
353 *( puint )out = load_bwd( pThis, &ptr );
354 len = *( puint )out;
355 out += sizeof( uint );
356 }
357 }
358 mem_copy( pThis, out, ptr, len );
359 ptr += len;
360 out += len;
361 }
362 // Alignment
363 if ( align && ( off & 3 ))
364 off += 4 - ( off & 0x3 );
365 psub++;
366 }
367 *size = off;
368
369 *output = out;
370 *input = ptr;
371 return ret;
372 }
373
374 /*-----------------------------------------------------------------------------
375 *
376 * ID: load_stack 26.12.06 0.0.A.
377 *
378 * Summary: Load stack object
379 *
380 -----------------------------------------------------------------------------*/
381
382 pvmobj STDCALL load_stack( pvmEngine pThis, int top, int cmd, void* pseudo )
383 {
384 povmstack pstack = ( povmstack )vmmng_begin( pThis, sizeof( ovmstack ));
385 mem_zero( pThis, pstack, sizeof( ovmstack ));
386
387 pstack->vmf.vmo.type = pseudo ? OVM_PSEUDOCMD : OVM_STACKCMD;
388 pstack->vmf.vmo.flag = GHRT_MAYCALL;
389 pstack->topshift = top;
390 pstack->cmdshift = cmd;
391 pstack->vmf.func = ( pvoid )pseudo;
392 load_addobj( pThis, 0 );
393 vmmng_end( pThis, ( pubyte )( pstack + 1 ));
394
395 return ( pvmobj )pstack;
396 }
397
398 /*-----------------------------------------------------------------------------
399 *
400 * ID: load_type 26.12.06 0.0.A.
401 *
402 * Summary: Load type object
403 *
404 -----------------------------------------------------------------------------*/
405
406 pvmobj STDCALL load_type( pvmEngine pThis, pubyte* input )
407 {
408 povmtype ptype;
409 pubyte out;
410 pubyte ptr = *input;
411
412 ptr = load_common( pThis, ptr, &out, sizeof( ovmtype ) );
413
414 ptype = ( povmtype )pThis->_vm.pmng->top;
415 ptype->size = 4;
416 ptype->stsize = 1;
417 ptype->index.type = 0;//TUint;
418
419 if ( ptype->vmo.flag & GHTY_INHERIT )
420 {
421 ptype->inherit = load_convert( pThis, &ptr );
422 // Наследуем index type от родителя
423 ptype->index.type = (( povmtype )PCMD( ptype->inherit ))->index.type;
424 ptype->index.oftype = (( povmtype )PCMD( ptype->inherit ))->index.oftype;
425 }
426 if ( ptype->vmo.flag & GHTY_INDEX )
427 {
428 ptype->index.type = load_convert( pThis, &ptr );
429 ptype->index.oftype = load_convert( pThis, &ptr );
430 }
431 if ( ptype->vmo.flag & GHTY_INITDEL )
432 {
433 ptype->ftype[ FTYPE_INIT ] = load_convert( pThis, &ptr );
434 ptype->ftype[ FTYPE_DELETE ] = load_convert( pThis, &ptr );
435 }
436 if ( ptype->vmo.flag & GHTY_EXTFUNC )
437 {
438 ptype->ftype[ FTYPE_OFTYPE ] = load_convert( pThis, &ptr );
439 ptype->ftype[ FTYPE_COLLECTION ] = load_convert( pThis, &ptr );
440 }
441 if ( ptype->vmo.flag & GHTY_ARRAY )
442 {
443 uint i, dim = load_convert( pThis, &ptr );
444
445 if ( dim <= MAX_MSR )
446 {
447 for ( i = 0; i < dim; i++ )
448 ptype->ftype[ FTYPE_ARRAY + i ] = load_convert( pThis, &ptr );
449 }
450 else
451 ptype->ftype[ FTYPE_ARRAY ] = dim;
452 }
453 ptype->count = load_bwd( pThis, &ptr );
454 if ( ptype->vmo.flag & GHTY_STACK )
455 {
456 ptype->size = ptype->count;
457 ptype->stsize = ptype->size > sizeof( uint ) ? 2 : 1;
458 ptype->count = 0;
459 }
460 else
461 if ( ptype->count )
462 {
463 ptype->children = load_var( pThis, &ptr, &out, ptype->count, &ptype->size, 0 );
464 }
465
466 load_addobj( pThis, 0 );
467 vmmng_end( pThis, out );
468
469 *input += pThis->_vm.isize;
470 return ( pvmobj )ptype;
471 }
472
473 /*-----------------------------------------------------------------------------
474 *
475 * ID: load_commonfunc 26.12.06 0.0.A.
476 *
477 * Summary: Common Load bytecode or func object
478 *
479 -----------------------------------------------------------------------------*/
480
481 pvmfunc STDCALL load_commonfunc( pvmEngine pThis, pubyte* input, pubyte* out, pubyte* end, puint size )
482 {
483 pvmfunc pfunc;
484 pubyte ptr = *input;
485 uint i;
486
487 // Проверка на повторный вызов
488 ptr = load_common( pThis, ptr, out, *size );
489 *end = *input + pThis->_vm.isize;
490
491 pfunc = ( pvmfunc )pThis->_vm.pmng->top;
492 pfunc->vmo.flag |= GHRT_MAYCALL;
493 pfunc->ret = load_var( pThis, &ptr, out, 1, size, 1 );
494 pfunc->dwret = ( ubyte )(( povmtype )PCMD( pfunc->ret->type ))->stsize;
495 pfunc->parcount = ( ubyte )load_bwd( pThis, &ptr );
496 if ((uint)*out & 3 ) // Alignment
497 *out += 4 - ( (uint)*out & 3 );
498
499 pfunc->params = load_var( pThis, &ptr, out, pfunc->parcount, size, 1 );
500
501 for ( i = 0; i < pfunc->parcount; i++ )
502 {
503 pfunc->parsize += ( ubyte )((povmtype)PCMD( pfunc->params[i].type ))->stsize;//( ubyte )( *size >> 2 );
504 }
505 *input = ptr;
506
507 return pfunc;
508 }
509
510
511 /*-----------------------------------------------------------------------------
512 *
513 * ID: load_bytecode 26.12.06 0.0.A.
514 *
515 * Summary: Load bytecode object
516 *
517 -----------------------------------------------------------------------------*/
518
519 pvmobj STDCALL load_bytecode( pvmEngine pThis, pubyte* input, uint mode )
520 {
521 povmbcode pbcode;
522 pvmobj ret;
523 pubyte out, end;
524 puint bcout;
525 pubyte ptr = *input;
526 uint size = sizeof( ovmbcode );
527 uint i, off, cmd;
528
529 pThis->_vm.loadmode = mode;
530 pbcode = ( povmbcode )load_commonfunc( pThis, &ptr, &out, &end, &size );
531
532 pbcode->setcount = ( ubyte )load_bwd( pThis, &ptr );
533 if ( pbcode->setcount )
534 {
535 pbcode->sets = ( pvarset )out;
536 out += sizeof( varset ) * pbcode->setcount;
537 off = 0;
538 for ( i = 0; i < pbcode->setcount; i++ )
539 {
540 pbcode->sets[i].count = ( ushort )load_bwd( pThis, &ptr );
541 pbcode->sets[i].first = ( ushort )off;
542 off += pbcode->sets[i].count;
543 }
544 pbcode->vars = load_var( pThis, &ptr, &out, off, &size, 1 );
545 pbcode->varsize = size >> 2;
546 off = 0;
547
548 // Sets summary size of block local variables in uints
549 for ( i = 0; i < ( uint )( pbcode->setcount - 1 ); i++ )
550 {
551 pbcode->sets[i].off = off;
552 pbcode->sets[i].size =
553 pbcode->vars[ pbcode->sets[ i + 1 ].first ].off - off;
554 off += pbcode->sets[i].size;
555 }
556 pbcode->sets[ i ].size = pbcode->varsize - off;
557 pbcode->sets[ i ].off = off;
558 }
559 if ( ptr < end || mode == VMLOAD_GE )
560 {
561 // if ((uint)out & 3 )
562 out += 4 - ( (uint)out & 3 ); // Alignment
563 pbcode->vmf.func = out;
564 }
565
566 // Loading byte-code
567 if ( mode == VMLOAD_GE )
568 {
569 bcout = ( puint )out;
570 while ( ptr < end )
571 {
572 cmd = load_convert( pThis, &ptr );
573 *bcout++ = cmd;
574 if ( cmd >= CNop && cmd < CNop + STACK_COUNT )
575 switch ( cmd )
576 {
577 case CQwload:
578 *bcout++ = *( puint )ptr;
579 ptr += sizeof( uint );
580 case CDwload:
581 *bcout++ = *( puint )ptr;
582 ptr += sizeof( uint );
583 break;
584 case CByload:
585 *( bcout - 1 ) = CDwload;
586 *bcout++ = *( pubyte )ptr;
587 ptr += sizeof( ubyte );
588 break;
589 case CShload:
590 *( bcout - 1 ) = CDwload;
591 *bcout++ = *( pushort )ptr;
592 ptr += sizeof( ushort );
593 break;
594 case CDwsload:
595 i = load_bwd( pThis, &ptr );
596 *bcout++ = i;
597 i <<= 2;
598 mem_copy( pThis, bcout, ptr, i );
599 bcout += *( bcout - 1 );
600 ptr += i;
601 break;
602 case CResload:
603 *bcout++ = load_bwd( pThis, &ptr ) + pThis->_vm.irescnv;
604 break;
605 case CCmdload:
606 case CPtrglobal:
607 *bcout++ = load_convert( pThis, &ptr );
608 break;
609 case CDatasize:
610 i = load_bwd( pThis, &ptr );
611 *bcout++ = i;
612 mem_copy( pThis, bcout, ptr, i );
613 bcout += ( i >> 2 ) + ( i & 3 ? 1 : 0 );
614 ptr += i;
615 // Зануляем последние добавочные байты
616 i &= 3;
617 if ( i )
618 {
619 i = 4 - i;
620 mem_zero( pThis, ( pubyte )bcout - i, i );
621 }
622 break;
623 default:
624 switch ( shifts[ cmd - CNop ] )
625 {
626 case SH1_3:
627 case SH2_3:
628 *bcout++ = load_bwd( pThis, &ptr );
629 case SHN1_2:
630 case SH0_2:
631 case SH1_2:
632 *bcout++ = load_bwd( pThis, &ptr );
633 break;
634 }
635 }
636 }
637 // Если у функции в конце нет команды возврата, то добавляем ее
638 if ( *( bcout - 1 ) != CReturn )
639 *bcout++ = CReturn;
640
641 out = ( pubyte )bcout;
642 }
643 else
644 while ( ptr < end )
645 *out++ = *ptr++;
646
647 if ( pbcode->vmf.func )
648 pbcode->bcsize = out - ( pubyte )pbcode->vmf.func;
649 ret = load_addobj( pThis, 0 );
650 if ( ret == ( pvmobj )pbcode )
651 vmmng_end( pThis, out );
652 // Проверка на методы для типов
653
654 *input += pThis->_vm.isize;
655 return ret;
656 }
657
658 /*-----------------------------------------------------------------------------
659 *
660 * ID: load_bytecode 26.12.06 0.0.A.
661 *
662 * Summary: Load bytecode object
663 *
664 -----------------------------------------------------------------------------*/
665
666 pvmobj STDCALL load_exfunc( pvmEngine pThis, pubyte* input, uint over )
667 {
668 povmfunc pfunc;
669 pvmobj pvmo;
670 pubyte out, end;
671 pubyte ptr = *input;
672 uint size = sizeof( ovmfunc );
673 // Проверка на повторный вызов ???
674
675 pThis->_vm.loadmode = VMLOAD_EXTERN;
676
677 pfunc = ( povmfunc )load_commonfunc( pThis, &ptr, &out, &end, &size );
678
679 if ( pfunc->vmf.vmo.name )
680 switch ( pfunc->vmf.vmo.name[0] )
681 {
682 case '@': pfunc->vmf.vmo.flag |= GHBC_METHOD; break;
683 case '#': pfunc->vmf.vmo.flag |= GHBC_OPERATOR; break;
684 }
685 if ( pfunc->vmf.vmo.flag & GHEX_IMPORT )
686 {
687 pfunc->import = load_convert( pThis, &ptr );
688 pfunc->original = out;
689 size = mem_copyuntilzero( pThis, out, ptr );
690 ptr += size;
691 out += size;
692 }
693 if ( pfunc->vmf.ret->type == TDouble || pfunc->vmf.ret->type == TFloat )
694 pfunc->vmf.vmo.flag |= GHEX_FLOAT;
695 pvmo = load_addobj( pThis, over );
696 if ( ( pvmobj )pfunc == pvmo )
697 vmmng_end( pThis, out );
698 // // Проверка на методы для типов
699 *input += pThis->_vm.isize;
700
701 return pvmo;
702 }
703
704 /*-----------------------------------------------------------------------------
705 *
706 * ID: load_define 26.12.06 0.0.A.
707 *
708 * Summary: Load define object
709 *
710 -----------------------------------------------------------------------------*/
711
712 pvmobj STDCALL load_define( pvmEngine pThis, pubyte* input )
713 {
714 // Добавляем объект
715 povmdefine pdefine;
716 pubyte out;
717 uint size;
718 pubyte ptr = *input;
719
720 ptr = load_common( pThis, ptr, &out, sizeof( ovmdefine ) );
721
722 pdefine = ( povmdefine )pThis->_vm.pmng->top;
723
724 pdefine->count = load_bwd( pThis, &ptr );
725 if ( pdefine->count )
726 {
727 pdefine->macros = load_var( pThis, &ptr, &out, pdefine->count, &size, 0 );
728 }
729
730 load_addobj( pThis, 0 );
731 vmmng_end( pThis, out );
732
733 *input += pThis->_vm.isize;
734 return ( pvmobj )pdefine;
735 }
736
737 /*-----------------------------------------------------------------------------
738 *
739 * ID: load_import 26.12.06 0.0.A.
740 *
741 * Summary: Load import object
742 *
743 -----------------------------------------------------------------------------*/
744
745 pvmobj STDCALL load_import( pvmEngine pThis, pubyte* input )
746 {
747 povmimport pimport;
748 pubyte out;
749 uint len;
750 pubyte ptr = *input;
751
752 ptr = load_common( pThis, ptr, &out, sizeof( ovmimport ) );
753
754 pimport = ( povmimport )pThis->_vm.pmng->top;
755 len = mem_copyuntilzero( pThis, out, ptr );
756 pimport->filename = out;
757 ptr += len;
758 out += len;
759
760 if ( pimport->vmo.flag & GHIMP_LINK )
761 {
762 pimport->size = *( puint )ptr;
763 ptr += sizeof( uint );
764
765 mem_copy( pThis, out, ptr, pimport->size );
766 pimport->data = out;
767 out += pimport->size;
768 }
769
770 load_addobj( pThis, 0 );
771 vmmng_end( pThis, out );
772 *input += pThis->_vm.isize;
773
774 return ( pvmobj )pimport;
775 }
776
777 /*-----------------------------------------------------------------------------
778 *
779 * ID: load_global 26.12.06 0.0.A.
780 *
781 * Summary: Load global variable object
782 *
783 -----------------------------------------------------------------------------*/
784
785 pvmobj STDCALL load_global( pvmEngine pThis, pubyte* input )
786 {
787 povmglobal pglobal;
788 pubyte out;
789 uint size;
790 pubyte ptr = *input;
791
792 ptr = load_common( pThis, ptr, &out, sizeof( ovmglobal ));
793
794 pglobal = ( povmglobal )pThis->_vm.pmng->top;
795 pglobal->type = load_var( pThis, &ptr, &out, 1, &size, 1 );
796 pglobal->pval = out;
797 out += max( sizeof( uint ), (( povmtype )PCMD( pglobal->type->type ))->size );
798 load_addobj( pThis, 0 );
799 vmmng_end( pThis, out );
800 *input += pThis->_vm.isize;
801
802 return ( pvmobj )pglobal;
803 }
804
805 /*-----------------------------------------------------------------------------
806 *
807 * ID: load_alias 26.12.06 0.0.A.
808 *
809 * Summary: Load alias object
810 *
811 -----------------------------------------------------------------------------*/
812
813 pvmobj STDCALL load_alias( pvmEngine pThis, pubyte* input )
814 {
815 povmalias palias;
816 pubyte out;
817 pubyte ptr = *input;
818
819 ptr = load_common( pThis, ptr, &out, sizeof( ovmalias ));
820
821 palias = ( povmalias )pThis->_vm.pmng->top;
822 palias->idlink = load_convert( pThis, &ptr );
823 load_addobj( pThis, 0 );
824 vmmng_end( pThis, out );
825 *input += pThis->_vm.isize;
826
827 return ( pvmobj )palias;
828 }
829
830 //-----------------------------------------------------------------------------
831
832
833 void STDCALL load_none( pvmEngine pThis )
834 {
835 pvmobj pvmo = ( pvmobj )vmmng_begin( pThis, sizeof( vmobj ));
836
837 load_addobj( pThis, 0 );
838 vmmng_end( pThis, ( pubyte )( pvmo + 1 ));
839 }
840
841 void STDCALL load_resource( pvmEngine pThis, pubyte* in )
842 {
843 uint count, i, type;
844
845 *in += 5;
846 count = load_bwd( pThis, in ); // skip size
847 count = load_bwd( pThis, in );
848 pThis->_vm.irescnv = collect_count( pThis, &pThis->_vm.resource );
849
850 for ( i = 0; i < count; i ++ )
851 {
852 type = load_convert( pThis, in );
853 if ( type == TStr )
854 {
855 vmres_addstr( pThis, *in );
856 // print("OK=%s %i\n", *in, _vm.rescnv[ i ] );
857 *in += mem_len( pThis, *in ) + 1;
858 }
859 }
860 }
861
862
863 uint STDCALL ge_load( pvmEngine pThis, char* fileName )
864 {
865 pubyte cur, end, ptemp;
866 uint size;
867 buf bcode;
868 str filename;
869 pgehead phead;
870
871 if ( setjmp( pThis->stack_state) == -1 )
872 return 0xFFFFFFFF;
873
874 buf_init( pThis, &bcode );
875 str_init( pThis, &filename );
876 str_copyzero( pThis, &filename, fileName );
877 file2buf( pThis, &filename, &bcode, 0 );
878 str_delete( pThis, &filename );
879 phead = ( pgehead )buf_ptr( pThis, &bcode );
880
881 // Проверка заголовка и целостности
882 // Сравниваем с 'GE' с двумя нулями на конце
883
884 if ( *( puint )phead != GE_STRING )//0x00004547 )
885 longjmp( pThis->stack_state, -1 );//msg( pThis, MNotGE | MSG_EXIT );
886 if ( phead->crc != crc( pThis, ( pubyte )phead + 12, phead->size - 12, 0xFFFFFFFF ))
887 longjmp( pThis->stack_state, -1 );//msg( pThis, MCrcGE | MSG_EXIT );
888 if ( phead->vermajor != GEVER_MAJOR || phead->verminor > GEVER_MINOR )
889 longjmp( pThis->stack_state, -1 );//msg( pThis, MVerGE | MSG_EXIT );
890
891 pThis->_vm.loadmode = VMLOAD_GE;
892 pThis->_vm.icnv = arr_count( pThis, &pThis->_vm.objtbl ) - KERNEL_COUNT;
893 cur = ( pubyte )phead + phead->headsize;
894 end = ( pubyte )phead + phead->size;
895 while ( cur < end )
896 {
897 ptemp = cur + 5; // type + flag
898 pThis->_vm.ipack = ( *( puint )( cur + 1 )) & GHCOM_PACK ? 1 : 0;
899
900 size = load_bwd( pThis, &ptemp );
901 ptemp = cur;
902
903 switch ( *cur )
904 {
905 case OVM_NONE:
906 load_none(pThis);
907 break;
908 case OVM_BYTECODE:
909 load_bytecode( pThis, &cur, VMLOAD_GE );
910 break;
911 case OVM_EXFUNC:
912 load_exfunc( pThis, &cur, 0 );
913 pThis->_vm.loadmode = VMLOAD_GE;
914 break;
915 case OVM_TYPE:
916 load_type( pThis, &cur );
917 break;
918 case OVM_GLOBAL:
919 load_global( pThis, &cur );
920 break;
921 case OVM_DEFINE:
922 load_define( pThis, &cur );
923 break;
924 case OVM_IMPORT:
925 load_import( pThis, &cur );
926 break;
927 case OVM_RESOURCE:
928 load_resource( pThis, &cur );
929 break;
930 case OVM_ALIAS:
931 load_alias( pThis, &cur );
932 break;
933 default:
934 longjmp( pThis->stack_state, -1 );//msg( pThis, MUnkGE | MSG_DVAL, cur - ( pubyte )phead );
935 }
936 cur = ptemp + size;
937 }
938 pThis->_vm.loadmode = VMLOAD_G;
939 buf_delete( pThis, &bcode );
940 return 1;
941 }
942
943