1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2011 by Digital Mars
4: // All Rights Reserved
5: // written by Walter Bright
6: // http://www.digitalmars.com
7: // http://www.dsource.org/projects/dmd/browser/trunk/src/mars.c
8: // License for redistribution is by either the Artistic License
9: // in artistic.txt, or the GNU General Public License in gnu.txt.
10: // See the included readme.txt for details.
11:
12: #include <stdio.h>
13: #include <stdlib.h>
14: #include <ctype.h>
15: static char __file__[] = __FILE__; /* for tassert.h */
16: #include "tassert.h"
17: #include <limits.h>
18:
19: #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
20: #include <errno.h>
21: #endif
22:
23: #include "rmem.h"
24: #include "root.h"
25: #include "async.h"
26:
27: #include "mars.h"
28: #include "module.h"
29: #include "mtype.h"
30: #include "id.h"
31: #include "cond.h"
32: #include "expression.h"
33: #include "lexer.h"
34: #include "lib.h"
35: #include "json.h"
36:
37: #if WINDOWS_SEH
38: #include <windows.h>
39: long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep);
40: #endif
41:
42:
43: int response_expand(int *pargc, char ***pargv);
44: void browse(const char *url);
45: void getenv_setargv(const char *envvar, int *pargc, char** *pargv);
46:
47: void obj_start(char *srcfile);
48: void obj_end(Library *library, File *objfile);
49:
50: Global global;
51:
52: Global::Global()
53: {
54: mars_ext = "d";
55: sym_ext = "d";
56: hdr_ext = "di";
57: doc_ext = "html";
58: ddoc_ext = "ddoc";
59: json_ext = "json";
60: map_ext = "map";
61:
62: #if TARGET_WINDOS
63: obj_ext = "obj";
64: #elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
65: obj_ext = "o";
66: #elif TARGET_NET
67: #else
68: #error "fix this"
69: #endif
70:
71: #if TARGET_WINDOS
72: lib_ext = "lib";
73: #elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
74: lib_ext = "a";
75: #elif TARGET_NET
76: #else
77: #error "fix this"
78: #endif
79:
80: #if TARGET_WINDOS
81: dll_ext = "dll";
82: #elif TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
83: dll_ext = "so";
84: #elif TARGET_OSX
85: dll_ext = "dylib";
86: #else
87: #error "fix this"
88: #endif
89:
90: copyright = "Copyright (c) 1999-2011 by Digital Mars";
91: written = "written by Walter Bright"
92: #if TARGET_NET
93: "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
94: #endif
95: ;
96: version = "v2.055";
97: global.structalign = 8;
98:
99: memset(¶ms, 0, sizeof(Param));
100: }
101:
102: char *Loc::toChars()
103: {
104: OutBuffer buf;
105: char *p;
warning C4101: 'p' : unreferenced local variable
106:
107: if (filename)
108: {
109: buf.printf("%s", filename);
110: }
111:
112: if (linnum)
113: buf.printf("(%d)", linnum);
114: buf.writeByte(0);
115: return (char *)buf.extractData();
116: }
117:
118: Loc::Loc(Module *mod, unsigned linnum)
119: {
120: this->linnum = linnum;
121: this->filename = mod ? mod->srcfile->toChars() : NULL;
122: }
123:
124: bool Loc::equals(const Loc& loc)
125: {
126: return linnum == loc.linnum && FileName::equals(filename, loc.filename);
127: }
128:
129: /**************************************
130: * Print error message and exit.
131: */
132:
133: void error(Loc loc, const char *format, ...)
134: {
135: va_list ap;
136: va_start(ap, format);
137: verror(loc, format, ap);
138: va_end( ap );
139: }
140:
141: void error(const char *filename, unsigned linnum, const char *format, ...)
142: { Loc loc;
143: loc.filename = (char *)filename;
144: loc.linnum = linnum;
145: va_list ap;
146: va_start(ap, format);
147: verror(loc, format, ap);
148: va_end( ap );
149: }
150:
151: void warning(Loc loc, const char *format, ...)
152: {
153: va_list ap;
154: va_start(ap, format);
155: vwarning(loc, format, ap);
156: va_end( ap );
157: }
158:
159: void verror(Loc loc, const char *format, va_list ap)
160: {
161: if (!global.gag)
162: {
163: char *p = loc.toChars();
164:
165: if (*p)
166: fprintf(stdmsg, "%s: ", p);
167: mem.free(p);
168:
169: fprintf(stdmsg, "Error: ");
170: #if _MSC_VER
171: // MS doesn't recognize %zu format
172: OutBuffer tmp;
173: tmp.vprintf(format, ap);
174: fprintf(stdmsg, "%s", tmp.toChars());
175: #else
176: vfprintf(stdmsg, format, ap);
177: #endif
178: fprintf(stdmsg, "\n");
179: fflush(stdmsg);
180: //halt();
181: }
182: global.errors++;
183: }
184:
185: void vwarning(Loc loc, const char *format, va_list ap)
186: {
187: if (global.params.warnings && !global.gag)
188: {
189: char *p = loc.toChars();
190:
191: if (*p)
192: fprintf(stdmsg, "%s: ", p);
193: mem.free(p);
194:
195: fprintf(stdmsg, "Warning: ");
196: #if _MSC_VER
197: // MS doesn't recognize %zu format
198: OutBuffer tmp;
199: tmp.vprintf(format, ap);
200: fprintf(stdmsg, "%s", tmp.toChars());
201: #else
202: vfprintf(stdmsg, format, ap);
203: #endif
204: fprintf(stdmsg, "\n");
205: fflush(stdmsg);
206: //halt();
207: if (global.params.warnings == 1)
208: global.warnings++; // warnings don't count if gagged
209: }
210: }
211:
212: /***************************************
213: * Call this after printing out fatal error messages to clean up and exit
214: * the compiler.
215: */
216:
217: void fatal()
218: {
219: #if 0
220: halt();
221: #endif
222: exit(EXIT_FAILURE);
223: }
224:
225: /**************************************
226: * Try to stop forgetting to remove the breakpoints from
227: * release builds.
228: */
229: void halt()
230: {
231: #ifdef DEBUG
232: *(char*)0=0;
233: #endif
234: }
235:
236: extern void backend_init();
237: extern void backend_term();
238:
239: void usage()
240: {
241: #if TARGET_LINUX
242: const char fpic[] ="\
243: -fPIC generate position independent code\n\
244: ";
245: #else
246: const char fpic[] = "";
247: #endif
248: printf("DMD%s D Compiler %s\n%s %s\n",
249: sizeof(size_t) == 4 ? "32" : "64",
250: global.version, global.copyright, global.written);
251: printf("\
252: Documentation: http://www.digitalmars.com/d/2.0/index.html\n\
253: Usage:\n\
254: dmd files.d ... { -switch }\n\
255: \n\
256: files.d D source files\n\
257: @cmdfile read arguments from cmdfile\n\
258: -c do not link\n\
259: -cov do code coverage analysis\n\
260: -D generate documentation\n\
261: -Dddocdir write documentation file to docdir directory\n\
262: -Dffilename write documentation file to filename\n\
263: -d allow deprecated features\n\
264: -debug compile in debug code\n\
265: -debug=level compile in debug code <= level\n\
266: -debug=ident compile in debug code identified by ident\n\
267: -debuglib=name set symbolic debug library to name\n\
268: -defaultlib=name set default library to name\n\
269: -deps=filename write module dependencies to filename\n%s"
270: #if TARGET_OSX
271: " -dylib generate dylib\n"
272: #endif
273: " -g add symbolic debug info\n\
274: -gc add symbolic debug info, pretend to be C\n\
275: -H generate 'header' file\n\
276: -Hddirectory write 'header' file to directory\n\
277: -Hffilename write 'header' file to filename\n\
278: --help print help\n\
279: -Ipath where to look for imports\n\
280: -ignore ignore unsupported pragmas\n\
281: -property enforce property syntax\n\
282: -inline do function inlining\n\
283: -Jpath where to look for string imports\n\
284: -Llinkerflag pass linkerflag to link\n\
285: -lib generate library rather than object files\n\
286: -man open web browser on manual page\n\
287: -map generate linker .map file\n\
288: -noboundscheck turns off array bounds checking for all functions\n\
289: -nofloat do not emit reference to floating point\n\
290: -O optimize\n\
291: -o- do not write object file\n\
292: -odobjdir write object & library files to directory objdir\n\
293: -offilename name output file to filename\n\
294: -op do not strip paths from source file\n\
295: -profile profile runtime performance of generated code\n\
296: -quiet suppress unnecessary messages\n\
297: -release compile release version\n\
298: -run srcfile args... run resulting program, passing args\n\
299: -unittest compile in unit tests\n\
300: -v verbose\n\
301: -version=level compile in version code >= level\n\
302: -version=ident compile in version code identified by ident\n\
303: -vtls list all variables going into thread local storage\n\
304: -w enable warnings\n\
305: -wi enable informational warnings\n\
306: -X generate JSON file\n\
307: -Xffilename write JSON file to filename\n\
308: ", fpic);
309: }
310:
311: extern signed char tyalignsize[];
312:
313: int main(int argc, char *argv[])
314: {
315: int i;
316: Strings files;
317: Strings libmodules;
318: char *p;
319: Module *m;
320: int status = EXIT_SUCCESS;
321: int argcstart = argc;
322: int setdebuglib = 0;
323: char noboundscheck = 0;
324: const char *inifilename = NULL;
325:
326: #ifdef DEBUG
327: printf("DMD %s DEBUG\n", global.version);
328: #endif
329:
330: unittests();
331:
332: // Check for malformed input
333: if (argc < 1 || !argv)
334: {
335: Largs:
336: error("missing or null command line arguments");
337: fatal();
338: }
339: for (i = 0; i < argc; i++)
340: {
341: if (!argv[i])
warning C6011: Dereferencing NULL pointer 'argv': Lines: 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 330, 333, 335, 336, 337, 339, 341
342: goto Largs;
343: }
344:
345: if (response_expand(&argc,&argv)) // expand response files
346: error("can't open response file");
347:
348: files.reserve(argc - 1);
349:
350: // Set default values
351: global.params.argv0 = argv[0];
352: global.params.link = 1;
353: global.params.useAssert = 1;
354: global.params.useInvariants = 1;
355: global.params.useIn = 1;
356: global.params.useOut = 1;
357: global.params.useArrayBounds = 2; // default to all functions
358: global.params.useSwitchError = 1;
359: global.params.useInline = 0;
360: global.params.obj = 1;
361: global.params.Dversion = 2;
362: global.params.quiet = 1;
363:
364: global.params.linkswitches = new Strings();
365: global.params.libfiles = new Strings();
366: global.params.objfiles = new Strings();
367: global.params.ddocfiles = new Strings();
368:
369: // Default to -m32 for 32 bit dmd, -m64 for 64 bit dmd
370: global.params.is64bit = (sizeof(size_t) == 8);
371:
372: #if TARGET_WINDOS
373: global.params.defaultlibname = "phobos";
374: #elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
375: global.params.defaultlibname = "phobos2";
376: #elif TARGET_NET
377: #else
378: #error "fix this"
379: #endif
380:
381: // Predefine version identifiers
382: VersionCondition::addPredefinedGlobalIdent("DigitalMars");
383:
384: #if TARGET_WINDOS
385: VersionCondition::addPredefinedGlobalIdent("Windows");
386: global.params.isWindows = 1;
387: #if TARGET_NET
388: // TARGET_NET macro is NOT mutually-exclusive with TARGET_WINDOS
389: VersionCondition::addPredefinedGlobalIdent("D_NET");
390: #endif
391: #elif TARGET_LINUX
392: VersionCondition::addPredefinedGlobalIdent("Posix");
393: VersionCondition::addPredefinedGlobalIdent("linux");
394: global.params.isLinux = 1;
395: #elif TARGET_OSX
396: VersionCondition::addPredefinedGlobalIdent("Posix");
397: VersionCondition::addPredefinedGlobalIdent("OSX");
398: global.params.isOSX = 1;
399:
400: // For legacy compatibility
401: VersionCondition::addPredefinedGlobalIdent("darwin");
402: #elif TARGET_FREEBSD
403: VersionCondition::addPredefinedGlobalIdent("Posix");
404: VersionCondition::addPredefinedGlobalIdent("FreeBSD");
405: global.params.isFreeBSD = 1;
406: #elif TARGET_OPENBSD
407: VersionCondition::addPredefinedGlobalIdent("Posix");
408: VersionCondition::addPredefinedGlobalIdent("OpenBSD");
409: global.params.isFreeBSD = 1;
410: #elif TARGET_SOLARIS
411: VersionCondition::addPredefinedGlobalIdent("Posix");
412: VersionCondition::addPredefinedGlobalIdent("Solaris");
413: global.params.isSolaris = 1;
414: #else
415: #error "fix this"
416: #endif
417:
418: VersionCondition::addPredefinedGlobalIdent("LittleEndian");
419: //VersionCondition::addPredefinedGlobalIdent("D_Bits");
420: #if DMDV2
421: VersionCondition::addPredefinedGlobalIdent("D_Version2");
422: #endif
423: VersionCondition::addPredefinedGlobalIdent("all");
424:
425: #if _WIN32
426: inifilename = inifile(argv[0], "sc.ini");
427: #elif linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
428: inifilename = inifile(argv[0], "dmd.conf");
429: #else
430: #error "fix this"
431: #endif
432: getenv_setargv("DFLAGS", &argc, &argv);
433:
434: #if 0
435: for (i = 0; i < argc; i++)
436: {
437: printf("argv[%d] = '%s'\n", i, argv[i]);
438: }
439: #endif
440:
441: for (i = 1; i < argc; i++)
442: {
443: p = argv[i];
444: if (*p == '-')
445: {
446: if (strcmp(p + 1, "d") == 0)
447: global.params.useDeprecated = 1;
448: else if (strcmp(p + 1, "c") == 0)
449: global.params.link = 0;
450: else if (strcmp(p + 1, "cov") == 0)
451: global.params.cov = 1;
452: #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
453: else if (strcmp(p + 1, "fPIC") == 0)
454: global.params.pic = 1;
455: #endif
456: #if TARGET_OSX
457: else if (strcmp(p + 1, "dylib") == 0)
458: global.params.dll = 1;
459: #endif
460: else if (strcmp(p + 1, "map") == 0)
461: global.params.map = 1;
462: else if (strcmp(p + 1, "multiobj") == 0)
463: global.params.multiobj = 1;
464: else if (strcmp(p + 1, "g") == 0)
465: global.params.symdebug = 1;
466: else if (strcmp(p + 1, "gc") == 0)
467: global.params.symdebug = 2;
468: else if (strcmp(p + 1, "gt") == 0)
469: { error("use -profile instead of -gt\n");
470: global.params.trace = 1;
471: }
472: else if (strcmp(p + 1, "m32") == 0)
473: global.params.is64bit = 0;
474: else if (strcmp(p + 1, "m64") == 0)
475: global.params.is64bit = 1;
476: else if (strcmp(p + 1, "profile") == 0)
477: global.params.trace = 1;
478: else if (strcmp(p + 1, "v") == 0)
479: global.params.verbose = 1;
480: #if DMDV2
481: else if (strcmp(p + 1, "vtls") == 0)
482: global.params.vtls = 1;
483: #endif
484: else if (strcmp(p + 1, "v1") == 0)
485: {
486: #if DMDV1
487: global.params.Dversion = 1;
488: #else
489: error("use DMD 1.0 series compilers for -v1 switch");
490: break;
491: #endif
492: }
493: else if (strcmp(p + 1, "w") == 0)
494: global.params.warnings = 1;
495: else if (strcmp(p + 1, "wi") == 0)
496: global.params.warnings = 2;
497: else if (strcmp(p + 1, "O") == 0)
498: global.params.optimize = 1;
499: else if (p[1] == 'o')
500: {
501: switch (p[2])
502: {
503: case '-':
504: global.params.obj = 0;
505: break;
506:
507: case 'd':
508: if (!p[3])
509: goto Lnoarg;
510: global.params.objdir = p + 3;
511: break;
512:
513: case 'f':
514: if (!p[3])
515: goto Lnoarg;
516: global.params.objname = p + 3;
517: break;
518:
519: case 'p':
520: if (p[3])
521: goto Lerror;
522: global.params.preservePaths = 1;
523: break;
524:
525: case 0:
526: error("-o no longer supported, use -of or -od");
527: break;
528:
529: default:
530: goto Lerror;
531: }
532: }
533: else if (p[1] == 'D')
534: { global.params.doDocComments = 1;
535: switch (p[2])
536: {
537: case 'd':
538: if (!p[3])
539: goto Lnoarg;
540: global.params.docdir = p + 3;
541: break;
542: case 'f':
543: if (!p[3])
544: goto Lnoarg;
545: global.params.docname = p + 3;
546: break;
547:
548: case 0:
549: break;
550:
551: default:
552: goto Lerror;
553: }
554: }
555: else if (p[1] == 'H')
556: { global.params.doHdrGeneration = 1;
557: switch (p[2])
558: {
559: case 'd':
560: if (!p[3])
561: goto Lnoarg;
562: global.params.hdrdir = p + 3;
563: break;
564:
565: case 'f':
566: if (!p[3])
567: goto Lnoarg;
568: global.params.hdrname = p + 3;
569: break;
570:
571: case 0:
572: break;
573:
574: default:
575: goto Lerror;
576: }
577: }
578: else if (p[1] == 'X')
579: { global.params.doXGeneration = 1;
580: switch (p[2])
581: {
582: case 'f':
583: if (!p[3])
584: goto Lnoarg;
585: global.params.xfilename = p + 3;
586: break;
587:
588: case 0:
589: break;
590:
591: default:
592: goto Lerror;
593: }
594: }
595: else if (strcmp(p + 1, "ignore") == 0)
596: global.params.ignoreUnsupportedPragmas = 1;
597: else if (strcmp(p + 1, "property") == 0)
598: global.params.enforcePropertySyntax = 1;
599: else if (strcmp(p + 1, "inline") == 0)
600: global.params.useInline = 1;
601: else if (strcmp(p + 1, "lib") == 0)
602: global.params.lib = 1;
603: else if (strcmp(p + 1, "nofloat") == 0)
604: global.params.nofloat = 1;
605: else if (strcmp(p + 1, "quiet") == 0)
606: global.params.quiet = 1;
607: else if (strcmp(p + 1, "release") == 0)
608: global.params.release = 1;
609: #if DMDV2
610: else if (strcmp(p + 1, "noboundscheck") == 0)
611: noboundscheck = 1;
612: #endif
613: else if (strcmp(p + 1, "unittest") == 0)
614: global.params.useUnitTests = 1;
615: else if (p[1] == 'I')
616: {
617: if (!global.params.imppath)
618: global.params.imppath = new Strings();
619: global.params.imppath->push(p + 2);
620: }
621: else if (p[1] == 'J')
622: {
623: if (!global.params.fileImppath)
624: global.params.fileImppath = new Strings();
625: global.params.fileImppath->push(p + 2);
626: }
627: else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
628: {
629: // Parse:
630: // -debug
631: // -debug=number
632: // -debug=identifier
633: if (p[6] == '=')
634: {
635: if (isdigit(p[7]))
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'isdigit'
636: { long level;
637:
638: errno = 0;
639: level = strtol(p + 7, &p, 10);
640: if (*p || errno || level > INT_MAX)
641: goto Lerror;
642: DebugCondition::setGlobalLevel((int)level);
643: }
644: else if (Lexer::isValidIdentifier(p + 7))
645: DebugCondition::addGlobalIdent(p + 7);
646: else
647: goto Lerror;
648: }
649: else if (p[6])
650: goto Lerror;
651: else
652: global.params.debuglevel = 1;
653: }
654: else if (memcmp(p + 1, "version", 5) == 0)
655: {
656: // Parse:
657: // -version=number
658: // -version=identifier
659: if (p[8] == '=')
660: {
661: if (isdigit(p[9]))
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'isdigit'
662: { long level;
663:
664: errno = 0;
665: level = strtol(p + 9, &p, 10);
666: if (*p || errno || level > INT_MAX)
667: goto Lerror;
668: VersionCondition::setGlobalLevel((int)level);
669: }
670: else if (Lexer::isValidIdentifier(p + 9))
671: VersionCondition::addGlobalIdent(p + 9);
672: else
673: goto Lerror;
674: }
675: else
676: goto Lerror;
677: }
678: else if (strcmp(p + 1, "-b") == 0)
679: global.params.debugb = 1;
680: else if (strcmp(p + 1, "-c") == 0)
681: global.params.debugc = 1;
682: else if (strcmp(p + 1, "-f") == 0)
683: global.params.debugf = 1;
684: else if (strcmp(p + 1, "-help") == 0)
685: { usage();
686: exit(EXIT_SUCCESS);
687: }
688: else if (strcmp(p + 1, "-r") == 0)
689: global.params.debugr = 1;
690: else if (strcmp(p + 1, "-x") == 0)
691: global.params.debugx = 1;
692: else if (strcmp(p + 1, "-y") == 0)
693: global.params.debugy = 1;
694: else if (p[1] == 'L')
695: {
696: global.params.linkswitches->push(p + 2);
697: }
698: else if (memcmp(p + 1, "defaultlib=", 11) == 0)
699: {
700: global.params.defaultlibname = p + 1 + 11;
701: }
702: else if (memcmp(p + 1, "debuglib=", 9) == 0)
703: {
704: setdebuglib = 1;
705: global.params.debuglibname = p + 1 + 9;
706: }
707: else if (memcmp(p + 1, "deps=", 5) == 0)
708: {
709: global.params.moduleDepsFile = p + 1 + 5;
710: if (!global.params.moduleDepsFile[0])
711: goto Lnoarg;
712: global.params.moduleDeps = new OutBuffer;
713: }
714: else if (memcmp(p + 1, "man", 3) == 0)
715: {
716: #if _WIN32
717: #if DMDV1
718: browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
719: #else
720: browse("http://www.digitalmars.com/d/2.0/dmd-windows.html");
721: #endif
722: #endif
723: #if linux
724: #if DMDV1
725: browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
726: #else
727: browse("http://www.digitalmars.com/d/2.0/dmd-linux.html");
728: #endif
729: #endif
730: #if __APPLE__
731: #if DMDV1
732: browse("http://www.digitalmars.com/d/1.0/dmd-osx.html");
733: #else
734: browse("http://www.digitalmars.com/d/2.0/dmd-osx.html");
735: #endif
736: #endif
737: #if __FreeBSD__
738: #if DMDV1
739: browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html");
740: #else
741: browse("http://www.digitalmars.com/d/2.0/dmd-freebsd.html");
742: #endif
743: #endif
744: #if __OpenBSD__
745: #if DMDV1
746: browse("http://www.digitalmars.com/d/1.0/dmd-openbsd.html");
747: #else
748: browse("http://www.digitalmars.com/d/2.0/dmd-openbsd.html");
749: #endif
750: #endif
751: exit(EXIT_SUCCESS);
752: }
753: else if (strcmp(p + 1, "run") == 0)
754: { global.params.run = 1;
755: global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
756: if (global.params.runargs_length)
757: {
758: files.push(argv[i + 1]);
759: global.params.runargs = &argv[i + 2];
760: i += global.params.runargs_length;
761: global.params.runargs_length--;
762: }
763: else
764: { global.params.run = 0;
765: goto Lnoarg;
766: }
767: }
768: else
769: {
770: Lerror:
771: error("unrecognized switch '%s'", argv[i]);
772: continue;
773:
774: Lnoarg:
775: error("argument expected for switch '%s'", argv[i]);
776: continue;
777: }
778: }
779: else
780: {
781: #if TARGET_WINDOS
782: char *ext = FileName::ext(p);
783: if (ext && FileName::compare(ext, "exe") == 0)
784: {
785: global.params.objname = p;
786: continue;
787: }
788: #endif
789: files.push(p);
790: }
791: }
792: if (global.errors)
793: {
794: fatal();
795: }
796: if (files.dim == 0)
797: { usage();
798: return EXIT_FAILURE;
799: }
800:
801: if (!setdebuglib)
802: global.params.debuglibname = global.params.defaultlibname;
803:
804: #if TARGET_OSX
805: global.params.pic = 1;
806: #endif
807:
808: if (global.params.release)
809: { global.params.useInvariants = 0;
810: global.params.useIn = 0;
811: global.params.useOut = 0;
812: global.params.useAssert = 0;
813: global.params.useArrayBounds = 1;
814: global.params.useSwitchError = 0;
815: }
816: if (noboundscheck)
817: global.params.useArrayBounds = 0;
818:
819: if (global.params.run)
820: global.params.quiet = 1;
821:
822: if (global.params.useUnitTests)
823: global.params.useAssert = 1;
824:
825: if (!global.params.obj || global.params.lib)
826: global.params.link = 0;
827:
828: if (global.params.link)
829: {
830: global.params.exefile = global.params.objname;
831: global.params.oneobj = 1;
832: if (global.params.objname)
833: {
834: /* Use this to name the one object file with the same
835: * name as the exe file.
836: */
837: global.params.objname = FileName::forceExt(global.params.objname, global.obj_ext)->toChars();
838:
839: /* If output directory is given, use that path rather than
840: * the exe file path.
841: */
842: if (global.params.objdir)
843: { char *name = FileName::name(global.params.objname);
844: global.params.objname = FileName::combine(global.params.objdir, name);
845: }
846: }
847: }
848: else if (global.params.lib)
849: {
850: global.params.libname = global.params.objname;
851: global.params.objname = NULL;
852:
853: // Haven't investigated handling these options with multiobj
854: if (!global.params.cov && !global.params.trace
855: #if 0 && TARGET_WINDOS
856: /* multiobj causes class/struct debug info to be attached to init-data,
857: * but this will not be linked into the executable, so this info is lost.
858: * Bugzilla 4014
859: */
860: && !global.params.symdebug
861: #endif
862: )
863: global.params.multiobj = 1;
864: }
865: else if (global.params.run)
866: {
867: error("flags conflict with -run");
868: fatal();
869: }
870: else
871: {
872: if (global.params.objname && files.dim > 1)
873: {
874: global.params.oneobj = 1;
875: //error("multiple source files, but only one .obj name");
876: //fatal();
877: }
878: }
879: if (global.params.is64bit)
880: {
881: VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86_64");
882: VersionCondition::addPredefinedGlobalIdent("X86_64");
883: VersionCondition::addPredefinedGlobalIdent("D_LP64");
884: #if TARGET_WINDOS
885: VersionCondition::addPredefinedGlobalIdent("Win64");
886: #endif
887: }
888: else
889: {
890: VersionCondition::addPredefinedGlobalIdent("D_InlineAsm");
891: VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86");
892: VersionCondition::addPredefinedGlobalIdent("X86");
893: #if TARGET_WINDOS
894: VersionCondition::addPredefinedGlobalIdent("Win32");
895: #endif
896: }
897: if (global.params.doDocComments)
898: VersionCondition::addPredefinedGlobalIdent("D_Ddoc");
899: if (global.params.cov)
900: VersionCondition::addPredefinedGlobalIdent("D_Coverage");
901: if (global.params.pic)
902: VersionCondition::addPredefinedGlobalIdent("D_PIC");
903: #if DMDV2
904: if (global.params.useUnitTests)
905: VersionCondition::addPredefinedGlobalIdent("unittest");
906: #endif
907:
908: // Initialization
909: Type::init();
910: Id::initialize();
911: Module::init();
912: initPrecedence();
913:
914: backend_init();
915:
916: if (global.params.verbose)
917: { printf("binary %s\n", argv[0]);
918: printf("version %s\n", global.version);
919: printf("config %s\n", inifilename ? inifilename : "(none)");
920: }
921:
922: //printf("%d source files\n",files.dim);
923:
924: // Build import search path
925: if (global.params.imppath)
926: {
927: for (i = 0; i < global.params.imppath->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
928: {
929: char *path = global.params.imppath->tdata()[i];
930: Strings *a = FileName::splitPath(path);
931:
932: if (a)
933: {
934: if (!global.path)
935: global.path = new Strings();
936: global.path->append(a);
937: }
938: }
939: }
940:
941: // Build string import search path
942: if (global.params.fileImppath)
943: {
944: for (i = 0; i < global.params.fileImppath->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
945: {
946: char *path = global.params.fileImppath->tdata()[i];
947: Strings *a = FileName::splitPath(path);
948:
949: if (a)
950: {
951: if (!global.filePath)
952: global.filePath = new Strings();
953: global.filePath->append(a);
954: }
955: }
956: }
957:
958: // Create Modules
959: Modules modules;
960: modules.reserve(files.dim);
961: int firstmodule = 1;
962: for (i = 0; i < files.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
963: {
964: char *ext;
965: char *name;
966:
967: p = files.tdata()[i];
968:
969: #if _WIN32
970: // Convert / to \ so linker will work
971: for (int i = 0; p[i]; i++)
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '315' of 'c:\projects\extern\d\dmd\src\mars.c': Lines: 315
972: {
973: if (p[i] == '/')
974: p[i] = '\\';
975: }
976: #endif
977:
978: p = FileName::name(p); // strip path
979: ext = FileName::ext(p);
980: if (ext)
981: { /* Deduce what to do with a file based on its extension
982: */
983: if (FileName::equals(ext, global.obj_ext))
984: {
985: global.params.objfiles->push(files.tdata()[i]);
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
986: libmodules.push(files.tdata()[i]);
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
987: continue;
988: }
989:
990: if (FileName::equals(ext, global.lib_ext))
991: {
992: global.params.libfiles->push(files.tdata()[i]);
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
993: libmodules.push(files.tdata()[i]);
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
994: continue;
995: }
996:
997: if (strcmp(ext, global.ddoc_ext) == 0)
998: {
999: global.params.ddocfiles->push(files.tdata()[i]);
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
1000: continue;
1001: }
1002:
1003: if (FileName::equals(ext, global.json_ext))
1004: {
1005: global.params.doXGeneration = 1;
1006: global.params.xfilename = files.tdata()[i];
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
1007: continue;
1008: }
1009:
1010: if (FileName::equals(ext, global.map_ext))
1011: {
1012: global.params.mapfile = files.tdata()[i];
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
1013: continue;
1014: }
1015:
1016: #if TARGET_WINDOS
1017: if (FileName::equals(ext, "res"))
1018: {
1019: global.params.resfile = files.tdata()[i];
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
1020: continue;
1021: }
1022:
1023: if (FileName::equals(ext, "def"))
1024: {
1025: global.params.deffile = files.tdata()[i];
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
1026: continue;
1027: }
1028:
1029: if (FileName::equals(ext, "exe"))
1030: {
1031: assert(0); // should have already been handled
1032: }
1033: #endif
1034:
1035: /* Examine extension to see if it is a valid
1036: * D source file extension
1037: */
1038: if (FileName::equals(ext, global.mars_ext) ||
1039: FileName::equals(ext, global.hdr_ext) ||
1040: FileName::equals(ext, "dd") ||
1041: FileName::equals(ext, "htm") ||
1042: FileName::equals(ext, "html") ||
1043: FileName::equals(ext, "xhtml"))
1044: {
1045: ext--; // skip onto '.'
1046: assert(*ext == '.');
1047: name = (char *)mem.malloc((ext - p) + 1);
1048: memcpy(name, p, ext - p);
1049: name[ext - p] = 0; // strip extension
1050:
1051: if (name[0] == 0 ||
1052: strcmp(name, "..") == 0 ||
1053: strcmp(name, ".") == 0)
1054: {
1055: Linvalid:
1056: error("invalid file name '%s'", files.tdata()[i]);
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
1057: fatal();
1058: }
1059: }
1060: else
1061: { error("unrecognized file extension %s\n", ext);
1062: fatal();
1063: }
1064: }
1065: else
1066: { name = p;
1067: if (!*name)
1068: goto Linvalid;
1069: }
1070:
1071: /* At this point, name is the D source file name stripped of
1072: * its path and extension.
1073: */
1074:
1075: Identifier *id = Lexer::idPool(name);
1076: m = new Module(files.tdata()[i], id, global.params.doDocComments, global.params.doHdrGeneration);
warning C4258: 'i' : definition from the for loop is ignored; the definition from the enclosing scope is used
mars.c(971) : definition of 'i' ignored
mars.c(315) : definition of 'i' used
1077: modules.push(m);
1078:
1079: if (firstmodule)
1080: { global.params.objfiles->push(m->objfile->name->str);
1081: firstmodule = 0;
1082: }
1083: }
1084:
1085: #if WINDOWS_SEH
1086: __try
1087: {
1088: #endif
1089: // Read files
1090: #define ASYNCREAD 1
1091: #if ASYNCREAD
1092: // Multi threaded
1093: AsyncRead *aw = AsyncRead::create(modules.dim);
1094: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1095: {
1096: m = modules.tdata()[i];
1097: aw->addFile(m->srcfile);
1098: }
1099: aw->start();
1100: #else
1101: // Single threaded
1102: for (i = 0; i < modules.dim; i++)
1103: {
1104: m = modules.tdata()[i];
1105: m->read(0);
1106: }
1107: #endif
1108:
1109: // Parse files
1110: int anydocfiles = 0;
1111: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1112: {
1113: m = modules.tdata()[i];
1114: if (global.params.verbose)
1115: printf("parse %s\n", m->toChars());
1116: if (!Module::rootModule)
1117: Module::rootModule = m;
1118: m->importedFrom = m;
1119: if (!global.params.oneobj || i == 0 || m->isDocFile)
1120: m->deleteObjFile();
1121: #if ASYNCREAD
1122: if (aw->read(i))
1123: {
1124: error("cannot read file %s", m->srcfile->name->toChars());
1125: }
1126: #endif
1127: m->parse();
1128: if (m->isDocFile)
1129: {
1130: anydocfiles = 1;
1131: m->gendocfile();
1132:
1133: // Remove m from list of modules
1134: modules.remove(i);
1135: i--;
1136:
1137: // Remove m's object file from list of object files
1138: for (int j = 0; j < global.params.objfiles->dim; j++)
warning C4018: '<' : signed/unsigned mismatch
1139: {
1140: if (m->objfile->name->str == global.params.objfiles->tdata()[j])
1141: {
1142: global.params.objfiles->remove(j);
1143: break;
1144: }
1145: }
1146:
1147: if (global.params.objfiles->dim == 0)
1148: global.params.link = 0;
1149: }
1150: }
1151: #if ASYNCREAD
1152: AsyncRead::dispose(aw);
1153: #endif
1154:
1155: if (anydocfiles && modules.dim &&
1156: (global.params.oneobj || global.params.objname))
1157: {
1158: error("conflicting Ddoc and obj generation options");
1159: fatal();
1160: }
1161: if (global.errors)
1162: fatal();
1163: if (global.params.doHdrGeneration)
1164: {
1165: /* Generate 'header' import files.
1166: * Since 'header' import files must be independent of command
1167: * line switches and what else is imported, they are generated
1168: * before any semantic analysis.
1169: */
1170: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1171: {
1172: m = modules.tdata()[i];
1173: if (global.params.verbose)
1174: printf("import %s\n", m->toChars());
1175: m->genhdrfile();
1176: }
1177: }
1178: if (global.errors)
1179: fatal();
1180:
1181: // load all unconditional imports for better symbol resolving
1182: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1183: {
1184: m = modules.tdata()[i];
1185: if (global.params.verbose)
1186: printf("importall %s\n", m->toChars());
1187: m->importAll(0);
1188: }
1189: if (global.errors)
1190: fatal();
1191:
1192: // Do semantic analysis
1193: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1194: {
1195: m = modules.tdata()[i];
1196: if (global.params.verbose)
1197: printf("semantic %s\n", m->toChars());
1198: m->semantic();
1199: }
1200: if (global.errors)
1201: fatal();
1202:
1203: Module::dprogress = 1;
1204: Module::runDeferredSemantic();
1205:
1206: // Do pass 2 semantic analysis
1207: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1208: {
1209: m = modules.tdata()[i];
1210: if (global.params.verbose)
1211: printf("semantic2 %s\n", m->toChars());
1212: m->semantic2();
1213: }
1214: if (global.errors)
1215: fatal();
1216:
1217: // Do pass 3 semantic analysis
1218: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1219: {
1220: m = modules.tdata()[i];
1221: if (global.params.verbose)
1222: printf("semantic3 %s\n", m->toChars());
1223: m->semantic3();
1224: }
1225: if (global.errors)
1226: fatal();
1227:
1228: if (global.params.moduleDeps != NULL)
1229: {
1230: assert(global.params.moduleDepsFile != NULL);
1231:
1232: File deps(global.params.moduleDepsFile);
1233: OutBuffer* ob = global.params.moduleDeps;
1234: deps.setbuffer((void*)ob->data, ob->offset);
1235: deps.writev();
1236: }
1237:
1238:
1239: // Scan for functions to inline
1240: if (global.params.useInline)
1241: {
1242: /* The problem with useArrayBounds and useAssert is that the
1243: * module being linked to may not have generated them, so if
1244: * we inline functions from those modules, the symbols for them will
1245: * not be found at link time.
1246: */
1247: if (!global.params.useArrayBounds && !global.params.useAssert)
1248: {
1249: // Do pass 3 semantic analysis on all imported modules,
1250: // since otherwise functions in them cannot be inlined
1251: for (i = 0; i < Module::amodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1252: {
1253: m = Module::amodules.tdata()[i];
1254: if (global.params.verbose)
1255: printf("semantic3 %s\n", m->toChars());
1256: m->semantic3();
1257: }
1258: if (global.errors)
1259: fatal();
1260: }
1261:
1262: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1263: {
1264: m = modules.tdata()[i];
1265: if (global.params.verbose)
1266: printf("inline scan %s\n", m->toChars());
1267: m->inlineScan();
1268: }
1269: }
1270:
1271: // Do not attempt to generate output files if errors or warnings occurred
1272: if (global.errors || global.warnings)
1273: fatal();
1274:
1275: Library *library = NULL;
1276: if (global.params.lib)
1277: {
1278: library = new Library();
1279: library->setFilename(global.params.objdir, global.params.libname);
1280:
1281: // Add input object and input library files to output library
1282: for (int i = 0; i < libmodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '315' of 'c:\projects\extern\d\dmd\src\mars.c': Lines: 315
1283: {
1284: char *p = libmodules.tdata()[i];
warning C6246: Local declaration of 'p' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '318' of 'c:\projects\extern\d\dmd\src\mars.c': Lines: 318
1285: library->addObject(p, NULL, 0);
1286: }
1287: }
1288:
1289: // Generate output files
1290:
1291: if (global.params.doXGeneration)
1292: json_generate(&modules);
1293:
1294: if (global.params.oneobj)
1295: {
1296: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1297: {
1298: m = modules.tdata()[i];
1299: if (global.params.verbose)
1300: printf("code %s\n", m->toChars());
1301: if (i == 0)
1302: obj_start(m->srcfile->toChars());
1303: m->genobjfile(0);
1304: if (!global.errors && global.params.doDocComments)
1305: m->gendocfile();
1306: }
1307: if (!global.errors && modules.dim)
1308: {
1309: obj_end(library, modules.tdata()[0]->objfile);
1310: }
1311: }
1312: else
1313: {
1314: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1315: {
1316: m = modules.tdata()[i];
1317: if (global.params.verbose)
1318: printf("code %s\n", m->toChars());
1319: if (global.params.obj)
1320: { obj_start(m->srcfile->toChars());
1321: m->genobjfile(global.params.multiobj);
1322: obj_end(library, m->objfile);
1323: obj_write_deferred(library);
1324: }
1325: if (global.errors)
1326: {
1327: if (!global.params.lib)
1328: m->deleteObjFile();
1329: }
1330: else
1331: {
1332: if (global.params.doDocComments)
1333: m->gendocfile();
1334: }
1335: }
1336: }
1337:
1338: if (global.params.lib && !global.errors)
1339: library->write();
1340:
1341: #if WINDOWS_SEH
1342: }
1343: __except (__ehfilter(GetExceptionInformation()))
1344: {
1345: printf("Stack overflow\n");
1346: fatal();
1347: }
1348: #endif
1349: backend_term();
1350: if (global.errors)
1351: fatal();
1352:
1353: if (!global.params.objfiles->dim)
1354: {
1355: if (global.params.link)
1356: error("no object files to link");
1357: }
1358: else
1359: {
1360: if (global.params.link)
1361: status = runLINK();
1362:
1363: if (global.params.run)
1364: {
1365: if (!status)
1366: {
1367: status = runProgram();
1368:
1369: /* Delete .obj files and .exe file
1370: */
1371: for (i = 0; i < modules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1372: {
1373: Module *m = modules.tdata()[i];
warning C6246: Local declaration of 'm' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '319' of 'c:\projects\extern\d\dmd\src\mars.c': Lines: 319
1374: m->deleteObjFile();
1375: if (global.params.oneobj)
1376: break;
1377: }
1378: deleteExeFile();
1379: }
1380: }
1381: }
1382:
1383: return status;
1384: }
1385:
1386:
1387:
1388: /***********************************
1389: * Parse and append contents of environment variable envvar
1390: * to argc and argv[].
1391: * The string is separated into arguments, processing \ and ".
1392: */
1393:
1394: void getenv_setargv(const char *envvar, int *pargc, char** *pargv)
1395: {
1396: char *p;
1397:
1398: int instring;
1399: int slash;
1400: char c;
1401:
1402: char *env = getenv(envvar);
warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdlib.h(433) : see declaration of 'getenv'
1403: if (!env)
1404: return;
1405:
1406: env = mem.strdup(env); // create our own writable copy
1407:
1408: int argc = *pargc;
1409: Strings *argv = new Strings();
1410: argv->setDim(argc);
1411:
1412: for (int i = 0; i < argc; i++)
1413: argv->tdata()[i] = (*pargv)[i];
1414:
1415: int j = 1; // leave argv[0] alone
1416: while (1)
1417: {
1418: int wildcard = 1; // do wildcard expansion
1419: switch (*env)
1420: {
1421: case ' ':
1422: case '\t':
1423: env++;
1424: break;
1425:
1426: case 0:
1427: goto Ldone;
1428:
1429: case '"':
1430: wildcard = 0;
1431: default:
1432: argv->push(env); // append
1433: //argv->insert(j, env); // insert at position j
1434: j++;
1435: argc++;
1436: p = env;
1437: slash = 0;
1438: instring = 0;
1439: c = 0;
1440:
1441: while (1)
1442: {
1443: c = *env++;
1444: switch (c)
1445: {
1446: case '"':
1447: p -= (slash >> 1);
1448: if (slash & 1)
1449: { p--;
1450: goto Laddc;
1451: }
1452: instring ^= 1;
1453: slash = 0;
1454: continue;
1455:
1456: case ' ':
1457: case '\t':
1458: if (instring)
1459: goto Laddc;
1460: *p = 0;
1461: //if (wildcard)
1462: //wildcardexpand(); // not implemented
1463: break;
1464:
1465: case '\\':
1466: slash++;
1467: *p++ = c;
1468: continue;
1469:
1470: case 0:
1471: *p = 0;
1472: //if (wildcard)
1473: //wildcardexpand(); // not implemented
1474: goto Ldone;
1475:
1476: default:
1477: Laddc:
1478: slash = 0;
1479: *p++ = c;
1480: continue;
1481: }
1482: break;
1483: }
1484: }
1485: }
1486:
1487: Ldone:
1488: *pargc = argc;
1489: *pargv = argv->tdata();
1490: }
1491:
1492: #if WINDOWS_SEH
1493:
1494: long __cdecl __ehfilter(LPEXCEPTION_POINTERS ep)
1495: {
1496: //printf("%x\n", ep->ExceptionRecord->ExceptionCode);
1497: if (ep->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
1498: {
1499: #ifndef DEBUG
1500: return EXCEPTION_EXECUTE_HANDLER;
1501: #endif
1502: }
1503: return EXCEPTION_CONTINUE_SEARCH;
1504: }
1505:
1506: #endif
1507: