1 /******************************************************************************
2 *
3 * Copyright (C) 2006-08, 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 * Author: Alexey Krivonogov
11 *
12 ******************************************************************************/
13
14 /*-----------------------------------------------------------------------------
15 * Id: genteeapi L "Gentee API"
16 *
17 * Desc: Gentee API functions for the using of gentee.dll.
18 * Summary: There is an option for software engineers to run programs in Gentee
19 in their own applications. To do that, it is enough to connect the
20 gentee.dll file. It contains several importable functions, which
21 are responsible for compilation and execution of the programs.
22 *
23 * List: *, gentee_call, gentee_compile, gentee_deinit, gentee_getid,
24 gentee_init, gentee_load, gentee_ptr, gentee_set,
25 *#lng/types#, tgentee, compileinfo, toptimize
26 *
27 -----------------------------------------------------------------------------*/
28
29 #include "gentee.h"
30 #include "../common/crc.h"
31 #include "../common/memory.h"
32 #include "../common/file.h"
33 #include "../os/user/defines.h"
34 #include "../bytecode/ge.h"
35
36 gentee _gentee;
37 pcompile _compile;
38
39 /*-----------------------------------------------------------------------------
40 * Id: gentee_deinit F1
41 *
42 * Summary: End of working with gentee.dll. This function should be called when
43 the work with Gentee is finished.
44 *
45 * Return: #lng/retf#
46 *
47 -----------------------------------------------------------------------------*/
48
49 uint STDCALL gentee_deinit( void )
50 {
51 // print("Deinit %i %s size=%i use=%i\n", &_gentee.tempdir, _gentee.tempdir.data,
52 // _gentee.tempdir.size, _gentee.tempdir.use );
53 vm_deinit();
54 if ( _gentee.tempfile )
55 {
56 str stemp;
57
58 str_init( &stemp );
59 str_reserve( &stemp, 512 );
60 os_dirdeletefull( &_gentee.tempdir );
61 os_fileclose( _gentee.tempfile );
62 str_printf( &stemp, "%s.tmp", str_ptr( &_gentee.tempdir ));
63 os_filedelete( &stemp );
64 str_delete( &stemp );
65 }
66 str_delete( &_gentee.tempdir );
67 mem_deinit();
68
69 return TRUE;
70 }
71
72 /*-----------------------------------------------------------------------------
73 * Id: gentee_init F
74 *
75 * Summary: Initialization of gentee.dll. This function should be called before
76 beginning to work with Gentee.
77 *
78 * Params: flags - Flags. $$[initflags]
79 *
80 * Return: #lng/retf#
81 *
82 -----------------------------------------------------------------------------*/
83
84 uint STDCALL gentee_init( uint flags )
85 {
86 mem_zero( &_gentee, sizeof( gentee ));
87
88 mem_init();
89 crc_init();
90
91 _gentee.flags = flags;
92 _gentee.print = &os_print;
93 os_init( 0 );
94
95 str_init( &_gentee.tempdir );
96
97 vm_init();
98 _compile = NULL;
99 _gentee.message = &message;
100
101 return TRUE;
102 }
103
104 /*-----------------------------------------------------------------------------
105 * Id: gentee_set F
106 *
107 * Summary: This function specifies some gentee parameters.
108 *
109 * Params: state - The identifier of the parameter.$$[setpars]
110 val - The new value of the parameter.
111 *
112 * Return: #lng/retf#
113 *
114 -----------------------------------------------------------------------------*/
115
116 uint STDCALL gentee_set( uint state, pvoid val )
117 {
118 switch ( state )
119 {
120 case GSET_FLAG:
121 _gentee.flags = ( uint )val;
122 break;
123 case GSET_TEMPDIR:
124 if ( _gentee.tempfile )
125 return 0;
126 str_copyzero( &_gentee.tempdir, ( pubyte )val );
127 break;
128 case GSET_PRINT:
129 _gentee.print = ( printfunc )val;
130 break;
131 case GSET_MESSAGE:
132 _gentee.message = ( messagefunc )val;
133 break;
134 case GSET_EXPORT:
135 _gentee.export = ( exportfunc )val;
136 break;
137 case GSET_DEBUG:
138 _gentee.debug = ( debugfunc )val;
139 break;
140 case GSET_GETCH:
141 _gentee.getch = ( getchfunc )val;
142 break;
143 case GSET_ARGS:
144 _gentee.args = val;
145 break;
146 }
147 return 1;
148 }
149
150 /*-----------------------------------------------------------------------------
151 * Id: gentee_ptr F
152 *
153 * Summary: Get Gentee structures. This function returns pointers to global
154 Gentee structures.
155 *
156 * Params: par - The identifier of the parameter.$$[ptrpars].
157 *
158 * Return: The pointer to according global Gentee structure.
159 *
160 -----------------------------------------------------------------------------*/
161
162 pvoid STDCALL gentee_ptr( uint par )
163 {
164 switch ( par )
165 {
166 case GPTR_GENTEE:
167 return &_gentee;
168 case GPTR_VM:
169 return _pvm;
170 case GPTR_COMPILE:
171 return _compile;
172 case GPTR_CALL:
173 return &gentee_call;
174 }
175 return &_gentee;
176 }
177
178 /*-----------------------------------------------------------------------------
179 * Id: gentee_load F
180 *
181 * Summary: Load and launch the bytecode. This function loads the bytecode from
182 the file or the memory and launch it if it is required. You can
183 create the bytecode with $[gentee_compile] function.
184 *
185 * Params: bytecode - The pointer to the bytecode or the filename of .ge file.
186 flag - Flags. $$[geloadflag]
187 *
188 * Return: The result of the executed bytecode if GLOAD_RUN was defined.
189 *
190 -----------------------------------------------------------------------------*/
191
192 uint STDCALL gentee_load( pubyte bytecode, uint flag )
193 {
194 pubyte cur, curout, oldargs;
195 uint count, result = 0;
196 ubyte stop;
197 buf bcode;
198
199 buf_init( &bcode );
200 if ( flag & GLOAD_ARGS )
201 { // Получаем аргументы из командной строки
202 oldargs = _gentee.args;
203 curout = _gentee.args = mem_alloc( 1024 );
204 cur = GetCommandLine();
205 count = 0;
206 while ( *cur )
207 {
208 while ( *cur == ' ' ) cur++;
209 if ( !*cur ) break;
210
211 if ( *cur == '\"' )
212 {
213 cur++;
214 stop = '\"';
215 }
216 else
217 stop = ' ';
218
219 while ( *cur != stop )
220 {
221 if ( count )
222 {
223 if ( *cur == '\\' && *( cur + 1 )== '\"' )
224 cur++;
225 *curout++ = *cur;
226 }
227 if ( !*++cur ) break;
228 }
229 if ( *cur == stop ) cur++;
230 if ( count++ )
231 *curout++ = 0;
232 }
233 *curout = 0;
234 }
235 if ( flag & GLOAD_FILE )
236 {
237 str filename;
238
239 str_init( &filename );
240 str_copyzero( &filename, bytecode );
241 file2buf( &filename, &bcode, 0 );
242 str_delete( &filename );
243 }
244 else
245 buf_copy( &bcode, bytecode, (( pgehead )bytecode)->size );
246 // print("OK 0\n");
247 ge_load( &bcode );
248
249 if ( flag & GLOAD_RUN )
250 result = vm_execute( 1 );
251
252 if ( flag & GLOAD_ARGS )
253 {
254 mem_free( _gentee.args );
255 _gentee.args = oldargs;
256 }
257 buf_delete( &bcode );
258 return result;
259 }
260
261 /*-----------------------------------------------------------------------------
262 ** Id: gentee_getid F
263 *
264 * Summary: Get the object's identifier by its name.
265 *
266 * Params: name - The name of the object. If you want to find a method then /
267 use '#b(@)' at the beginning of the name. For example, /
268 "#b( @mymethod )". If you want to find an operator then /
269 use '#b(##)' at the beginning of the name. For example, /
270 "#b( #+= )".
271 count - The count of the following parameters. If you want to find /
272 any object with the defined name then specify the following /
273 flag. $$[getidflag]
274 ... - Specify the sequence of the type's identifiers of the /
275 parameters. If the parameter of the function has "#b( of )" /
276 subtype then specify it in the HIWORD of the value.
277 *
278 * Return: Returns object’s identifier or #b(0), if the object was not found.
279 *
280 -----------------------------------------------------------------------------*/
281
282 uint CDECLCALL gentee_getid( pubyte name, uint count, ... )
283 {
284 uint k = 0;
285 uint params[ 32 ];
286 uint bcode, flag;
287 va_list argptr;
288
289 flag = count;
290 count &= 0xFFFFFF;
291
292 if ( flag & GID_ANYOBJ )
293 {
294 phashitem phi;
295 phi = hash_find( &_vm.objname, name );
296 return phi ? *( puint )( phi + 1 ) : 0;
297 }
298 va_start( argptr, count );
299
300 while ( count-- )
301 {
302 params[ k++ ] = va_arg( argptr, uint );
303 if ( params[ k - 1 ] & 0xFFFF0000 )
304 {
305 params[ k ] = params[ k - 1 ] >> 16;
306 params[ k - 1 ] &= 0xFFFF;
307 }
308 else
309 params[ k ] = 0;
310 k++;
311 }
312 va_end( argptr );
313
314 bcode = ( uint )vm_find( name, k >> 1, params );
315 return ( uint )bcode < MSGCOUNT ? 0 : ((pvmfunc)bcode)->vmo.id;
316 }
317
318 //--------------------------------------------------------------------------
319