Fixed some lexing problems with DOS line-endings
[delight/core.git] / dmd2 / mars.c
blob69bf9be66560da12c2889bf600dbd7a80ac05cd9
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <ctype.h>
14 #include <assert.h>
15 #include <limits.h>
17 #ifndef IN_GCC
18 #if _WIN32
19 #include <windows.h>
20 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
21 #endif
23 #if __DMC__
24 #include <dos.h>
25 #endif
27 #if linux
28 #include <errno.h>
29 #endif
30 #endif
32 #include "mem.h"
33 #include "root.h"
35 #include "mars.h"
36 #include "module.h"
37 #include "mtype.h"
38 #include "id.h"
39 #include "cond.h"
40 #include "expression.h"
41 #include "lexer.h"
42 #include "lib.h"
44 void browse(const char *url);
45 void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
47 void obj_start(char *srcfile);
48 void obj_end(Library *library, File *objfile);
50 Global global;
52 Global::Global()
54 mars_ext = "d";
55 sym_ext = "d";
56 hdr_ext = "di";
57 doc_ext = "html";
58 ddoc_ext = "ddoc";
60 #ifndef IN_GCC
61 #if _WIN32
62 obj_ext = "obj";
63 #elif linux
64 obj_ext = "o";
65 #else
66 #error "fix this"
67 #endif
68 #else
69 obj_ext = "o";
70 #endif
72 #ifndef IN_GCC
73 #if _WIN32
74 lib_ext = "lib";
75 #elif linux
76 lib_ext = "a";
77 #else
78 #error "fix this"
79 #endif
80 #else
81 lib_ext = "a";
82 #endif
84 copyright = "Copyright (c) 1999-2008 by Digital Mars";
85 written = "written by Walter Bright";
86 version = "v2.014";
87 global.structalign = 8;
89 memset(&params, 0, sizeof(Param));
92 char *Loc::toChars()
94 OutBuffer buf;
95 char *p;
97 if (filename)
99 buf.printf("%s", filename);
102 if (linnum)
103 #ifndef IN_GCC
104 buf.printf("(%d)", linnum);
105 #else
106 buf.printf(":%u", linnum);
107 #endif
108 buf.writeByte(0);
109 return (char *)buf.extractData();
112 Loc::Loc(Module *mod, unsigned linnum)
114 this->linnum = linnum;
115 this->filename = mod ? mod->srcfile->toChars() : NULL;
118 /**************************************
119 * Print error message and exit.
122 void error(Loc loc, const char *format, ...)
124 va_list ap;
125 va_start(ap, format);
126 verror(loc, format, ap);
127 va_end( ap );
130 void verror(Loc loc, const char *format, va_list ap)
132 if (!global.gag)
134 char *p = loc.toChars();
136 if (*p)
137 fprintf(stdmsg, "%s: ", p);
138 mem.free(p);
140 fprintf(stdmsg, "Error: ");
141 vfprintf(stdmsg, format, ap);
142 fprintf(stdmsg, "\n");
143 fflush(stdmsg);
144 //halt();
146 global.errors++;
149 /***************************************
150 * Call this after printing out fatal error messages to clean up and exit
151 * the compiler.
154 void fatal()
156 #if 0
157 halt();
158 #endif
159 exit(EXIT_FAILURE);
162 /**************************************
163 * Try to stop forgetting to remove the breakpoints from
164 * release builds.
166 void halt()
168 #ifdef DEBUG
169 *(char*)0=0;
170 #endif
173 #ifndef IN_GCC
175 extern void backend_init();
176 extern void backend_term();
178 void usage()
180 printf("Digital Mars D Compiler %s\n%s %s\n",
181 global.version, global.copyright, global.written);
182 printf("\
183 Documentation: http://www.digitalmars.com/d/2.0/index.html\n\
184 Usage:\n\
185 dmd files.d ... { -switch }\n\
187 files.d D source files\n%s\
188 -c do not link\n\
189 -cov do code coverage analysis\n\
190 -D generate documentation\n\
191 -Dddocdir write documentation file to docdir directory\n\
192 -Dffilename write documentation file to filename\n\
193 -d allow deprecated features\n\
194 -debug compile in debug code\n\
195 -debug=level compile in debug code <= level\n\
196 -debug=ident compile in debug code identified by ident\n\
197 -debuglib=name set symbolic debug library to name\n\
198 -defaultlib=name set default library to name\n\
199 -g add symbolic debug info\n\
200 -gc add symbolic debug info, pretend to be C\n\
201 -H generate 'header' file\n\
202 -Hdhdrdir write 'header' file to hdrdir directory\n\
203 -Hffilename write 'header' file to filename\n\
204 --help print help\n\
205 -Ipath where to look for imports\n\
206 -ignore ignore unsupported pragmas\n\
207 -inline do function inlining\n\
208 -Jpath where to look for string imports\n\
209 -Llinkerflag pass linkerflag to link\n\
210 -lib generate library rather than object files\n\
211 -man open web browser on manual page\n\
212 -nofloat do not emit reference to floating point\n\
213 -O optimize\n\
214 -o- do not write object file\n\
215 -odobjdir write object & library files to directory objdir\n\
216 -offilename name output file to filename\n\
217 -op do not strip paths from source file\n\
218 -profile profile runtime performance of generated code\n\
219 -quiet suppress unnecessary messages\n\
220 -release compile release version\n\
221 -run srcfile args... run resulting program, passing args\n\
222 -unittest compile in unit tests\n\
223 -v verbose\n\
224 -version=level compile in version code >= level\n\
225 -version=ident compile in version code identified by ident\n\
226 -w enable warnings\n\
228 #if WIN32
229 " @cmdfile read arguments from cmdfile\n"
230 #else
232 #endif
236 int main(int argc, char *argv[])
238 int i;
239 Array files;
240 Array libmodules;
241 char *p;
242 Module *m;
243 int status = EXIT_SUCCESS;
244 int argcstart = argc;
246 // Check for malformed input
247 if (argc < 1 || !argv)
249 Largs:
250 error("missing or null command line arguments");
251 fatal();
253 for (i = 0; i < argc; i++)
255 if (!argv[i])
256 goto Largs;
259 #if __DMC__ // DMC unique support for response files
260 if (response_expand(&argc,&argv)) // expand response files
261 error("can't open response file");
262 #endif
264 files.reserve(argc - 1);
266 // Set default values
267 global.params.argv0 = argv[0];
268 global.params.link = 1;
269 global.params.useAssert = 1;
270 global.params.useInvariants = 1;
271 global.params.useIn = 1;
272 global.params.useOut = 1;
273 global.params.useArrayBounds = 1;
274 global.params.useSwitchError = 1;
275 global.params.useInline = 0;
276 global.params.obj = 1;
277 global.params.Dversion = 2;
278 global.params.quiet = 1;
280 global.params.linkswitches = new Array();
281 global.params.libfiles = new Array();
282 global.params.objfiles = new Array();
283 global.params.ddocfiles = new Array();
285 #if _WIN32
286 global.params.defaultlibname = "phobos";
287 #elif linux
288 global.params.defaultlibname = "phobos2";
289 #endif
290 global.params.debuglibname = global.params.defaultlibname;
292 // Predefine version identifiers
293 VersionCondition::addPredefinedGlobalIdent("DigitalMars");
294 #if _WIN32
295 VersionCondition::addPredefinedGlobalIdent("Windows");
296 VersionCondition::addPredefinedGlobalIdent("Win32");
297 global.params.isWindows = 1;
298 #endif
299 #if linux
300 VersionCondition::addPredefinedGlobalIdent("linux");
301 global.params.isLinux = 1;
302 #endif /* linux */
303 VersionCondition::addPredefinedGlobalIdent("X86");
304 VersionCondition::addPredefinedGlobalIdent("LittleEndian");
305 //VersionCondition::addPredefinedGlobalIdent("D_Bits");
306 VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
307 VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
308 #if V2
309 VersionCondition::addPredefinedGlobalIdent("D_Version2");
310 #endif
311 VersionCondition::addPredefinedGlobalIdent("all");
313 #if _WIN32
314 inifile(argv[0], "sc.ini");
315 #endif
316 #if linux
317 inifile(argv[0], "dmd.conf");
318 #endif
319 getenv_setargv("DFLAGS", &argc, &argv);
321 #if 0
322 for (i = 0; i < argc; i++)
324 printf("argv[%d] = '%s'\n", i, argv[i]);
326 #endif
328 for (i = 1; i < argc; i++)
330 p = argv[i];
331 if (*p == '-')
333 if (strcmp(p + 1, "d") == 0)
334 global.params.useDeprecated = 1;
335 else if (strcmp(p + 1, "c") == 0)
336 global.params.link = 0;
337 else if (strcmp(p + 1, "cov") == 0)
338 global.params.cov = 1;
339 else if (strcmp(p + 1, "fPIC") == 0)
340 global.params.pic = 1;
341 else if (strcmp(p + 1, "multiobj") == 0)
342 global.params.multiobj = 1;
343 else if (strcmp(p + 1, "g") == 0)
344 global.params.symdebug = 1;
345 else if (strcmp(p + 1, "gc") == 0)
346 global.params.symdebug = 2;
347 else if (strcmp(p + 1, "gt") == 0)
348 { error("use -profile instead of -gt\n");
349 global.params.trace = 1;
351 else if (strcmp(p + 1, "profile") == 0)
352 global.params.trace = 1;
353 else if (strcmp(p + 1, "v") == 0)
354 global.params.verbose = 1;
355 else if (strcmp(p + 1, "v1") == 0)
357 #if V1
358 global.params.Dversion = 1;
359 #else
360 error("use DMD 1.0 series compilers for -v1 switch");
361 break;
362 #endif
364 else if (strcmp(p + 1, "w") == 0)
365 global.params.warnings = 1;
366 else if (strcmp(p + 1, "O") == 0)
367 global.params.optimize = 1;
368 else if (p[1] == 'o')
370 switch (p[2])
372 case '-':
373 global.params.obj = 0;
374 break;
376 case 'd':
377 if (!p[3])
378 goto Lnoarg;
379 global.params.objdir = p + 3;
380 break;
382 case 'f':
383 if (!p[3])
384 goto Lnoarg;
385 global.params.objname = p + 3;
386 break;
388 case 'p':
389 if (p[3])
390 goto Lerror;
391 global.params.preservePaths = 1;
392 break;
394 case 0:
395 error("-o no longer supported, use -of or -od");
396 break;
398 default:
399 goto Lerror;
402 else if (p[1] == 'D')
403 { global.params.doDocComments = 1;
404 switch (p[2])
406 case 'd':
407 if (!p[3])
408 goto Lnoarg;
409 global.params.docdir = p + 3;
410 break;
411 case 'f':
412 if (!p[3])
413 goto Lnoarg;
414 global.params.docname = p + 3;
415 break;
417 case 0:
418 break;
420 default:
421 goto Lerror;
424 #ifdef _DH
425 else if (p[1] == 'H')
426 { global.params.doHdrGeneration = 1;
427 switch (p[2])
429 case 'd':
430 if (!p[3])
431 goto Lnoarg;
432 global.params.hdrdir = p + 3;
433 break;
435 case 'f':
436 if (!p[3])
437 goto Lnoarg;
438 global.params.hdrname = p + 3;
439 break;
441 case 0:
442 break;
444 default:
445 goto Lerror;
448 #endif
449 else if (strcmp(p + 1, "ignore") == 0)
450 global.params.ignoreUnsupportedPragmas = 1;
451 else if (strcmp(p + 1, "inline") == 0)
452 global.params.useInline = 1;
453 else if (strcmp(p + 1, "lib") == 0)
454 global.params.lib = 1;
455 else if (strcmp(p + 1, "nofloat") == 0)
456 global.params.nofloat = 1;
457 else if (strcmp(p + 1, "quiet") == 0)
458 global.params.quiet = 1;
459 else if (strcmp(p + 1, "release") == 0)
460 global.params.release = 1;
461 else if (strcmp(p + 1, "unittest") == 0)
462 global.params.useUnitTests = 1;
463 else if (p[1] == 'I')
465 if (!global.params.imppath)
466 global.params.imppath = new Array();
467 global.params.imppath->push(p + 2);
469 else if (p[1] == 'J')
471 if (!global.params.fileImppath)
472 global.params.fileImppath = new Array();
473 global.params.fileImppath->push(p + 2);
475 else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
477 // Parse:
478 // -debug
479 // -debug=number
480 // -debug=identifier
481 if (p[6] == '=')
483 if (isdigit(p[7]))
484 { long level;
486 errno = 0;
487 level = strtol(p + 7, &p, 10);
488 if (*p || errno || level > INT_MAX)
489 goto Lerror;
490 DebugCondition::setGlobalLevel((int)level);
492 else if (Lexer::isValidIdentifier(p + 7))
493 DebugCondition::addGlobalIdent(p + 7);
494 else
495 goto Lerror;
497 else if (p[6])
498 goto Lerror;
499 else
500 global.params.debuglevel = 1;
502 else if (memcmp(p + 1, "version", 5) == 0)
504 // Parse:
505 // -version=number
506 // -version=identifier
507 if (p[8] == '=')
509 if (isdigit(p[9]))
510 { long level;
512 errno = 0;
513 level = strtol(p + 9, &p, 10);
514 if (*p || errno || level > INT_MAX)
515 goto Lerror;
516 VersionCondition::setGlobalLevel((int)level);
518 else if (Lexer::isValidIdentifier(p + 9))
519 VersionCondition::addGlobalIdent(p + 9);
520 else
521 goto Lerror;
523 else
524 goto Lerror;
526 else if (strcmp(p + 1, "-b") == 0)
527 global.params.debugb = 1;
528 else if (strcmp(p + 1, "-c") == 0)
529 global.params.debugc = 1;
530 else if (strcmp(p + 1, "-f") == 0)
531 global.params.debugf = 1;
532 else if (strcmp(p + 1, "-help") == 0)
533 { usage();
534 exit(EXIT_SUCCESS);
536 else if (strcmp(p + 1, "-r") == 0)
537 global.params.debugr = 1;
538 else if (strcmp(p + 1, "-x") == 0)
539 global.params.debugx = 1;
540 else if (strcmp(p + 1, "-y") == 0)
541 global.params.debugy = 1;
542 else if (p[1] == 'L')
544 global.params.linkswitches->push(p + 2);
546 else if (memcmp(p + 1, "defaultlib=", 11) == 0)
548 global.params.defaultlibname = p + 1 + 11;
550 else if (memcmp(p + 1, "debuglib=", 9) == 0)
552 global.params.debuglibname = p + 1 + 9;
554 else if (memcmp(p + 1, "man", 3) == 0)
556 #if _WIN32
557 #if V1
558 browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
559 #else
560 browse("http://www.digitalmars.com/d/2.0/dmd-windows.html");
561 #endif
562 #endif
563 #if linux
564 #if V1
565 browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
566 #else
567 browse("http://www.digitalmars.com/d/2.0/dmd-linux.html");
568 #endif
569 #endif
570 exit(EXIT_SUCCESS);
572 else if (strcmp(p + 1, "run") == 0)
573 { global.params.run = 1;
574 global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
575 if (global.params.runargs_length)
577 files.push(argv[i + 1]);
578 global.params.runargs = &argv[i + 2];
579 i += global.params.runargs_length;
580 global.params.runargs_length--;
582 else
583 { global.params.run = 0;
584 goto Lnoarg;
587 else
589 Lerror:
590 error("unrecognized switch '%s'", argv[i]);
591 continue;
593 Lnoarg:
594 error("argument expected for switch '%s'", argv[i]);
595 continue;
598 else
600 #if !TARGET_LINUX
601 char *ext = FileName::ext(p);
602 if (ext && stricmp(ext, "exe") == 0)
604 global.params.objname = p;
605 continue;
607 #endif
608 files.push(p);
611 if (global.errors)
613 fatal();
615 if (files.dim == 0)
616 { usage();
617 return EXIT_FAILURE;
620 if (global.params.release)
621 { global.params.useInvariants = 0;
622 global.params.useIn = 0;
623 global.params.useOut = 0;
624 global.params.useAssert = 0;
625 global.params.useArrayBounds = 0;
626 global.params.useSwitchError = 0;
629 if (global.params.run)
630 global.params.quiet = 1;
632 if (global.params.useUnitTests)
633 global.params.useAssert = 1;
635 if (!global.params.obj || global.params.lib)
636 global.params.link = 0;
638 if (global.params.link)
640 global.params.exefile = global.params.objname;
641 global.params.oneobj = 1;
642 if (global.params.objname)
644 /* Use this to name the one object file with the same
645 * name as the exe file.
647 global.params.objname = FileName::forceExt(global.params.objname, global.obj_ext)->toChars();
649 /* If output directory is given, use that path rather than
650 * the exe file path.
652 if (global.params.objdir)
653 { char *name = FileName::name(global.params.objname);
654 global.params.objname = FileName::combine(global.params.objdir, name);
658 else if (global.params.lib)
660 global.params.libname = global.params.objname;
661 global.params.objname = NULL;
663 // Haven't investigated handling these options with multiobj
664 if (!global.params.cov && !global.params.trace)
665 global.params.multiobj = 1;
667 else if (global.params.run)
669 error("flags conflict with -run");
670 fatal();
672 else
674 if (global.params.objname && files.dim > 1)
676 global.params.oneobj = 1;
677 //error("multiple source files, but only one .obj name");
678 //fatal();
681 if (global.params.cov)
682 VersionCondition::addPredefinedGlobalIdent("D_Coverage");
683 #if V2
684 if (global.params.useUnitTests)
685 VersionCondition::addPredefinedGlobalIdent("unittest");
686 #endif
688 // Initialization
689 Type::init();
690 Id::initialize();
691 Module::init();
692 initPrecedence();
694 backend_init();
696 //printf("%d source files\n",files.dim);
698 // Build import search path
699 if (global.params.imppath)
701 for (i = 0; i < global.params.imppath->dim; i++)
703 char *path = (char *)global.params.imppath->data[i];
704 Array *a = FileName::splitPath(path);
706 if (a)
708 if (!global.path)
709 global.path = new Array();
710 global.path->append(a);
715 // Build string import search path
716 if (global.params.fileImppath)
718 for (i = 0; i < global.params.fileImppath->dim; i++)
720 char *path = (char *)global.params.fileImppath->data[i];
721 Array *a = FileName::splitPath(path);
723 if (a)
725 if (!global.filePath)
726 global.filePath = new Array();
727 global.filePath->append(a);
732 // Create Modules
733 Array modules;
734 modules.reserve(files.dim);
735 int firstmodule = 1;
736 for (i = 0; i < files.dim; i++)
738 char *ext;
739 char *name;
741 p = (char *) files.data[i];
743 #if _WIN32
744 // Convert / to \ so linker will work
745 for (int i = 0; p[i]; i++)
747 if (p[i] == '/')
748 p[i] = '\\';
750 #endif
752 p = FileName::name(p); // strip path
753 ext = FileName::ext(p);
754 if (ext)
755 { /* Deduce what to do with a file based on its extension
757 #if TARGET_LINUX
758 if (strcmp(ext, global.obj_ext) == 0)
759 #else
760 if (stricmp(ext, global.obj_ext) == 0)
761 #endif
763 global.params.objfiles->push(files.data[i]);
764 libmodules.push(files.data[i]);
765 continue;
768 #if TARGET_LINUX
769 if (strcmp(ext, global.lib_ext) == 0)
770 #else
771 if (stricmp(ext, global.lib_ext) == 0)
772 #endif
774 global.params.libfiles->push(files.data[i]);
775 libmodules.push(files.data[i]);
776 continue;
779 if (strcmp(ext, global.ddoc_ext) == 0)
781 global.params.ddocfiles->push(files.data[i]);
782 continue;
785 #if !TARGET_LINUX
786 if (stricmp(ext, "res") == 0)
788 global.params.resfile = (char *)files.data[i];
789 continue;
792 if (stricmp(ext, "def") == 0)
794 global.params.deffile = (char *)files.data[i];
795 continue;
798 if (stricmp(ext, "exe") == 0)
800 assert(0); // should have already been handled
802 #endif
804 /* Examine extension to see if it is a valid
805 * D source file extension
807 if (stricmp(ext, global.mars_ext) == 0 ||
808 stricmp(ext, "dd") == 0 ||
809 stricmp(ext, "htm") == 0 ||
810 stricmp(ext, "html") == 0 ||
811 stricmp(ext, "xhtml") == 0)
813 ext--; // skip onto '.'
814 assert(*ext == '.');
815 name = (char *)mem.malloc((ext - p) + 1);
816 memcpy(name, p, ext - p);
817 name[ext - p] = 0; // strip extension
819 if (name[0] == 0 ||
820 strcmp(name, "..") == 0 ||
821 strcmp(name, ".") == 0)
823 Linvalid:
824 error("invalid file name '%s'", (char *)files.data[i]);
825 fatal();
828 else
829 { error("unrecognized file extension %s\n", ext);
830 fatal();
833 else
834 { name = p;
835 if (!*name)
836 goto Linvalid;
839 /* At this point, name is the D source file name stripped of
840 * its path and extension.
843 Identifier *id = new Identifier(name, 0);
844 m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration);
845 modules.push(m);
847 if (firstmodule)
848 { global.params.objfiles->push(m->objfile->name->str);
849 firstmodule = 0;
853 #if _WIN32
854 __try
856 #endif
857 // Read files, parse them
858 int anydocfiles = 0;
859 for (i = 0; i < modules.dim; i++)
861 m = (Module *)modules.data[i];
862 if (global.params.verbose)
863 printf("parse %s\n", m->toChars());
864 if (!Module::rootModule)
865 Module::rootModule = m;
866 m->importedFrom = m;
867 if (!global.params.oneobj || i == 0 || m->isDocFile)
868 m->deleteObjFile();
869 m->read(0);
870 m->parse();
871 if (m->isDocFile)
873 anydocfiles = 1;
874 m->gendocfile();
876 // Remove m from list of modules
877 modules.remove(i);
878 i--;
880 // Remove m's object file from list of object files
881 for (int j = 0; j < global.params.objfiles->dim; j++)
883 if (m->objfile->name->str == global.params.objfiles->data[j])
885 global.params.objfiles->remove(j);
886 break;
890 if (global.params.objfiles->dim == 0)
891 global.params.link = 0;
894 if (anydocfiles && modules.dim &&
895 (global.params.oneobj || global.params.objname))
897 error("conflicting Ddoc and obj generation options");
898 fatal();
900 if (global.errors)
901 fatal();
902 #ifdef _DH
903 if (global.params.doHdrGeneration)
905 /* Generate 'header' import files.
906 * Since 'header' import files must be independent of command
907 * line switches and what else is imported, they are generated
908 * before any semantic analysis.
910 for (i = 0; i < modules.dim; i++)
912 m = (Module *)modules.data[i];
913 if (global.params.verbose)
914 printf("import %s\n", m->toChars());
915 m->genhdrfile();
918 if (global.errors)
919 fatal();
920 #endif
922 // Do semantic analysis
923 for (i = 0; i < modules.dim; i++)
925 m = (Module *)modules.data[i];
926 if (global.params.verbose)
927 printf("semantic %s\n", m->toChars());
928 m->semantic();
930 if (global.errors)
931 fatal();
933 // Do pass 2 semantic analysis
934 for (i = 0; i < modules.dim; i++)
936 m = (Module *)modules.data[i];
937 if (global.params.verbose)
938 printf("semantic2 %s\n", m->toChars());
939 m->semantic2();
941 if (global.errors)
942 fatal();
944 // Do pass 3 semantic analysis
945 for (i = 0; i < modules.dim; i++)
947 m = (Module *)modules.data[i];
948 if (global.params.verbose)
949 printf("semantic3 %s\n", m->toChars());
950 m->semantic3();
952 if (global.errors)
953 fatal();
955 // Scan for functions to inline
956 if (global.params.useInline)
958 /* The problem with useArrayBounds and useAssert is that the
959 * module being linked to may not have generated them, so if
960 * we inline functions from those modules, the symbols for them will
961 * not be found at link time.
963 if (!global.params.useArrayBounds && !global.params.useAssert)
965 // Do pass 3 semantic analysis on all imported modules,
966 // since otherwise functions in them cannot be inlined
967 for (i = 0; i < Module::amodules.dim; i++)
969 m = (Module *)Module::amodules.data[i];
970 if (global.params.verbose)
971 printf("semantic3 %s\n", m->toChars());
972 m->semantic3();
974 if (global.errors)
975 fatal();
978 for (i = 0; i < modules.dim; i++)
980 m = (Module *)modules.data[i];
981 if (global.params.verbose)
982 printf("inline scan %s\n", m->toChars());
983 m->inlineScan();
986 if (global.errors)
987 fatal();
989 Library *library = NULL;
990 if (global.params.lib)
992 library = new Library();
993 library->setFilename(global.params.objdir, global.params.libname);
995 // Add input object and input library files to output library
996 for (int i = 0; i < libmodules.dim; i++)
998 char *p = (char *)libmodules.data[i];
999 library->addObject(p, NULL, 0);
1003 // Generate output files
1004 if (global.params.oneobj)
1006 for (i = 0; i < modules.dim; i++)
1008 m = (Module *)modules.data[i];
1009 if (global.params.verbose)
1010 printf("code %s\n", m->toChars());
1011 if (i == 0)
1012 obj_start(m->srcfile->toChars());
1013 m->genobjfile(0);
1014 if (!global.errors && global.params.doDocComments)
1015 m->gendocfile();
1017 if (!global.errors && modules.dim)
1019 obj_end(library, ((Module *)modules.data[0])->objfile);
1022 else
1024 for (i = 0; i < modules.dim; i++)
1026 m = (Module *)modules.data[i];
1027 if (global.params.verbose)
1028 printf("code %s\n", m->toChars());
1029 if (global.params.obj)
1030 { obj_start(m->srcfile->toChars());
1031 m->genobjfile(global.params.multiobj);
1032 obj_end(library, m->objfile);
1033 obj_write_deferred(library);
1035 if (global.errors)
1037 if (!global.params.lib)
1038 m->deleteObjFile();
1040 else
1042 if (global.params.doDocComments)
1043 m->gendocfile();
1048 if (global.params.lib && !global.errors)
1049 library->write();
1051 #if _WIN32
1053 __except (__ehfilter(GetExceptionInformation()))
1055 printf("Stack overflow\n");
1056 fatal();
1058 #endif
1059 backend_term();
1060 if (global.errors)
1061 fatal();
1063 if (!global.params.objfiles->dim)
1065 if (global.params.link)
1066 error("no object files to link");
1068 else
1070 if (global.params.link)
1071 status = runLINK();
1073 if (global.params.run)
1075 if (!status)
1077 status = runProgram();
1079 /* Delete .obj files and .exe file
1081 for (i = 0; i < modules.dim; i++)
1083 Module *m = (Module *)modules.data[i];
1084 m->deleteObjFile();
1085 if (global.params.oneobj)
1086 break;
1088 deleteExeFile();
1093 return status;
1098 /***********************************
1099 * Parse and append contents of environment variable envvar
1100 * to argc and argv[].
1101 * The string is separated into arguments, processing \ and ".
1104 void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
1106 char *env;
1107 char *p;
1108 Array *argv;
1109 int argc;
1111 int wildcard; // do wildcard expansion
1112 int instring;
1113 int slash;
1114 char c;
1115 int j;
1117 env = getenv(envvar);
1118 if (!env)
1119 return;
1121 env = mem.strdup(env); // create our own writable copy
1123 argc = *pargc;
1124 argv = new Array();
1125 argv->setDim(argc);
1127 for (int i = 0; i < argc; i++)
1128 argv->data[i] = (void *)(*pargv)[i];
1130 j = 1; // leave argv[0] alone
1131 while (1)
1133 wildcard = 1;
1134 switch (*env)
1136 case ' ':
1137 case '\t':
1138 env++;
1139 break;
1141 case 0:
1142 goto Ldone;
1144 case '"':
1145 wildcard = 0;
1146 default:
1147 argv->push(env); // append
1148 //argv->insert(j, env); // insert at position j
1149 j++;
1150 argc++;
1151 p = env;
1152 slash = 0;
1153 instring = 0;
1154 c = 0;
1156 while (1)
1158 c = *env++;
1159 switch (c)
1161 case '"':
1162 p -= (slash >> 1);
1163 if (slash & 1)
1164 { p--;
1165 goto Laddc;
1167 instring ^= 1;
1168 slash = 0;
1169 continue;
1171 case ' ':
1172 case '\t':
1173 if (instring)
1174 goto Laddc;
1175 *p = 0;
1176 //if (wildcard)
1177 //wildcardexpand(); // not implemented
1178 break;
1180 case '\\':
1181 slash++;
1182 *p++ = c;
1183 continue;
1185 case 0:
1186 *p = 0;
1187 //if (wildcard)
1188 //wildcardexpand(); // not implemented
1189 goto Ldone;
1191 default:
1192 Laddc:
1193 slash = 0;
1194 *p++ = c;
1195 continue;
1197 break;
1202 Ldone:
1203 *pargc = argc;
1204 *pargv = (char **)argv->data;
1207 #if _WIN32
1209 long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep)
1211 //printf("%x\n", ep->ExceptionRecord->ExceptionCode);
1212 if (ep->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
1214 #ifndef DEBUG
1215 return EXCEPTION_EXECUTE_HANDLER;
1216 #endif
1218 return EXCEPTION_CONTINUE_SEARCH;
1221 #endif
1223 #endif