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: compile 18.10.06 0.0.A.
11 *
12 * Author: Alexey Krivonogov ( gentee )
13 *
14 ******************************************************************************/
15
16 #include "compile.h"
17 #include "../lex/lex.h"
18 #include "../lex/lexgentee.h"
19 #include "../genteeapi/gentee.h"
20 #include "../common/file.h"
21 #include "../common/hash.h"
22 #include "../bytecode/ge.h"
23 #include "lexem.h"
24 #include "operlist.h"
25 #include "define.h"
26 #include "macro.h"
27 #include "compinit.h"
28 #include "include.h"
29 #include "import.h"
30 #include "global.h"
31
32 #include <setjmp.h>
33 jmp_buf stack_state;
34
35 //----------------------------------------------------------------------------
36
37 extern const uint lexgentee[];
38
39 /*-----------------------------------------------------------------------------
40 *
41 * ID: compile_process 23.10.06 0.0.A.
42 *
43 * Summary: The main gentee compile function
44 *
45 -----------------------------------------------------------------------------*/
46
47 uint STDCALL compile_process( pstr filename )
48 {
49 pcompilefile prev;
50 compilefile cmpfile;
51 arr lexout;
52 arr lexems;
53 pstr stemp;
54 pstr dir;
55 pubyte input;
56 plexem plex;
57 pvmobj pvmo;
58 uint i;
59
60 // plexem pil;
61 // ubyte idname[ 32 ]; // delete
62 // pcompile pcmp = _gentee.compile;
63
64 prev = _compile->cur;
65
66 mem_zero( &cmpfile, sizeof( compilefile ));
67 cmpfile.src = str_new( str_ptr( filename ));
68 cmpfile.filename = str_new( 0 );
69
70 dir = str_new( 0 );
71 stemp = str_new( 0 );
72
73 if ( _compile->flag & CMPL_SRC )
74 _compile->flag &= ~CMPL_SRC;
75 else
76 {
77 os_filefullname( filename, cmpfile.filename );
78 if ( hash_find( &_compile->files, str_ptr( cmpfile.filename )))
79 goto end;
80
81 os_dirgetcur( dir );
82 file2buf( filename, cmpfile.src, prev ? prev->pos : 0 );
83 os_filefullname( filename, cmpfile.filename );
84 if ( hash_find( &_compile->files, str_ptr( cmpfile.filename )))
85 goto end;
86
87 hash_create( &_compile->files, str_ptr( cmpfile.filename ));
88 // Set a new directory
89 str_getdirfile( filename, stemp, 0 );
90 os_dirsetcur( stemp );
91 }
92
93 _compile->cur = &cmpfile;
94 _compile->cur->idfirst = _vm.count;
95
96 // print("First=%i\n", _compile->cur->idfirst );
97 if ( *( puint )str_ptr( cmpfile.src ) == GE_STRING )
98 {
99 msg( MLoad | MSG_STR, cmpfile.filename );
100 // Загружаем байт-код из откомпилированного файла
101 ge_load( cmpfile.src );
102 // ??? Обнуление смещения vm->curoff проиcходит в конце gentee_load
103 goto end;
104 }
105 msg( MLoad | MSG_STR, cmpfile.filename );
106 _compile->flag &= ~CMPL_LINE;
107
108 // Adding zero character
109 buf_appendch( cmpfile.src, 0 );
110
111 input = str_ptr( cmpfile.src );
112 // Ignoring all first strings beginning with #
113 while ( input[ cmpfile.off ] == '#' )
114 {
115 while ( input[ cmpfile.off ] && input[ cmpfile.off ] != 0xA )
116 cmpfile.off++;
117 if ( input[ cmpfile.off ] == 0xA )
118 cmpfile.off++;
119 }
120 input += cmpfile.off;
121 // The first pass
122 arr_init( &lexout, sizeof( lexitem ));
123
124 gentee_lexptr( input, &_compile->ilex, &lexout );
125
126 _compile->cur->lexems = &lexems;
127 // The second pass and generating an array of lexems
128 lexem_load( &lexems, &lexout );
129
130 /* for ( i = 0; i < arr_count( &lexems ); i++ )
131 {
132 pil = ( plexem )arr_ptr( &lexems, i );
133 printf("Type = %i pos = %i ", pil->type, pil->pos );
134 switch ( pil->type )
135 {
136 case LEXEM_BINARY:
137 printf( "binary= %s", str_ptr( lexem_getstr( pil )));
138 break;
139 case LEXEM_FILENAME:
140 printf( "filename= %s", str_ptr( lexem_getstr( pil )));
141 break;
142 case LEXEM_STRING:
143 printf( "string= %s len = %i", str_ptr( lexem_getstr( pil )),
144 str_len( lexem_getstr( pil )));
145 break;
146 case LEXEM_MACRO:
147 printf( "macro= %s", hash_name( &_compile->names, pil->macroid ));
148 break;
149 case LEXEM_NAME:
150 printf( "name= %s", hash_name( &_compile->names, pil->nameid ));
151 break;
152 case LEXEM_KEYWORD:
153 printf( "keyword = %i", pil->key );
154 break;
155 case LEXEM_OPER:
156 printf( "oper= %s id=%i", &pil->oper.name, pil->oper.operid );
157 break;
158 case LEXEM_NUMBER:
159 printf( "number = " );
160 switch ( pil->num.type )
161 {
162 case TUint:
163 printf( "+%lu", pil->num.vint );
164 break;
165 case TInt:
166 printf( "%i", pil->num.vint );
167 break;
168 case TUlong:
169 printf( "+%sL", _ui64toa( pil->num.vlong, &idname, 10 ));
170 break;
171 case TLong:
172 printf( "%sL", _i64toa( pil->num.vlong, &idname, 10 ));
173 break;
174 case TFloat:
175 printf( "F%e", pil->num.vfloat );
176 break;
177 case TDouble:
178 printf( "D%e", pil->num.vdouble );
179 break;
180 }
181 break;
182 }
183 printf("\n" );
184 }
185 */
186 plex = 0;
187 // print("Before "); memstat();
188 while ( plex = lexem_next( plex, LEXNEXT_NULL | LEXNEXT_IGNLINE ))
189 {
190 if ( plex->type == LEXEM_KEYWORD )
191 {
192 switch ( plex->key ) {
193 case KEY_DEFINE:
194 plex = define( plex );
195 break;
196 case KEY_GLOBAL:
197 plex = global( plex );
198 break;
199 // case KEY_IFDEF: // check in lexem_next
200 // break;
201 case KEY_IMPORT:
202 plex = import( plex );
203 break;
204 case KEY_INCLUDE:
205 plex = include( plex );
206 break;
207 case KEY_TYPE:
208 plex = type( plex );
209 break;
210 case KEY_OPERATOR:
211 case KEY_METHOD:
212 case KEY_FUNC:
213 case KEY_TEXT:
214 case KEY_PROPERTY:
215 plex = m_func( plex, 0 );
216 break;
217 case KEY_PRIVATE:
218 _compile->cur->priv = 1;
219 break;
220 case KEY_PUBLIC:
221 _compile->cur->priv = 0;
222 break;
223 case KEY_EXTERN:
224 plex = m_extern( plex );
225 break;
226 default:
227 msg( MUnkcmd | MSG_LEXNAMEERR, plex );
228 break;
229 }
230 }
231 else
232 msg( MUnkcmd | MSG_LEXNAMEERR, plex );
233 }
234 // Proceed private public protected
235 for ( i = _compile->cur->idfirst; i < _vm.count; i++ )
236 {
237 pvmo = ( pvmobj )PCMD( i );
238 if ( pvmo->flag & GHRT_INCLUDED )
239 continue;
240 if ( pvmo->type == OVM_TYPE && pvmo->flag & GHTY_PROTECTED )
241 type_protect( ( povmtype )pvmo );
242 if ( pvmo->flag & GHRT_PRIVATE )
243 vm_clearname( i );
244 // Надо добавить для глобальных переменных !!! ???
245
246 pvmo->flag |= GHRT_INCLUDED;
247 }
248
249 lexem_delete( &lexems );
250 arr_delete( &lexout );
251 end:
252
253 if ( str_len( dir ))
254 os_dirsetcur( dir );
255 str_destroy( cmpfile.src );
256 str_destroy( cmpfile.filename );
257 str_destroy( dir );
258 str_destroy( stemp );
259 _compile->cur = prev;
260
261 return 1;
262 }
263
264 /*-----------------------------------------------------------------------------
265 *
266 * ID: gentee_compile 23.10.06 0.0.A.
267 *
268 * Summary: The public compile function
269 *
270 -----------------------------------------------------------------------------*/
271 //uint STDCALL gentee_compile( pcompileinfo compinit )
272 uint STDCALL thread_compile( pcompileinfo compinit )
273 {
274 compile icompile;
275 pstr data;//, src;
276 uint i;
277 pubyte ptr;
278 buf stack;
279 // pstr src;
280
281 if ( setjmp( stack_state ) == -1 )
282 return FALSE;
283
284 // if ( !getenv("GNUMSIGN") )
285 msg( MStart );
286 // else
287 // _time = os_time();
288
289 initcompile();
290 // memstat();
291 _vm.loadmode = 1;
292 mem_zero( &icompile, sizeof( compile ));
293 _compile = &icompile;
294
295 if ( compinit->flag & CMPL_OPTIMIZE )
296 _compile->popti = &compinit->opti;
297
298 icompile.flag = compinit->flag;
299 data = str_new( compinit->input );
300 buf_init( &stack );
301 buf_reserve( &stack, (( STACK_OPERS + STACK_OPS ) << 1 ) + STACK_PARS );//0xFFFF << 1 );
302
303 arrdata_strload( arrdata_init( &icompile.libdirs ), compinit->libdirs );
304 hash_init( &icompile.files, sizeof( uint ));
305 hash_init( &icompile.names, sizeof( uint ));
306 hash_init( &icompile.resource, sizeof( uint ));
307 hash_init( &icompile.opers, sizeof( uint ));
308 hash_init( &icompile.macros, sizeof( macro ));
309 hash_init( &icompile.namedef, sizeof( macro ));
310
311 arrdata_init( &icompile.string );
312 arrdata_init( &icompile.binary );
313 icompile.files.ignore = 1;
314 lex_init( &icompile.ilex, ( puint )&lexgentee );
315 icompile.stkopers = buf_ptr( &stack );
316 icompile.stkops = ( pubyte )icompile.stkopers + STACK_OPERS;//0xFFFF;
317 icompile.stkpars = ( pubyte )icompile.stkops + STACK_OPS;//0xFFFF;
318 icompile.stkmopers = ( pubyte )icompile.stkpars + STACK_PARS;//0xFFFF;
319 icompile.stkmops = ( pubyte )icompile.stkmopers + STACK_OPERS;//0xFFFF;
320 ptr = ( pubyte )&operlexlist;
321 // Loading hash of operators
322 for ( i = 0; i < OPERCOUNT; i++ )
323 {
324 if ( *ptr )
325 {
326 hash_setuint( &icompile.opers, ptr, i );
327 ptr += mem_len( ptr );
328 }
329 ptr++;
330 }
331 macro_init();
332
333 /*#ifndef LINUX
334 src = str_new( 0 );
335 if ( icompile.flag & CMPL_SRC )
336 str_copy( src, data );
337 else
338 file2buf( data, src, 0 );
339
340 // print( "CMD LINE=%s\n",str_ptr( cmpfile.src ) );
341 // getch();
342 if ( *( pushort )str_ptr( src ) == 0x2123 &&
343 _compile->flag & CMPL_LINE && !getenv("GNUMSIGN"))
344 {
345 ubyte cmdline[512];
346 pubyte cur;
347 pubyte input = str_ptr( src ) + 2;
348 PROCESS_INFORMATION stpi;
349 STARTUPINFO start;
350
351 ZeroMemory( &stpi, sizeof( PROCESS_INFORMATION ));
352 ZeroMemory( &start, sizeof( STARTUPINFO ));
353 start.cb = sizeof( STARTUPINFO );
354
355 cur = ( pubyte )&cmdline;
356 while ( *input >= ' ' )
357 {
358 if ( *input == '%' && *( input + 1 ) == '1' )
359 {
360 mem_copyuntilzero( cur, str_ptr( data ));
361 cur += mem_len( cur );
362 input += 2;
363 }
364 else
365 *cur++ = *input++;
366 }
367 *cur = 0;
368 _putenv("GNUMSIGN=1");
369 // print( "CMD LINE=%s\n",cmdline );
370 CreateProcess( 0, cmdline, 0, 0, TRUE,
371 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
372 0, 0, &start, &stpi );
373 ExitProcess( 0 );
374 }
375 str_destroy( src );
376 #endif*/
377
378 if ( *compinit->defargs || *compinit->include )
379 {
380 pstr stemp = str_new( "" );
381 pstr include = str_new( "" );
382 pstr dargs = str_new( "" );
383 pubyte cur, src;
384
385 str_reserve( stemp, 1024 );
386 str_reserve( include, 1024 );
387 str_reserve( dargs, 1024 );
388
389 if ( *compinit->include )
390 {
391 cur = str_ptr( include );
392 src = compinit->include;
393 while ( *src )
394 {
395 sprintf( cur, "$\"%s\"\r\n", src );
396 cur += mem_len( cur );
397 src += mem_len( src ) + 1;
398 }
399 *cur = 0;
400 str_setlen( include, cur - str_ptr( include ));
401 }
402 if ( *compinit->defargs )
403 {
404 cur = str_ptr( dargs );
405 src = compinit->defargs;
406 while ( *src )
407 {
408 sprintf( cur, "%s\r\n", src );
409 cur += mem_len( cur );
410 src += mem_len( src ) + 1;
411 }
412 *cur = 0;
413 str_setlen( dargs, cur - str_ptr( dargs ));
414 }
415 str_printf( stemp, "define {\r\n\
416 %s\r\n\
417 }\r\n\
418 include {\r\n\
419 %s\r\n\
420 }\r\n\
421 include : $\"%s\"", str_ptr( dargs ), str_ptr( include ), str_ptr( data ));
422 // printf( str_ptr( stemp ));
423 _compile->flag |= CMPL_SRC;
424 str_copy( data, stemp );
425 str_destroy( stemp );
426 str_destroy( include );
427 str_destroy( dargs );
428 }
429 compile_process( data );
430
431 hash_delete( &icompile.files );
432 hash_delete( &icompile.names );
433 hash_delete( &icompile.resource );
434 hash_delete( &icompile.opers );
435 hash_delete( &icompile.macros );
436 hash_delete( &icompile.namedef );
437 arrdata_delete( &icompile.libdirs );
438 arrdata_delete( &icompile.string );
439 arrdata_delete( &icompile.binary );
440
441 lex_delete( &icompile.ilex );
442 msg( MEnd );
443
444 if ( compinit->flag & CMPL_GE )
445 {
446 buf_clear( &stack );
447 ge_save( &stack );
448 if ( compinit->output[0] )
449 str_copyzero( data, compinit->output );
450 else
451 {
452 str_copyzero( data, compinit->input );
453 str_ptr( data )[ str_len( data )] = 'e';
454 buf_appendch( (pbuf)data, 0 );
455 }
456 buf2file( data, &stack );
457 }
458 _compile = NULL;
459 buf_delete( &stack );
460 str_destroy( data );
461 // memstat();
462
463 if ( !( icompile.flag & CMPL_NORUN ))
464 compinit->result = vm_execute( 1 );
465 return TRUE;
466 }
467
468 /*-----------------------------------------------------------------------------
469 ** Id: gentee_compile F
470 *
471 * Summary: Program compilation. This function allows to compile and run
472 programs in Gentee.
473 *
474 * Params: compinit - The pointer to $[compileinfo] structure with the /
475 specified compiling options.
476 *
477 * Return: #lng/retf#
478 *
479 -----------------------------------------------------------------------------*/
480
481 uint STDCALL gentee_compile( pcompileinfo compinit )
482 {
483 uint ret = 0;
484 uint i;
485
486 compinit->result = 0;
487 compinit->hthread = 0;
488 for ( i = KERNEL_COUNT; i < arr_count( &_vm.objtbl ); i++ )
489 {
490 ((pvmobj)PCMD( i ))->flag |= GHRT_SKIP;
491 vm_clearname( i );
492 }
493 if ( compinit->flag & CMPL_THREAD )
494 {
495 compinit->hthread = os_thread( &thread_compile, compinit );
496 if ( compinit->flag & CMPL_NOWAIT )
497 return 1;
498 os_wait( compinit->hthread, INFINITE );
499 os_exitcode( compinit->hthread, &ret );
500 }
501 else
502 ret = thread_compile( compinit );
503
504 return ret;
505 }
506
507 //----------------------------------------------------------------------------