0
|
1 module main;
|
|
2
|
|
3 import dmd.Array;
|
|
4 import dmd.Module;
|
|
5 import dmd.Global;
|
|
6 import dmd.VersionCondition;
|
|
7 import dmd.DebugCondition;
|
|
8 import dmd.Loc;
|
|
9 import dmd.Lexer;
|
|
10 import dmd.OutBuffer;
|
|
11 import dmd.FileName;
|
|
12 import dmd.Type;
|
|
13 import dmd.File;
|
|
14 import dmd.Id;
|
|
15 import dmd.Identifier;
|
|
16 import dmd.Library;
|
|
17 import dmd.TOK;
|
|
18 import dmd.String;
|
|
19 import dmd.backend.glue;
|
|
20
|
|
21 import std.stdarg;
|
|
22 import std.string : toStringz;
|
|
23 import std.contracts;
|
|
24
|
|
25 import core.stdc.string;
|
|
26 import core.stdc.stdio;
|
|
27 import core.stdc.ctype;
|
|
28 import core.stdc.errno;
|
|
29 import core.stdc.stdlib;
|
|
30 import core.stdc.limits;
|
|
31
|
|
32 import core.memory;
|
|
33
|
|
34 import dlib.CrashHandler;
|
|
35 import dbg.ui.CrashWindow;
|
|
36
|
|
37 import dmd.Util;
|
|
38
|
|
39 bool loop = true;
|
|
40
|
|
41 enum ExitCode
|
|
42 {
|
|
43 EXIT_SUCCESS = 0,
|
|
44 }
|
|
45
|
|
46 version (Windows)
|
|
47 {
|
|
48 private import core.stdc.wchar_;
|
|
49 }
|
|
50
|
|
51 extern (C) void gc_init();
|
|
52 extern (C) void gc_term();
|
|
53 extern (C) void _minit();
|
|
54 extern (C) void _moduleCtor();
|
|
55 extern (C) void _moduleDtor();
|
|
56 extern (C) void thread_joinAll();
|
|
57
|
|
58 shared bool _d_isHalting = false;
|
|
59
|
|
60 import win32.windows;
|
|
61
|
|
62 extern (C) int main(int argc, char **argv)
|
|
63 {
|
|
64 char[][] args;
|
|
65 int result;
|
|
66
|
|
67 version (OSX)
|
|
68 { /* OSX does not provide a way to get at the top of the
|
|
69 * stack, except for the magic value 0xC0000000.
|
|
70 * But as far as the gc is concerned, argv is at the top
|
|
71 * of the main thread's stack, so save the address of that.
|
|
72 */
|
|
73 __osx_stack_end = cast(void*)&argv;
|
|
74 }
|
|
75
|
|
76 version (Posix)
|
|
77 {
|
|
78 _STI_monitor_staticctor();
|
|
79 _STI_critical_init();
|
|
80 }
|
|
81
|
|
82 version (Windows)
|
|
83 {
|
|
84 wchar_t* wcbuf = GetCommandLineW();
|
|
85 size_t wclen = wcslen(wcbuf);
|
|
86 int wargc = 0;
|
|
87 wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
|
|
88 assert(wargc == argc);
|
|
89
|
|
90 char* cargp = null;
|
|
91 size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, null);
|
|
92
|
|
93 cargp = cast(char*) alloca(cargl);
|
|
94 args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
|
|
95
|
|
96 for (size_t i = 0, p = 0; i < wargc; i++)
|
|
97 {
|
|
98 int wlen = wcslen(wargs[i]);
|
|
99 int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, null);
|
|
100 args[i] = cargp[p .. p+clen];
|
|
101 p += clen; assert(p <= cargl);
|
|
102 WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, null);
|
|
103 }
|
|
104 LocalFree(cast(HANDLE)wargs);
|
|
105 wargs = null;
|
|
106 wargc = 0;
|
|
107 }
|
|
108 else version (Posix)
|
|
109 {
|
|
110 char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
|
|
111 scope(exit) free(am);
|
|
112
|
|
113 for (size_t i = 0; i < argc; i++)
|
|
114 {
|
|
115 auto len = strlen(argv[i]);
|
|
116 am[i] = argv[i][0 .. len];
|
|
117 }
|
|
118 args = am[0 .. argc];
|
|
119 }
|
|
120
|
|
121 gc_init();
|
|
122 version (Windows)
|
|
123 _minit();
|
|
124 _moduleCtor();
|
|
125
|
4
|
126 GC.disable();
|
0
|
127 CrashHandlerInit();
|
|
128
|
|
129 result = main(cast(string[])args);
|
|
130
|
|
131 thread_joinAll();
|
|
132 _d_isHalting = true;
|
|
133 _moduleDtor();
|
|
134 gc_term();
|
|
135
|
|
136 version (Posix)
|
|
137 {
|
|
138 _STD_critical_term();
|
|
139 _STD_monitor_staticdtor();
|
|
140 }
|
|
141
|
|
142 return result;
|
|
143 }
|
|
144
|
|
145 int main(string[] args)
|
|
146 {
|
|
147 Array files = new Array();
|
|
148 Array libmodules = new Array();
|
|
149 Module m;
|
|
150 int status = ExitCode.EXIT_SUCCESS;
|
|
151 int argcstart = args.length;
|
|
152 int setdebuglib = 0;
|
|
153
|
|
154 global = new Global();
|
|
155
|
|
156 /// if (response_expand(&argc,&argv)) // expand response files
|
|
157 /// error("can't open response file");
|
|
158
|
|
159 files.reserve(args.length - 1);
|
|
160
|
|
161 // Set default values
|
|
162 global.params.argv0 = args[0];
|
|
163 global.params.link = 1;
|
|
164 global.params.useAssert = 1;
|
|
165 global.params.useInvariants = 1;
|
|
166 global.params.useIn = 1;
|
|
167 global.params.useOut = 1;
|
|
168 global.params.useArrayBounds = 1;
|
|
169 global.params.useSwitchError = 1;
|
|
170 global.params.useInline = 0;
|
|
171 global.params.obj = 1;
|
|
172 global.params.Dversion = 2;
|
|
173 global.params.quiet = 1;
|
|
174
|
|
175 global.params.linkswitches = new Array();
|
|
176 global.params.libfiles = new Array();
|
|
177 global.params.objfiles = new Array();
|
|
178 global.params.ddocfiles = new Array();
|
|
179
|
|
180 version (TARGET_WINDOS) {
|
|
181 global.params.defaultlibname = "phobos";
|
|
182 } else version (XXX) { //#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
|
|
183 global.params.defaultlibname = "phobos2";
|
|
184 } else version (TARGET_NET) {
|
|
185 } else {
|
|
186 static assert(false, "fix this");
|
|
187 }
|
|
188
|
|
189 // Predefine version identifiers
|
|
190 VersionCondition.addPredefinedGlobalIdent("DigitalMars");
|
|
191
|
|
192 version (TARGET_WINDOS) {
|
|
193 VersionCondition.addPredefinedGlobalIdent("Windows");
|
|
194 global.params.isWindows = 1;
|
|
195 version (TARGET_NET) {
|
|
196 // TARGET_NET macro is NOT mutually-exclusive with TARGET_WINDOS
|
|
197 VersionCondition.addPredefinedGlobalIdent("D_NET");
|
|
198 }
|
|
199 } else version (TARGET_LINUX) {
|
|
200 VersionCondition.addPredefinedGlobalIdent("Posix");
|
|
201 VersionCondition.addPredefinedGlobalIdent("linux");
|
|
202 global.params.isLinux = 1;
|
|
203 } else version (TARGET_OSX) {
|
|
204 VersionCondition.addPredefinedGlobalIdent("Posix");
|
|
205 VersionCondition.addPredefinedGlobalIdent("OSX");
|
|
206 global.params.isOSX = 1;
|
|
207
|
|
208 // For legacy compatibility
|
|
209 VersionCondition.addPredefinedGlobalIdent("darwin");
|
|
210 } else version (TARGET_FREEBSD) {
|
|
211 VersionCondition.addPredefinedGlobalIdent("Posix");
|
|
212 VersionCondition.addPredefinedGlobalIdent("FreeBSD");
|
|
213 global.params.isFreeBSD = 1;
|
|
214 } else version (TARGET_SOLARIS) {
|
|
215 VersionCondition.addPredefinedGlobalIdent("Posix");
|
|
216 VersionCondition.addPredefinedGlobalIdent("Solaris");
|
|
217 global.params.isSolaris = 1;
|
|
218 } else {
|
|
219 static assert (false, "fix this");
|
|
220 }
|
|
221
|
|
222 VersionCondition.addPredefinedGlobalIdent("LittleEndian");
|
|
223 //VersionCondition.addPredefinedGlobalIdent("D_Bits");
|
|
224 version (DMDV2) {
|
|
225 VersionCondition.addPredefinedGlobalIdent("D_Version2");
|
|
226 }
|
|
227 VersionCondition.addPredefinedGlobalIdent("all");
|
|
228
|
|
229 version (_WIN32) {
|
|
230 inifile(args[0], "sc.ini");
|
|
231 } else version (XXX) {///linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
|
|
232 inifile(argv[0], "dmd.conf");
|
|
233 } else {
|
|
234 static assert (false, "fix this");
|
|
235 }
|
|
236 args = getenv_setargv("DFLAGS", args);
|
|
237
|
|
238 version (disabled) {
|
|
239 for (i = 0; i < argc; i++)
|
|
240 {
|
|
241 writef("argv[%d] = '%s'\n", i, argv[i]);
|
|
242 }
|
|
243 }
|
|
244
|
|
245 foreach(i; 1..args.length)
|
|
246 {
|
|
247 auto arg = args[i];
|
|
248 auto p = arg.ptr;
|
|
249 if (*p == '-')
|
|
250 {
|
|
251 arg = arg[1..$];
|
|
252 if (arg == "d")
|
|
253 global.params.useDeprecated = 1;
|
|
254 else if (arg == "c")
|
|
255 global.params.link = 0;
|
|
256 else if (arg == "cov")
|
|
257 global.params.cov = 1;
|
|
258 ///version (XXX) {// TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
|
|
259 /// else if (arg == "fPIC")
|
|
260 /// global.params.pic = 1;
|
|
261 ///}
|
|
262 else if (arg == "multiobj")
|
|
263 global.params.multiobj = 1;
|
|
264 else if (arg == "g")
|
|
265 global.params.symdebug = 1;
|
|
266 else if (arg == "gc")
|
|
267 global.params.symdebug = 2;
|
|
268 else if (arg == "gt")
|
|
269 { error("use -profile instead of -gt\n");
|
|
270 global.params.trace = 1;
|
|
271 }
|
|
272 else if (arg == "m64")
|
|
273 global.params.isX86_64 = 1;
|
|
274 else if (arg == "profile")
|
|
275 global.params.trace = 1;
|
|
276 else if (arg == "v")
|
|
277 global.params.verbose = 1;
|
|
278 ///version (DMDV2) {
|
|
279 else if (arg == "vtls")
|
|
280 global.params.vtls = 1;
|
|
281 ///}
|
|
282 else if (arg == "v1")
|
|
283 {
|
|
284 version (DMDV1) {
|
|
285 global.params.Dversion = 1;
|
|
286 } else {
|
|
287 error("use DMD 1.0 series compilers for -v1 switch");
|
|
288 break;
|
|
289 }
|
|
290 }
|
|
291 else if (arg == "w")
|
|
292 global.params.warnings = 1;
|
|
293 else if (arg == "O")
|
|
294 global.params.optimize = 1;
|
|
295 else if (p[1] == 'o')
|
|
296 {
|
|
297 switch (p[2])
|
|
298 {
|
|
299 case '-':
|
|
300 global.params.obj = 0;
|
|
301 break;
|
|
302
|
|
303 case 'd':
|
|
304 if (!p[3])
|
|
305 goto Lnoarg;
|
|
306 global.params.objdir = arg[(p - arg.ptr) + 3..$];
|
|
307 break;
|
|
308
|
|
309 case 'f':
|
|
310 {
|
|
311 if (!p[3])
|
|
312 goto Lnoarg;
|
|
313
|
|
314 global.params.objname = arg[(p - arg.ptr) + 3..$];
|
|
315 break;
|
|
316 }
|
|
317
|
|
318 case 'p':
|
|
319 if (p[3])
|
|
320 goto Lerror;
|
|
321 global.params.preservePaths = 1;
|
|
322 break;
|
|
323
|
|
324 case 0:
|
|
325 error("-o no longer supported, use -of or -od");
|
|
326 break;
|
|
327
|
|
328 default:
|
|
329 goto Lerror;
|
|
330 }
|
|
331 }
|
|
332 else if (p[1] == 'D')
|
|
333 { global.params.doDocComments = 1;
|
|
334 switch (p[2])
|
|
335 {
|
|
336 case 'd':
|
|
337 if (!p[3])
|
|
338 goto Lnoarg;
|
|
339 global.params.docdir = arg[(p - arg.ptr) + 3..$];
|
|
340 break;
|
|
341 case 'f':
|
|
342 if (!p[3])
|
|
343 goto Lnoarg;
|
|
344 global.params.docname = arg[(p - arg.ptr) + 3..$];
|
|
345 break;
|
|
346
|
|
347 case 0:
|
|
348 break;
|
|
349
|
|
350 default:
|
|
351 goto Lerror;
|
|
352 }
|
|
353 }
|
|
354 ///version (_DH) {
|
|
355 else if (p[1] == 'H')
|
|
356 { global.params.doHdrGeneration = 1;
|
|
357 switch (p[2])
|
|
358 {
|
|
359 case 'd':
|
|
360 if (!p[3])
|
|
361 goto Lnoarg;
|
|
362 global.params.hdrdir = arg[(p - arg.ptr) + 3..$];
|
|
363 break;
|
|
364
|
|
365 case 'f':
|
|
366 if (!p[3])
|
|
367 goto Lnoarg;
|
|
368 global.params.hdrname = arg[(p - arg.ptr) + 3..$];
|
|
369 break;
|
|
370
|
|
371 case 0:
|
|
372 break;
|
|
373
|
|
374 default:
|
|
375 goto Lerror;
|
|
376 }
|
|
377 }
|
|
378 ///}
|
|
379 else if (arg == "ignore")
|
|
380 global.params.ignoreUnsupportedPragmas = 1;
|
|
381 else if (arg == "inline")
|
|
382 global.params.useInline = 1;
|
|
383 else if (arg == "lib")
|
|
384 global.params.lib = 1;
|
|
385 else if (arg == "nofloat")
|
|
386 global.params.nofloat = 1;
|
|
387 else if (arg == "quiet")
|
|
388 global.params.quiet = 1;
|
|
389 else if (arg == "release")
|
|
390 global.params.release = 1;
|
|
391 ///version (DMDV2) {
|
|
392 else if (arg == "safe")
|
|
393 global.params.safe = 1;
|
|
394 ///}
|
|
395 else if (arg == "unittest")
|
|
396 global.params.useUnitTests = 1;
|
|
397 else if (p[1] == 'I')
|
|
398 {
|
|
399 if (!global.params.imppath)
|
|
400 global.params.imppath = new Array();
|
|
401 global.params.imppath.push(cast(void*)new String(arg[(p - arg.ptr) + 2..$])); ///
|
|
402 }
|
|
403 else if (p[1] == 'J')
|
|
404 {
|
|
405 if (!global.params.fileImppath)
|
|
406 global.params.fileImppath = new Array();
|
|
407 global.params.fileImppath.push(cast(void*)new String(arg[(p - arg.ptr) + 2..$]));
|
|
408 }
|
|
409 else if (memcmp(p + 1, "debug".ptr, 5) == 0 && p[6] != 'l')
|
|
410 {
|
|
411 // Parse:
|
|
412 // -debug
|
|
413 // -debug=number
|
|
414 // -debug=identifier
|
|
415 if (p[6] == '=')
|
|
416 {
|
|
417 if (isdigit(p[7]))
|
|
418 { long level;
|
|
419
|
|
420 errno = 0;
|
|
421 level = strtol(p + 7, cast(char**)&p, 10);
|
|
422 if (*p || errno || level > INT_MAX)
|
|
423 goto Lerror;
|
|
424 DebugCondition.setGlobalLevel(cast(int)level);
|
|
425 }
|
|
426 else if (Lexer.isValidIdentifier(arg[(p - arg.ptr) + 7..$])) ///
|
|
427 DebugCondition.addGlobalIdent(p + 7);
|
|
428 else
|
|
429 goto Lerror;
|
|
430 }
|
|
431 else if (p[6])
|
|
432 goto Lerror;
|
|
433 else
|
|
434 global.params.debuglevel = 1;
|
|
435 }
|
|
436 else if (memcmp(p + 1, "version".ptr, 5) == 0)
|
|
437 {
|
|
438 // Parse:
|
|
439 // -version=number
|
|
440 // -version=identifier
|
|
441 if (p[8] == '=')
|
|
442 {
|
|
443 if (isdigit(p[9]))
|
|
444 { long level;
|
|
445
|
|
446 errno = 0;
|
|
447 level = strtol(p + 9, cast(char**)&p, 10); ///
|
|
448 if (*p || errno || level > INT_MAX)
|
|
449 goto Lerror;
|
|
450 VersionCondition.setGlobalLevel(cast(int)level);
|
|
451 }
|
|
452 else if (Lexer.isValidIdentifier(arg[(p - arg.ptr) + 9..$])) ///
|
|
453 VersionCondition.addGlobalIdent(arg[(p - arg.ptr) + 9..$]);
|
|
454 else
|
|
455 goto Lerror;
|
|
456 }
|
|
457 else
|
|
458 goto Lerror;
|
|
459 }
|
|
460 else if (arg == "-b")
|
|
461 global.params.debugb = 1;
|
|
462 else if (arg == "-c")
|
|
463 global.params.debugc = 1;
|
|
464 else if (arg == "-f")
|
|
465 global.params.debugf = 1;
|
|
466 else if (arg == "-help")
|
|
467 { usage();
|
|
468 exit(EXIT_SUCCESS);
|
|
469 }
|
|
470 else if (arg == "-r")
|
|
471 global.params.debugr = 1;
|
|
472 else if (arg == "-x")
|
|
473 global.params.debugx = 1;
|
|
474 else if (arg == "-y")
|
|
475 global.params.debugy = 1;
|
|
476 else if (p[1] == 'L')
|
|
477 {
|
|
478 global.params.linkswitches.push(cast(void*)p + 2);
|
|
479 }
|
|
480 else if (memcmp(p + 1, "defaultlib=".ptr, 11) == 0)
|
|
481 {
|
|
482 global.params.defaultlibname = p + 1 + 11;
|
|
483 }
|
|
484 else if (memcmp(p + 1, "debuglib=".ptr, 9) == 0)
|
|
485 {
|
|
486 setdebuglib = 1;
|
|
487 global.params.debuglibname = p + 1 + 9;
|
|
488 }
|
|
489 else if (memcmp(p + 1, "deps=".ptr, 5) == 0)
|
|
490 {
|
|
491 global.params.moduleDepsFile = arg[(p - arg.ptr) + 1 + 5..$];
|
|
492 if (!global.params.moduleDepsFile[0])
|
|
493 goto Lnoarg;
|
|
494 global.params.moduleDeps = new OutBuffer;
|
|
495 }
|
|
496 else if (memcmp(p + 1, "man".ptr, 3) == 0)
|
|
497 {
|
|
498 version (_WIN32) {
|
|
499 version (DMDV1) {
|
|
500 browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
|
|
501 } else {
|
|
502 browse("http://www.digitalmars.com/d/2.0/dmd-windows.html");
|
|
503 }
|
|
504 }
|
|
505 version (linux) {
|
|
506 version (DMDV1) {
|
|
507 browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
|
|
508 } else {
|
|
509 browse("http://www.digitalmars.com/d/2.0/dmd-linux.html");
|
|
510 }
|
|
511 }
|
|
512 version (__APPLE__) {
|
|
513 version (DMDV1) {
|
|
514 browse("http://www.digitalmars.com/d/1.0/dmd-osx.html");
|
|
515 } else {
|
|
516 browse("http://www.digitalmars.com/d/2.0/dmd-osx.html");
|
|
517 }
|
|
518 }
|
|
519 version (__FreeBSD__) {
|
|
520 version (DMDV1) {
|
|
521 browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html");
|
|
522 } else {
|
|
523 browse("http://www.digitalmars.com/d/2.0/dmd-freebsd.html");
|
|
524 }
|
|
525 }
|
|
526 exit(EXIT_SUCCESS);
|
|
527 }
|
|
528 else if (arg == "run")
|
|
529 { global.params.run = 1;
|
|
530 global.params.runargs_length = ((i >= argcstart) ? args.length : argcstart) - i - 1;
|
|
531 if (global.params.runargs_length)
|
|
532 {
|
|
533 files.push(cast(void*)args[i + 1].ptr);
|
|
534 global.params.runargs = args[i + 2..$];
|
|
535 i += global.params.runargs_length;
|
|
536 global.params.runargs_length--;
|
|
537 }
|
|
538 else
|
|
539 { global.params.run = 0;
|
|
540 goto Lnoarg;
|
|
541 }
|
|
542 }
|
|
543 else
|
|
544 {
|
|
545 Lerror:
|
|
546 error("unrecognized switch '%s'", args[i]);
|
|
547 continue;
|
|
548
|
|
549 Lnoarg:
|
|
550 error("argument expected for switch '%s'", args[i]);
|
|
551 continue;
|
|
552 }
|
|
553 }
|
|
554 else
|
|
555 {
|
|
556 version (TARGET_WINDOS) {
|
|
557 string ext = FileName.ext(p[0..arg.length]);
|
|
558 if (ext != null && FileName.compare(ext, "exe") == 0)
|
|
559 {
|
|
560 global.params.objname = arg[(p - arg.ptr)..$];
|
|
561 continue;
|
|
562 }
|
|
563 }
|
|
564 files.push(cast(void*)new String(arg[(p - arg.ptr)..$]));
|
|
565 }
|
|
566 }
|
|
567 if (global.errors)
|
|
568 {
|
|
569 fatal();
|
|
570 }
|
|
571 if (files.dim == 0)
|
|
572 { usage();
|
|
573 return EXIT_FAILURE;
|
|
574 }
|
|
575
|
|
576 if (!setdebuglib)
|
|
577 global.params.debuglibname = global.params.defaultlibname;
|
|
578
|
|
579 version (TARGET_OSX) {
|
|
580 global.params.pic = 1;
|
|
581 }
|
|
582
|
|
583 if (global.params.release)
|
|
584 { global.params.useInvariants = 0;
|
|
585 global.params.useIn = 0;
|
|
586 global.params.useOut = 0;
|
|
587 global.params.useAssert = 0;
|
|
588 global.params.useArrayBounds = 0;
|
|
589 global.params.useSwitchError = 0;
|
|
590 }
|
|
591
|
|
592 if (global.params.run)
|
|
593 global.params.quiet = 1;
|
|
594
|
|
595 if (global.params.useUnitTests)
|
|
596 global.params.useAssert = 1;
|
|
597
|
|
598 if (!global.params.obj || global.params.lib)
|
|
599 global.params.link = 0;
|
|
600
|
|
601 if (global.params.link)
|
|
602 {
|
|
603 global.params.exefile = global.params.objname;
|
|
604 global.params.oneobj = 1;
|
|
605 if (global.params.objname)
|
|
606 {
|
|
607 /* Use this to name the one object file with the same
|
|
608 * name as the exe file.
|
|
609 */
|
|
610 global.params.objname = FileName.forceExt(global.params.objname, global.obj_ext).toChars();
|
|
611
|
|
612 /* If output directory is given, use that path rather than
|
|
613 * the exe file path.
|
|
614 */
|
|
615 if (global.params.objdir)
|
|
616 {
|
|
617 string name = FileName.name(global.params.objname);
|
|
618 global.params.objname = FileName.combine(global.params.objdir, name);
|
|
619 }
|
|
620 }
|
|
621 }
|
|
622 else if (global.params.lib)
|
|
623 {
|
|
624 global.params.libname = global.params.objname;
|
|
625 global.params.objname = null;
|
|
626
|
|
627 // Haven't investigated handling these options with multiobj
|
|
628 if (!global.params.cov && !global.params.trace)
|
|
629 global.params.multiobj = 1;
|
|
630 }
|
|
631 else if (global.params.run)
|
|
632 {
|
|
633 error("flags conflict with -run");
|
|
634 fatal();
|
|
635 }
|
|
636 else
|
|
637 {
|
|
638 if (global.params.objname && files.dim > 1)
|
|
639 {
|
|
640 global.params.oneobj = 1;
|
|
641 //error("multiple source files, but only one .obj name");
|
|
642 //fatal();
|
|
643 }
|
|
644 }
|
|
645 if (global.params.isX86_64)
|
|
646 {
|
|
647 VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86_64");
|
|
648 VersionCondition.addPredefinedGlobalIdent("X86_64");
|
|
649 VersionCondition.addPredefinedGlobalIdent("D_LP64");
|
|
650 version (TARGET_WINDOS) {
|
|
651 VersionCondition.addPredefinedGlobalIdent("Win64");
|
|
652 }
|
|
653 }
|
|
654 else
|
|
655 {
|
|
656 VersionCondition.addPredefinedGlobalIdent("D_InlineAsm");
|
|
657 VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86");
|
|
658 VersionCondition.addPredefinedGlobalIdent("X86");
|
|
659 version (TARGET_WINDOS) {
|
|
660 VersionCondition.addPredefinedGlobalIdent("Win32");
|
|
661 }
|
|
662 }
|
|
663 if (global.params.doDocComments)
|
|
664 VersionCondition.addPredefinedGlobalIdent("D_Ddoc");
|
|
665 if (global.params.cov)
|
|
666 VersionCondition.addPredefinedGlobalIdent("D_Coverage");
|
|
667 if (global.params.pic)
|
|
668 VersionCondition.addPredefinedGlobalIdent("D_PIC");
|
|
669 version (DMDV2) {
|
|
670 if (global.params.useUnitTests)
|
|
671 VersionCondition.addPredefinedGlobalIdent("unittest");
|
|
672 }
|
|
673
|
|
674 // Initialization
|
|
675 Type.init();
|
|
676 Id.initialize();
|
|
677 Module.init();
|
|
678 initPrecedence();
|
|
679
|
|
680 backend_init();
|
|
681
|
|
682 //printf("%d source files\n",files.dim);
|
|
683
|
|
684 // Build import search path
|
|
685 if (global.params.imppath)
|
|
686 {
|
|
687 for (int i = 0; i < global.params.imppath.dim; i++)
|
|
688 {
|
|
689 string path = (cast(String)global.params.imppath.data[i]).str;
|
|
690 string[] a = FileName.splitPath(path);
|
|
691
|
|
692 global.path ~= a;
|
|
693 }
|
|
694 }
|
|
695
|
|
696 // Build string import search path
|
|
697 if (global.params.fileImppath)
|
|
698 {
|
|
699 for (int i = 0; i < global.params.fileImppath.dim; i++)
|
|
700 {
|
|
701 string path = (cast(String)global.params.fileImppath.data[i]).str;
|
|
702 string[] a = FileName.splitPath(path);
|
|
703
|
|
704 global.filePath ~= a;
|
|
705 }
|
|
706 }
|
|
707
|
|
708 // Create Modules
|
|
709 Array modules = new Array();
|
|
710 modules.reserve(files.dim);
|
|
711 int firstmodule = 1;
|
|
712 for (int i = 0; i < files.dim; i++)
|
|
713 {
|
|
714 string ext;
|
|
715 string name;
|
|
716
|
|
717 String s = cast(String) files.data[i];
|
|
718 string mp = s.str;
|
|
719
|
|
720 version (_WIN32) {
|
|
721 char[] copy = null;
|
|
722 // Convert / to \ so linker will work
|
|
723 foreach (j, c; mp)
|
|
724 {
|
|
725 if (c == '/') {
|
|
726 if (copy is null) copy = mp.dup;
|
|
727 copy[j] = '\\';
|
|
728 }
|
|
729 }
|
|
730
|
|
731 if (copy !is null) mp = assumeUnique(copy);
|
|
732 }
|
|
733 string p = mp;
|
|
734
|
|
735 p = FileName.name(p); // strip path
|
|
736 ext = FileName.ext(p);
|
|
737
|
|
738 if (ext.length != 0)
|
|
739 { /* Deduce what to do with a file based on its extension
|
|
740 */
|
|
741 if (FileName.equals(ext, global.obj_ext))
|
|
742 {
|
|
743 global.params.objfiles.push(files.data[i]);
|
|
744 libmodules.push(files.data[i]);
|
|
745 continue;
|
|
746 }
|
|
747
|
|
748 if (FileName.equals(ext, global.lib_ext))
|
|
749 {
|
|
750 global.params.libfiles.push(files.data[i]);
|
|
751 libmodules.push(files.data[i]);
|
|
752 continue;
|
|
753 }
|
|
754
|
|
755 if (ext == global.ddoc_ext)
|
|
756 {
|
|
757 global.params.ddocfiles.push(files.data[i]);
|
|
758 continue;
|
|
759 }
|
|
760
|
|
761 version (TARGET_WINDOS) {
|
|
762 if (FileName.equals(ext, "res"))
|
|
763 {
|
|
764 global.params.resfile = (cast(immutable(char)*)files.data[i])[0..0]; /// !!!
|
|
765 continue;
|
|
766 }
|
|
767
|
|
768 if (FileName.equals(ext, "def"))
|
|
769 {
|
|
770 global.params.deffile = (cast(immutable(char)*)files.data[i])[0..0];
|
|
771 continue;
|
|
772 }
|
|
773
|
|
774 if (FileName.equals(ext, "exe"))
|
|
775 {
|
|
776 assert(0); // should have already been handled
|
|
777 }
|
|
778 }
|
|
779
|
|
780 /* Examine extension to see if it is a valid
|
|
781 * D source file extension
|
|
782 */
|
|
783 if (FileName.equals(ext, global.mars_ext) ||
|
|
784 FileName.equals(ext, global.hdr_ext) ||
|
|
785 FileName.equals(ext, "dd") ||
|
|
786 FileName.equals(ext, "htm") ||
|
|
787 FileName.equals(ext, "html") ||
|
|
788 FileName.equals(ext, "xhtml"))
|
|
789 {
|
|
790 immutable(char)* e = ext.ptr;
|
|
791 e--; // skip onto '.'
|
|
792 assert(*e == '.');
|
|
793
|
|
794 immutable(char)* n = p.ptr;
|
|
795
|
|
796 name = n[0..(e-n)]; // strip extension
|
|
797
|
|
798 if (name.length == 0 || name == ".." || name == ".")
|
|
799 {
|
|
800 Linvalid:
|
|
801 error("invalid file name '%s'", (cast(String)files.data[i]).str);
|
|
802 fatal();
|
|
803 }
|
|
804 }
|
|
805 else
|
|
806 { error("unrecognized file extension %s\n", ext);
|
|
807 fatal();
|
|
808 }
|
|
809 }
|
|
810 else
|
|
811 {
|
|
812 name = p;
|
|
813 if (!*name)
|
|
814 goto Linvalid;
|
|
815 }
|
|
816
|
|
817 /* At this point, name is the D source file name stripped of
|
|
818 * its path and extension.
|
|
819 */
|
|
820
|
|
821 Identifier id = new Identifier(name, TOK.TOKreserved);
|
|
822 m = new Module((cast(String) files.data[i]).str, id, global.params.doDocComments, global.params.doHdrGeneration);
|
|
823 modules.push(cast(void*)m);
|
|
824
|
|
825 if (firstmodule)
|
|
826 {
|
|
827 global.params.objfiles.push(cast(void*)m.objfile.name);
|
|
828 firstmodule = 0;
|
|
829 }
|
|
830 }
|
|
831
|
|
832 // Read files
|
|
833 //version = ASYNCREAD;
|
|
834 version (ASYNCREAD) {
|
|
835 // Multi threaded
|
|
836 AsyncRead *aw = AsyncRead.create(modules.dim);
|
|
837 for (i = 0; i < modules.dim; i++)
|
|
838 {
|
|
839 m = cast(Module *)modules.data[i];
|
|
840 aw.addFile(m.srcfile);
|
|
841 }
|
|
842 aw.start();
|
|
843 } else {
|
|
844 // Single threaded
|
|
845 for (int i = 0; i < modules.dim; i++)
|
|
846 {
|
|
847 m = cast(Module)modules.data[i];
|
|
848 m.read(Loc(0));
|
|
849 }
|
|
850 }
|
|
851
|
|
852 // Parse files
|
|
853 int anydocfiles = 0;
|
|
854 for (int i = 0; i < modules.dim; i++)
|
|
855 {
|
|
856 m = cast(Module)modules.data[i];
|
|
857 if (global.params.verbose)
|
|
858 writef("parse %s\n", m.toChars());
|
|
859 if (!Module.rootModule)
|
|
860 Module.rootModule = m;
|
|
861 m.importedFrom = m;
|
|
862 if (!global.params.oneobj || i == 0 || m.isDocFile)
|
|
863 m.deleteObjFile();
|
|
864 version (ASYNCREAD) {
|
|
865 if (aw.read(i))
|
|
866 {
|
|
867 error("cannot read file %s", m.srcfile.name.toChars());
|
|
868 }
|
|
869 }
|
|
870
|
|
871 //while (loop) {}
|
|
872 m.parse();
|
|
873 if (m.isDocFile)
|
|
874 {
|
|
875 anydocfiles = 1;
|
|
876 m.gendocfile();
|
|
877
|
|
878 // Remove m from list of modules
|
|
879 modules.remove(i);
|
|
880 i--;
|
|
881
|
|
882 // Remove m's object file from list of object files
|
|
883 for (int j = 0; j < global.params.objfiles.dim; j++)
|
|
884 {
|
|
885 if (m.objfile.name.str == (cast(FileName)global.params.objfiles.data[j]).str)
|
|
886 {
|
|
887 global.params.objfiles.remove(j);
|
|
888 break;
|
|
889 }
|
|
890 }
|
|
891
|
|
892 if (global.params.objfiles.dim == 0)
|
|
893 global.params.link = 0;
|
|
894 }
|
|
895 }
|
|
896 version (ASYNCREAD) {
|
|
897 AsyncRead.dispose(aw);
|
|
898 }
|
|
899
|
|
900 if (anydocfiles && modules.dim &&
|
|
901 (global.params.oneobj || global.params.objname))
|
|
902 {
|
|
903 error("conflicting Ddoc and obj generation options");
|
|
904 fatal();
|
|
905 }
|
|
906 if (global.errors)
|
|
907 fatal();
|
|
908 version (_DH) {
|
|
909 if (global.params.doHdrGeneration)
|
|
910 {
|
|
911 /* Generate 'header' import files.
|
|
912 * Since 'header' import files must be independent of command
|
|
913 * line switches and what else is imported, they are generated
|
|
914 * before any semantic analysis.
|
|
915 */
|
|
916 for (i = 0; i < modules.dim; i++)
|
|
917 {
|
|
918 m = cast(Module *)modules.data[i];
|
|
919 if (global.params.verbose)
|
|
920 writef("import %s\n", m.toChars());
|
|
921 m.genhdrfile();
|
|
922 }
|
|
923 }
|
|
924 if (global.errors)
|
|
925 fatal();
|
|
926 }
|
|
927
|
|
928 // Do semantic analysis
|
|
929 for (int i = 0; i < modules.dim; i++)
|
|
930 {
|
|
931 m = cast(Module)modules.data[i];
|
|
932 if (global.params.verbose)
|
|
933 writef("semantic %s\n", m.toChars());
|
|
934 m.semantic();
|
|
935 }
|
|
936 if (global.errors)
|
|
937 fatal();
|
|
938
|
|
939 // Do pass 2 semantic analysis
|
|
940 for (int i = 0; i < modules.dim; i++)
|
|
941 {
|
|
942 m = cast(Module)modules.data[i];
|
|
943 if (global.params.verbose)
|
|
944 writef("semantic2 %s\n", m.toChars());
|
|
945 m.semantic2();
|
|
946 }
|
|
947 if (global.errors)
|
|
948 fatal();
|
|
949
|
|
950 // Do pass 3 semantic analysis
|
|
951 for (int i = 0; i < modules.dim; i++)
|
|
952 {
|
|
953 m = cast(Module)modules.data[i];
|
|
954 if (global.params.verbose)
|
|
955 writef("semantic3 %s\n", m.toChars());
|
|
956 m.semantic3();
|
|
957 }
|
|
958 if (global.errors)
|
|
959 fatal();
|
|
960
|
|
961 if (global.params.moduleDeps !is null)
|
|
962 {
|
|
963 assert(global.params.moduleDepsFile !is null);
|
|
964
|
|
965 File deps = new File(global.params.moduleDepsFile);
|
|
966 OutBuffer ob = global.params.moduleDeps;
|
|
967 deps.setbuffer(cast(void*)ob.data, ob.offset);
|
|
968 deps.writev();
|
|
969 }
|
|
970
|
|
971
|
|
972 // Scan for functions to inline
|
|
973 if (global.params.useInline)
|
|
974 {
|
|
975 /* The problem with useArrayBounds and useAssert is that the
|
|
976 * module being linked to may not have generated them, so if
|
|
977 * we inline functions from those modules, the symbols for them will
|
|
978 * not be found at link time.
|
|
979 */
|
|
980 if (!global.params.useArrayBounds && !global.params.useAssert)
|
|
981 {
|
|
982 // Do pass 3 semantic analysis on all imported modules,
|
|
983 // since otherwise functions in them cannot be inlined
|
|
984 for (int i = 0; i < Module.amodules.dim; i++)
|
|
985 {
|
|
986 m = cast(Module)Module.amodules.data[i];
|
|
987 if (global.params.verbose)
|
|
988 writef("semantic3 %s\n", m.toChars());
|
|
989 m.semantic3();
|
|
990 }
|
|
991 if (global.errors)
|
|
992 fatal();
|
|
993 }
|
|
994
|
|
995 for (int i = 0; i < modules.dim; i++)
|
|
996 {
|
|
997 m = cast(Module)modules.data[i];
|
|
998 if (global.params.verbose)
|
|
999 writef("inline scan %s\n", m.toChars());
|
|
1000
|
|
1001 m.inlineScan();
|
|
1002 }
|
|
1003 }
|
|
1004 if (global.errors)
|
|
1005 fatal();
|
|
1006
|
|
1007 Library library = null;
|
|
1008 if (global.params.lib)
|
|
1009 {
|
|
1010 library = new Library();
|
|
1011 library.setFilename(global.params.objdir, global.params.libname);
|
|
1012
|
|
1013 // Add input object and input library files to output library
|
|
1014 for (int i = 0; i < libmodules.dim; i++)
|
|
1015 {
|
|
1016 string p = (cast(String)libmodules.data[i]).str;
|
|
1017 library.addObject(p, null, 0);
|
|
1018 }
|
|
1019 }
|
|
1020
|
|
1021 // Generate output files
|
|
1022 if (global.params.oneobj)
|
|
1023 {
|
|
1024 for (int i = 0; i < modules.dim; i++)
|
|
1025 {
|
|
1026 m = cast(Module)modules.data[i];
|
|
1027 if (global.params.verbose)
|
|
1028 writef("code %s\n", m.toChars());
|
|
1029 if (i == 0)
|
|
1030 obj_start(cast(char*)toStringz(m.srcfile.toChars()));
|
|
1031 m.genobjfile(0);
|
|
1032 if (!global.errors && global.params.doDocComments)
|
|
1033 m.gendocfile();
|
|
1034 }
|
|
1035 if (!global.errors && modules.dim)
|
|
1036 {
|
|
1037 obj_end(library, (cast(Module)modules.data[0]).objfile);
|
|
1038 }
|
|
1039 }
|
|
1040 else
|
|
1041 {
|
|
1042 for (int i = 0; i < modules.dim; i++)
|
|
1043 {
|
|
1044 m = cast(Module)modules.data[i];
|
|
1045 if (global.params.verbose)
|
|
1046 writef("code %s\n", m.toChars());
|
|
1047 if (global.params.obj)
|
|
1048 {
|
|
1049 obj_start(cast(char*)toStringz(m.srcfile.toChars()));
|
|
1050 m.genobjfile(global.params.multiobj);
|
|
1051 obj_end(library, m.objfile);
|
|
1052 obj_write_deferred(library);
|
|
1053 }
|
|
1054 if (global.errors)
|
|
1055 {
|
|
1056 if (!global.params.lib)
|
|
1057 m.deleteObjFile();
|
|
1058 }
|
|
1059 else
|
|
1060 {
|
|
1061 if (global.params.doDocComments)
|
|
1062 m.gendocfile();
|
|
1063 }
|
|
1064 }
|
|
1065 }
|
|
1066
|
|
1067 if (global.params.lib && !global.errors)
|
|
1068 library.write();
|
|
1069
|
|
1070 backend_term();
|
|
1071 if (global.errors)
|
|
1072 fatal();
|
|
1073
|
|
1074 if (!global.params.objfiles.dim)
|
|
1075 {
|
|
1076 if (global.params.link)
|
|
1077 error("no object files to link");
|
|
1078 }
|
|
1079 else
|
|
1080 {
|
|
1081 if (global.params.link)
|
|
1082 status = runLINK();
|
|
1083
|
|
1084 if (global.params.run)
|
|
1085 {
|
|
1086 if (!status)
|
|
1087 {
|
|
1088 status = runProgram();
|
|
1089
|
|
1090 /* Delete .obj files and .exe file
|
|
1091 */
|
|
1092 for (int i = 0; i < modules.dim; i++)
|
|
1093 {
|
|
1094 m = cast(Module)modules.data[i];
|
|
1095 m.deleteObjFile();
|
|
1096 if (global.params.oneobj)
|
|
1097 break;
|
|
1098 }
|
|
1099 deleteExeFile();
|
|
1100 }
|
|
1101 }
|
|
1102 }
|
|
1103
|
|
1104 return status;
|
|
1105 } |