1 #output = %EXEPATH%\gentee-x.exe
2 #norun = 1
3 #exe = 1 d g
4 #optimizer = 1
5 #include = clear
6 #wait = 3
7 #res = ..\..\res\exe\version.res
8 /******************************************************************************
9 *
10 * Copyright (C) 2008, The Gentee Group. All rights reserved.
11 * This file is part of the Gentee open source project - http://www.gentee.com.
12 *
13 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
14 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
15 * ACCEPTANCE OF THE AGREEMENT.
16 *
17 * Author: Alexey Krivonogov ( gentee )
18 *
19 ******************************************************************************/
20
21 // При смене команд надо делать exe.exe -> gentee.exe и запускать так
22 //..\..\exe\gentee.exe gentee.g -xd gentee.g
23
24 include
25 {
26 $"..\..\lib\stdlib\stdlib.g"
27 $"..\..\lib\compiler\compiler.g"
28 $"..\..\lib\linker\linker.g"
29 $"..\..\lib\ini\ini.g"
30 }
31
32 global
33 {
34 str head = "Gentee Programming Language v3.6.1
35 Freeware open source compiler & the run-time engine
36 Copyright (C) 2004-09 The Gentee Group. All rights reserved.
37 Internet: http://www.gentee.com Email: info@gentee.com\l\l"
38
39 }
40
41 global
42 {
43 arrstr errtext = %{
44 "Cannot create/open file %s.",
45 "%s is not a launcher.",
46 "Cannot write %s file.",
47 "Cannot write the temporary resource file %s.",
48 "Cannot add the resource file %s.",
49 "Cannot copy %s",
50 "Cannot read %s",
51 "Cannot create the .gentee section.",
52 "Cannot add the XP manifest."
53 }
54 }
55
56 func linkerror( uint code, str param )
57 {
58 str out
59
60 if ¶m : out.printf( errtext[ code ], %{ param } )
61 else : out = errtext[ code ]
62 print( "Linker error: \(out)\nPress any key..." )
63 getch()
64 exit( 0 )
65 }
66
67 func macroreplace( gcompileinfo gcinfo )
68 {
69 arrstr amacro = %{ "%GNAME%", "%GPATH%", "%EXEPATH%" }
70 arrstr mpath[3]
71 str stemp
72
73 getmodulepath( mpath[2], "" )
74 gcinfo.input.fgetparts( mpath[1], mpath[0], 0->str )
75
76 gcinfo.includes.replace( amacro, mpath, $QS_IGNCASE )
77 gcinfo.libs.replace( amacro, mpath, $QS_IGNCASE )
78 gcinfo.defargs.replace( amacro, mpath, $QS_IGNCASE )
79 gcinfo.args.replace( amacro, mpath, $QS_IGNCASE )
80 gcinfo.output.replace( amacro, mpath, $QS_IGNCASE )
81 }
82
83 func uint wrongpar( str filename option )
84 {
85 print( head )
86 print( "Please specify \(filename) after '\(option)' option.\l
87 gentee.exe [<switches>] \(option) <\(filename)> <source file>\n" )
88 getch()
89 return 0
90 }
91
92 func uint main<main>
93 {
94 gcompileinfo gcinfo
95 uint next flag wait exe run i
96 ini pini
97 linker plinker
98 str profile stemp ininame tempdir
99
100 subfunc uint getprofile( str name, uint ptrval, uint flag )
101 {
102 str val
103
104 if flag < 0xFFF0
105 {
106 pini.getvalue( profile, name, val, ?( ptrval->uint & flag, "1", "0" ))
107 if val[0] == '1' : ptrval->uint |= flag
108 else : ptrval->uint &= ~flag
109 }
110 elif flag == 0xFFF0 // string value
111 {
112 pini.getvalue( profile, name, val, ptrval->str )
113 ptrval->str = val
114 }
115 elif flag == 0xFFF1
116 {
117 uint i
118 str skey = name
119
120 while 1
121 {
122 pini.getvalue( profile, skey, val, "" )
123 if !*val : break
124 ptrval->arrstr += val
125 skey = "\(name)\(++i)"
126 }
127 }
128 elif flag == 0xFFF2
129 {
130 arrstr apar
131 uint i clt k
132
133 pini.getvalue( profile, name, val, "" )
134 if !uint( val ) : return 0
135 val.split( apar, ' ', $SPLIT_NOSYS )
136 clt as ptrval->collection
137
138 fornum i = 1, *apar
139 {
140 fornum k = 0, *clt / 3
141 {
142 if clt[k*3]->str %== apar[i]
143 {
144 clt[ k*3 + 1 ]->uint |= clt[ k*3 + 2 ]
145 break
146 }
147 }
148 }
149 if *apar == 1 && !*( clt[*clt - 3]->str )
150 {
151 clt[ *clt - 2 ]->uint |= clt[ *clt - 1 ]
152 }
153 return 1
154 }
155 elif flag == 0xFFF3
156 {
157 pini.getvalue( profile, name, val, "0" )
158 ptrval->uint = uint( val )
159 }
160 return 0
161 }
162
163 subfunc loadprofile( str data )
164 {
165 if *data
166 {
167 pini.data = data
168 pini.data.lines( pini.lines, 1, pini.offset )
169 }
170 else
171 {
172 getmodulename( ininame ).fsetext("ini")
173 pini.read( ininame )
174 }
175
176 // Load options from profile
177 getprofile( "silent", &flag, $G_SILENT )
178 getprofile( "charoem", &flag, $G_CHARPRN )
179 getprofile( "gefile", &gcinfo.flag, $CMPL_GE )
180 getprofile( "norun", &gcinfo.flag, $CMPL_NORUN )
181 getprofile( "debug", &gcinfo.flag, $CMPL_DEBUG )
182 getprofile( "asm", &gcinfo.flag, $CMPL_ASM )
183 getprofile( "numsign", &gcinfo.flag, $CMPL_LINE )
184 getprofile( "output", &gcinfo.output, 0xFFF0 )
185 getprofile( "wait", &wait, 0xFFF3 );
186 exe = getprofile( "exe", &%{ "g", &plinker.flag, $LINK_GUI,
187 "d", &plinker.flag, $LINK_DLL,
188 "a", &plinker.flag, $LINK_ASM,
189 "p", &plinker.flag, $LINK_PACK,
190 "r", &plinker.flag, $LINK_ASMRT,
191 "t", &plinker.flag, $RES_ACCESS,
192 "n", &plinker.flag, $RES_ADMIN }, 0xFFF2 );
193 if getprofile( "optimizer", &%{ "d", &gcinfo.optiflag, $OPTI_DEFINE,
194 "n", &gcinfo.optiflag, $OPTI_NAME,
195 "u", &gcinfo.optiflag, $OPTI_AVOID,
196 "", &gcinfo.optiflag, $OPTI_DEFINE | $OPTI_NAME | $OPTI_AVOID
197 }, 0xFFF2 )
198 {
199 gcinfo.flag |= $CMPL_OPTIMIZE
200 }
201 getprofile( "icon", &plinker.icons, 0xFFF1 );
202 getprofile( "res", &plinker.res, 0xFFF1 );
203 getprofile( "define", &gcinfo.defargs, 0xFFF1 );
204 getprofile( "libdir", &gcinfo.includes, 0xFFF1 );
205 getprofile( "include", &gcinfo.libs, 0xFFF1 );
206 getprofile( "args", &gcinfo.args, 0xFFF1 );
207 }
208 subfunc addargs( str out )
209 {
210 foreach cura, gcinfo.args
211 {
212 if cura.findch(' ') < *cura : out += " \"\(cura)\""
213 else : out += " \(cura)"
214 }
215 }
216 if !argc()
217 {
218 print( head )
219 print( "How to compile:
220 gentee.exe [<switches>] <source .g or .ge file> [command line arguments]
221
222 <switches>
223 -a - Convert bytecode to assembler
224 -c - Compiling only. Do not run the program after compiling
225 -m <define macros>- Define macros for compiling
226 Example: -m \"MODE=1;NAME=\\\"My Company, Inc\\\"\"
227 -f - Create GE file.
228 -n - Ignore the command line #!...
229 -o <output file> - Output GE or EXE filename (not default) will be specified.
230 -p <profile name> - Use the profile from gentee.ini file.
231 -s - Do not display any messages during the compiling or the executing
232 -t - Convert print strings to OEM-defined character set
233 -d - Include debug information
234 -w - Wait for pressing key at the end.
235 -z[d][n][u] - Optimize a byte-code ( -f or -x compatible )
236 -zd - Delete defines.
237 -zn - Delete names.
238 -zu - Delete no used objects.
239 -z equals -zdnu. Combine -zd, -zn and -zu
240 -x[d][g][a][r][p] - Create executable EXE file.
241 -xd - Dynamic usage of gentee.dll.
242 -xg - Make a gui application.
243 In default a console application is created.
244 -xa - Compile a bytecode to assembler.
245 -xr - Run-time converting a bytecode to assembler.
246 -xp - Compress a byte-code & dll.
247 Example: -xdg - Combine -xd and -xg
248 -i <icon file> - Link .ico file ( -x compatible ).
249 -i \"c:\\data\\myicon.ico\"
250 -r <res file> - Link .res file ( -x compatible ).
251 -r \"c:\\data\\myres.res\"
252 Examples
253 gentee.exe -x -i \"c:\\myfile.ico\" -w myfile.g
254
255 Press any key...")
256 getch()
257 return 0
258 }
259 gcinfo.flag |= $CMPL_LINE | $CMPL_THREAD
260
261 fornum next, argc()
262 {
263 str sarg
264
265 argv( stemp, next + 1 )
266 if stemp[0] != '-' : break;
267
268 switch stemp[ 1 ]
269 {
270 case 'a','A' : gcinfo.flag |= $CMPL_ASM
271 case 'c','C' : gcinfo.flag |= $CMPL_NORUN
272 case 'n','N' : gcinfo.flag &= ~$CMPL_LINE
273 case 'm','M'
274 {
275 argv( sarg, ++next + 1 )
276 if !*sarg || sarg[0] == '-' : return wrongpar( "macros", "-m" )
277 gcinfo.defargs += sarg;
278 }
279 case 'f','F': gcinfo.flag |= $CMPL_GE
280 case 'o','O'
281 {
282 argv( sarg, ++next + 1 )
283 if !*sarg || sarg[0] == '-' : return wrongpar( "output file", "-o" )
284 gcinfo.output = sarg
285 gcinfo.flag |= $CMPL_GE
286 }
287 case 's','S': flag |= $G_SILENT
288 case 't','T': flag |= $G_CHARPRN
289 case 'd','D': gcinfo.flag |= $CMPL_DEBUG
290 case 'p','P'
291 {
292 argv( sarg, ++next + 1 )
293 if !*sarg || sarg[0] == '-'
294 {
295 return wrongpar( "profile name", "-p" )
296 }
297 profile = sarg
298 loadprofile( "" )
299 }
300 case 'w','W': wait = 1
301 case 'x','X'
302 {
303 exe = 1
304 i = 2
305 stemp.lower()
306 while stemp[ i ]
307 {
308 switch stemp[i]
309 {
310 case 'g' : plinker.flag |= $LINK_GUI
311 case 'd' : plinker.flag |= $LINK_DLL
312 case 'a' : plinker.flag |= $LINK_ASM
313 case 'r' : plinker.flag |= $LINK_ASMRT
314 case 'p' : plinker.flag |= $LINK_PACK
315 }
316 i++
317 }
318 }
319 case 'i','I'
320 {
321 argv( sarg, ++next + 1 )
322 if !*sarg || sarg[0] == '-' : return wrongpar( "icon file", "-i" )
323 plinker.icons += "ICON_APP, \(sarg)"
324 }
325 case 'r','R'
326 {
327 argv( sarg, ++next + 1 )
328 if !*sarg || sarg[0] == '-'
329 {
330 return wrongpar( "resource file", "-r" )
331 }
332 plinker.res += sarg
333 }
334 case 'z','Z'
335 {
336 i = 2
337 stemp.lower()
338 if !stemp[2]
339 {
340 gcinfo.optiflag = $OPTI_DEFINE | $OPTI_NAME | $OPTI_AVOID
341 }
342 else
343 {
344 while stemp[ i ]
345 {
346 if stemp[i] == 'd' : gcinfo.optiflag |= $OPTI_DEFINE
347 elif stemp[i] == 'n' : gcinfo.optiflag |= $OPTI_NAME
348 elif stemp[i] == 'u' : gcinfo.optiflag |= $OPTI_AVOID
349 i++
350 }
351 }
352 gcinfo.flag |= $CMPL_OPTIMIZE
353 }
354 }
355 }
356 gentee_set( $GSET_FLAG, flag )
357 if next == argc()
358 {
359 print( head )
360 print( "Please specify a source filename.\l
361 gentee.exe [<switches>] <source file>")
362 getch()
363 return 0
364 }
365 argv( gcinfo.input, ++next )
366 while next++ < argc()
367 {
368 argv( stemp, next )
369 gcinfo.args += stemp
370 }
371 addargs( stemp.clear() )
372 if gcinfo.flag & $CMPL_LINE && gcinfo.input.fgetext() %!= "ge"
373 {
374 arrstr alines
375 alines.read( gcinfo.input )
376
377 if *alines
378 {
379 if "#!".eqlen( alines[0] ) && !uint( getenv( "GNUMSIGN", "" ))
380 {
381 getmodulepath( tempdir, 0->str )
382 stemp.copy( alines[0].ptr() + 2 )
383 stemp.replace( "%1", gcinfo.input, 0 )
384 addargs( stemp )
385 setenv( "GNUMSIGN", "1" )
386 // tempdir.fgetdir( gcinfo.input )
387 process( stemp, 0->str, 0 ) // tempdir
388 return 0
389 }
390 // Read file for getting # options
391 if alines[0][0] == '#' && alines[0][1] != '!'
392 {
393 profile = "gentee"
394 stemp = "[gentee]\l"
395 i = 0
396 while alines[i][0] == '#'
397 {
398 stemp.append( alines[i].ptr() + 1, *alines[i] - 1 )
399 stemp += "\l"
400 i++
401 }
402 loadprofile( stemp )
403 }
404 }
405 }
406 // Replace macro values
407
408 macroreplace( gcinfo )
409 if !( flag & $G_SILENT ) : print( head )
410 if exe
411 {
412 if !( gcinfo.flag & $CMPL_NORUN )
413 {
414 run = 1
415 gcinfo.flag |= $CMPL_NORUN
416 }
417 gcinfo.flag |= $CMPL_GE
418 if !*gcinfo.output : gcinfo.output = gcinfo.input
419
420 gcinfo.output.fsetext( "ge" )
421 }
422 if *gcinfo.libs && gcinfo.libs[ *gcinfo.libs - 1 ] %== "clear"
423 {
424 gcinfo.libs.clear()
425 }
426 compile_file( gcinfo )
427 if exe
428 {
429 with plinker
430 {
431 .errfunc = &linkerror
432 .input = gcinfo.output
433 (.output = .input ).fsetext("exe")
434 if flag & $G_CHARPRN : .flag |= $LINK_CHAR
435 if gcinfo.flag & $CMPL_ASM : .flag |= $LINK_ASM
436 }
437 if plinker.create() && !( flag & $G_SILENT )
438 {
439 print( "Executable file \( plinker.output ) - created...\n" )
440 }
441 deletefile( gcinfo.output )
442 }
443
444 if wait == 1 : congetch("\nPress any key...\n")
445 elif wait > 1 : Sleep( wait * 1000 )
446 if run
447 {
448 stemp = "\"\(plinker.output)\""
449 addargs( stemp )
450 tempdir.fgetdir( plinker.output )
451 process( stemp, tempdir, 0 )
452 }
453
454 return 0
455 }