PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/compiler/compile.c

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