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 icompile.curdir = str_new( 0 );
296 os_dirgetcur( icompile.curdir );
297
298 if ( compinit->flag & CMPL_OPTIMIZE )
299 _compile->popti = &compinit->opti;
300
301 icompile.flag = compinit->flag;
302 data = str_new( compinit->input );
303 buf_init( &stack );
304 buf_reserve( &stack, (( STACK_OPERS + STACK_OPS ) << 1 ) + STACK_PARS );//0xFFFF << 1 );
305
306 arrdata_strload( arrdata_init( &icompile.libdirs ), compinit->libdirs );
307 hash_init( &icompile.files, sizeof( uint ));
308 hash_init( &icompile.names, sizeof( uint ));
309 hash_init( &icompile.resource, sizeof( uint ));
310 hash_init( &icompile.opers, sizeof( uint ));
311 hash_init( &icompile.macros, sizeof( macro ));
312 hash_init( &icompile.namedef, sizeof( macro ));
313
314 arrdata_init( &icompile.string );
315 arrdata_init( &icompile.binary );
316 icompile.files.ignore = 1;
317 lex_init( &icompile.ilex, ( puint )&lexgentee );
318 icompile.stkopers = buf_ptr( &stack );
319 icompile.stkops = ( pubyte )icompile.stkopers + STACK_OPERS;//0xFFFF;
320 icompile.stkpars = ( pubyte )icompile.stkops + STACK_OPS;//0xFFFF;
321 icompile.stkmopers = ( pubyte )icompile.stkpars + STACK_PARS;//0xFFFF;
322 icompile.stkmops = ( pubyte )icompile.stkmopers + STACK_OPERS;//0xFFFF;
323 ptr = ( pubyte )&operlexlist;
324 // Loading hash of operators
325 for ( i = 0; i < OPERCOUNT; i++ )
326 {
327 if ( *ptr )
328 {
329 hash_setuint( &icompile.opers, ptr, i );
330 ptr += mem_len( ptr );
331 }
332 ptr++;
333 }
334 macro_init();
335
336 /*#ifndef LINUX
337 src = str_new( 0 );
338 if ( icompile.flag & CMPL_SRC )
339 str_copy( src, data );
340 else
341 file2buf( data, src, 0 );
342
343 // print( "CMD LINE=%s\n",str_ptr( cmpfile.src ) );
344 // getch();
345 if ( *( pushort )str_ptr( src ) == 0x2123 &&
346 _compile->flag & CMPL_LINE && !getenv("GNUMSIGN"))
347 {
348 ubyte cmdline[512];
349 pubyte cur;
350 pubyte input = str_ptr( src ) + 2;
351 PROCESS_INFORMATION stpi;
352 STARTUPINFO start;
353
354 ZeroMemory( &stpi, sizeof( PROCESS_INFORMATION ));
355 ZeroMemory( &start, sizeof( STARTUPINFO ));
356 start.cb = sizeof( STARTUPINFO );
357
358 cur = ( pubyte )&cmdline;
359 while ( *input >= ' ' )
360 {
361 if ( *input == '%' && *( input + 1 ) == '1' )
362 {
363 mem_copyuntilzero( cur, str_ptr( data ));
364 cur += mem_len( cur );
365 input += 2;
366 }
367 else
368 *cur++ = *input++;
369 }
370 *cur = 0;
371 _putenv("GNUMSIGN=1");
372 // print( "CMD LINE=%s\n",cmdline );
373 CreateProcess( 0, cmdline, 0, 0, TRUE,
374 CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
375 0, 0, &start, &stpi );
376 ExitProcess( 0 );
377 }
378 str_destroy( src );
379 #endif*/
380
381 if ( *compinit->defargs || *compinit->include )
382 {
383 pstr stemp = str_new( "" );
384 pstr include = str_new( "" );
385 pstr dargs = str_new( "" );
386 pubyte cur, src;
387
388 str_reserve( stemp, 1024 );
389 str_reserve( include, 1024 );
390 str_reserve( dargs, 1024 );
391
392 if ( *compinit->include )
393 {
394 cur = str_ptr( include );
395 src = compinit->include;
396 while ( *src )
397 {
398 sprintf( cur, "$\"%s\"\r\n", src );
399 cur += mem_len( cur );
400 src += mem_len( src ) + 1;
401 }
402 *cur = 0;
403 str_setlen( include, cur - str_ptr( include ));
404 }
405 if ( *compinit->defargs )
406 {
407 cur = str_ptr( dargs );
408 src = compinit->defargs;
409 while ( *src )
410 {
411 sprintf( cur, "%s\r\n", src );
412 cur += mem_len( cur );
413 src += mem_len( src ) + 1;
414 }
415 *cur = 0;
416 str_setlen( dargs, cur - str_ptr( dargs ));
417 }
418 str_printf( stemp, "define {\r\n\
419 %s\r\n\
420 }\r\n\
421 include {\r\n\
422 %s\r\n\
423 }\r\n\
424 include : $\"%s\"", str_ptr( dargs ), str_ptr( include ), str_ptr( data ));
425 // printf( str_ptr( stemp ));
426 _compile->flag |= CMPL_SRC;
427 str_copy( data, stemp );
428 str_destroy( stemp );
429 str_destroy( include );
430 str_destroy( dargs );
431 }
432 compile_process( data );
433
434 hash_delete( &icompile.files );
435 hash_delete( &icompile.names );
436 hash_delete( &icompile.resource );
437 hash_delete( &icompile.opers );
438 hash_delete( &icompile.macros );
439 hash_delete( &icompile.namedef );
440 arrdata_delete( &icompile.libdirs );
441 arrdata_delete( &icompile.string );
442 arrdata_delete( &icompile.binary );
443
444 lex_delete( &icompile.ilex );
445 msg( MEnd );
446
447 if ( compinit->flag & CMPL_GE )
448 {
449 buf_clear( &stack );
450 ge_save( &stack );
451 if ( compinit->output[0] )
452 str_copyzero( data, compinit->output );
453 else
454 {
455 str_copyzero( data, compinit->input );
456 str_ptr( data )[ str_len( data )] = 'e';
457 buf_appendch( (pbuf)data, 0 );
458 }
459 buf2file( data, &stack );
460 }
461 str_destroy( icompile.curdir );
462 _compile = NULL;
463 buf_delete( &stack );
464 str_destroy( data );
465 // memstat();
466
467 if ( !( icompile.flag & CMPL_NORUN ))
468 compinit->result = vm_execute( 1 );
469 return TRUE;
470 }
471
472 /*-----------------------------------------------------------------------------
473 ** Id: gentee_compile F
474 *
475 * Summary: Program compilation. This function allows to compile and run
476 programs in Gentee.
477 *
478 * Params: compinit - The pointer to $[compileinfo] structure with the /
479 specified compiling options.
480 *
481 * Return: #lng/retf#
482 *
483 -----------------------------------------------------------------------------*/
484
485 uint STDCALL gentee_compile( pcompileinfo compinit )
486 {
487 uint ret = 0;
488 uint i;
489
490 compinit->result = 0;
491 compinit->hthread = 0;
492 if ( !( compinit->flag & CMPL_NOCLEAR ))
493 for ( i = KERNEL_COUNT; i < arr_count( &_vm.objtbl ); i++ )
494 {
495 ((pvmobj)PCMD( i ))->flag |= GHRT_SKIP;
496 vm_clearname( i );
497 }
498
499 if ( compinit->flag & CMPL_THREAD )
500 {
501 compinit->hthread = os_thread( &thread_compile, compinit );
502 if ( compinit->flag & CMPL_NOWAIT )
503 return 1;
504 os_wait( compinit->hthread, INFINITE );
505 os_exitcode( compinit->hthread, &ret );
506 }
507 else
508 ret = thread_compile( compinit );
509
510 return ret;
511 }
512
513 //----------------------------------------------------------------------------
514