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