Mercurial > projects > ldc
annotate dmd/mars.c @ 284:70c370e97944 trunk
[svn r305] Started support for custom class allocators/deallocators. Allocators with more than one argument still need to be fixed.
Removed the LLVM stacktrace code from mars.c.
Moved the LLVM based default target detection code from mars.c to llvmhelpers.cpp.
author | lindquist |
---|---|
date | Sat, 21 Jun 2008 02:48:53 +0200 |
parents | a137ed004205 |
children | 297690b5d4a5 |
rev | line source |
---|---|
159 | 1 // Compiler implementation of the D programming language |
2 // Copyright (c) 1999-2008 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 #include <stdio.h> | |
11 #include <stdlib.h> | |
12 #include <ctype.h> | |
13 #include <assert.h> | |
14 #include <limits.h> | |
15 #include <string> | |
16 #include <cstdarg> | |
17 | |
18 #if __DMC__ | |
19 #include <dos.h> | |
20 #endif | |
21 | |
22 #if linux | |
23 #include <errno.h> | |
24 #endif | |
25 | |
26 #include "mem.h" | |
27 #include "root.h" | |
28 | |
29 #include "mars.h" | |
30 #include "module.h" | |
31 #include "mtype.h" | |
32 #include "id.h" | |
33 #include "cond.h" | |
34 #include "expression.h" | |
35 #include "lexer.h" | |
36 | |
37 #include "gen/logger.h" | |
277
90a8c798b0db
[svn r298] Eliminated the dmd/link.c source file entirely in favor of a llvm::sys based approach to the same functionality.
lindquist
parents:
276
diff
changeset
|
38 #include "gen/linker.h" |
159 | 39 |
40 void getenv_setargv(const char *envvar, int *pargc, char** *pargv); | |
41 | |
284
70c370e97944
[svn r305] Started support for custom class allocators/deallocators. Allocators with more than one argument still need to be fixed.
lindquist
parents:
279
diff
changeset
|
42 // llvmdc |
70c370e97944
[svn r305] Started support for custom class allocators/deallocators. Allocators with more than one argument still need to be fixed.
lindquist
parents:
279
diff
changeset
|
43 void findDefaultTarget(); |
70c370e97944
[svn r305] Started support for custom class allocators/deallocators. Allocators with more than one argument still need to be fixed.
lindquist
parents:
279
diff
changeset
|
44 |
159 | 45 Global global; |
46 | |
47 Global::Global() | |
48 { | |
49 mars_ext = "d"; | |
50 sym_ext = "d"; | |
51 hdr_ext = "di"; | |
52 doc_ext = "html"; | |
53 ddoc_ext = "ddoc"; | |
54 | |
55 #if IN_LLVM | |
56 obj_ext = "bc"; | |
57 ll_ext = "ll"; | |
58 bc_ext = "bc"; | |
59 nativeobj_ext = "o"; | |
60 #elif _WIN32 | |
61 obj_ext = "obj"; | |
62 #elif linux | |
63 obj_ext = "o"; | |
64 #else | |
65 #error "fix this" | |
66 #endif | |
67 | |
68 copyright = "Copyright (c) 1999-2008 by Digital Mars and Tomas Lindquist Olsen"; | |
69 written = "written by Walter Bright and Tomas Lindquist Olsen"; | |
70 version = "v1.029"; | |
71 llvmdc_version = "0.1"; | |
72 global.structalign = 8; | |
73 | |
74 memset(¶ms, 0, sizeof(Param)); | |
75 } | |
76 | |
77 char *Loc::toChars() const | |
78 { | |
79 OutBuffer buf; | |
80 char *p; | |
81 | |
82 if (filename) | |
83 { | |
84 buf.printf("%s", filename); | |
85 } | |
86 | |
87 if (linnum) | |
88 buf.printf("(%d)", linnum); | |
89 buf.writeByte(0); | |
90 return (char *)buf.extractData(); | |
91 } | |
92 | |
93 Loc::Loc(Module *mod, unsigned linnum) | |
94 { | |
95 this->linnum = linnum; | |
96 this->filename = mod ? mod->srcfile->toChars() : NULL; | |
97 } | |
98 | |
99 /************************************** | |
100 * Print error message and exit. | |
101 */ | |
102 | |
103 void error(Loc loc, const char *format, ...) | |
104 { | |
105 va_list ap; | |
106 va_start(ap, format); | |
107 verror(loc, format, ap); | |
108 va_end( ap ); | |
109 } | |
110 | |
111 void verror(Loc loc, const char *format, va_list ap) | |
112 { | |
113 if (!global.gag) | |
114 { | |
115 char *p = loc.toChars(); | |
116 | |
117 if (*p) | |
118 fprintf(stdmsg, "%s: ", p); | |
119 mem.free(p); | |
120 | |
121 fprintf(stdmsg, "Error: "); | |
122 vfprintf(stdmsg, format, ap); | |
123 fprintf(stdmsg, "\n"); | |
124 fflush(stdmsg); | |
125 } | |
126 global.errors++; | |
127 } | |
128 | |
129 /*************************************** | |
130 * Call this after printing out fatal error messages to clean up and exit | |
131 * the compiler. | |
132 */ | |
133 | |
134 void fatal() | |
135 { | |
136 #if 0 | |
137 halt(); | |
138 #endif | |
139 exit(EXIT_FAILURE); | |
140 } | |
141 | |
142 /************************************** | |
143 * Try to stop forgetting to remove the breakpoints from | |
144 * release builds. | |
145 */ | |
146 void halt() | |
147 { | |
148 #ifdef DEBUG | |
149 *(char*)0=0; | |
150 #endif | |
151 } | |
152 | |
153 extern void backend_init(); | |
154 extern void backend_term(); | |
155 | |
156 void usage() | |
157 { | |
205
9d44ec83acd1
[svn r221] Update: Switched to the 2.3 LLVM svn branch, http://llvm.org/svn/llvm-project/llvm/branches/release_23 .
lindquist
parents:
159
diff
changeset
|
158 printf("LLVM D Compiler %s (based on DMD %s and LLVM 2.3)\n%s\n%s\n", |
159 | 159 global.llvmdc_version, global.version, global.copyright, global.written); |
160 printf("\ | |
161 D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ | |
162 LLVMDC Homepage: http://www.dsource.org/projects/llvmdc\n\ | |
163 Usage:\n\ | |
164 dmd files.d ... { -switch }\n\ | |
165 \n\ | |
166 files.d D source files\n%s\ | |
167 -annotate annotate the bitcode with human readable source code\n\ | |
168 -c do not link\n\ | |
169 -cov do code coverage analysis\n\ | |
170 -D generate documentation\n\ | |
171 -Dd<docdir> write documentation file to <docdir> directory\n\ | |
172 -Df<filename> write documentation file to <filename>\n\ | |
173 -d allow deprecated features\n\ | |
174 -debug compile in debug code\n\ | |
175 -debug=level compile in debug code <= level\n\ | |
176 -debug=ident compile in debug code identified by ident\n\ | |
177 -debuglib=name set symbolic debug library to name\n\ | |
178 -defaultlib=name set default library to name\n\ | |
179 -dis disassemble module after compiling\n\ | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
180 -fp80 enable 80bit reals on x86 32bit (EXPERIMENTAL)\n\ |
159 | 181 -g add symbolic debug info\n\ |
182 -gc add symbolic debug info, pretend to be C\n\ | |
183 -H generate 'header' file\n\ | |
184 -Hd<hdrdir> write 'header' file to <hdrdir> directory\n\ | |
185 -Hf<filename> write 'header' file to <filename>\n\ | |
186 --help print help\n\ | |
187 -I<path> where to look for imports\n\ | |
188 -J<path> where to look for string imports\n\ | |
189 -ignore ignore unsupported pragmas\n\ | |
190 -inline do function inlining\n\ | |
262
88252a1af660
[svn r280] Fixed a bunch of issues with switch statements. Ended up a bit far reaching...
lindquist
parents:
250
diff
changeset
|
191 -Llinkerflag pass linkerflag to llvm-ld\n\ |
159 | 192 -m<arch> emit code specific to <arch>\n\ |
193 x86 x86-64 ppc32 ppc64\n\ | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
194 -noasm do not allow use of inline asm\n\ |
159 | 195 -nofloat do not emit reference to floating point\n\ |
196 -noruntime do not allow code that generates implicit runtime calls\n\ | |
197 -noverify do not run the validation pass before writing bitcode\n\ | |
198 -O optimize, same as -O2\n\ | |
199 -O<n> optimize at level <n> (0-5)\n\ | |
200 -o- do not write object file\n\ | |
201 -od<objdir> write object files to directory <objdir>\n\ | |
202 -of<filename> name output file to <filename>\n\ | |
203 -op do not strip paths from source file\n\ | |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
204 -oq write object files with fully qualified names\n\ |
159 | 205 -profile profile runtime performance of generated code\n\ |
206 -quiet suppress unnecessary messages\n\ | |
207 -release compile release version\n\ | |
208 -run srcfile args... run resulting program, passing args\n\ | |
209 -R<path> provide path to the directory containing the runtime library\n\ | |
210 -unittest compile in unit tests\n\ | |
211 -v verbose\n\ | |
212 -vv very verbose (does not include -v)\n\ | |
213 -v1 D language version 1\n\ | |
214 -version=level compile in version code >= level\n\ | |
215 -version=ident compile in version code identified by ident\n\ | |
216 -w enable warnings\n\ | |
217 ", | |
218 #if WIN32 | |
219 " @cmdfile read arguments from cmdfile\n" | |
220 #else | |
221 "" | |
222 #endif | |
223 ); | |
224 } | |
225 | |
226 int main(int argc, char *argv[]) | |
227 { | |
228 int i; | |
229 Array files; | |
230 char *p; | |
231 Module *m; | |
232 int status = EXIT_SUCCESS; | |
233 int argcstart = argc; | |
234 char* tt_arch = 0; | |
235 char* tt_os = 0; | |
236 char* data_layout = 0; | |
237 bool very_verbose = false; | |
238 | |
239 // Check for malformed input | |
240 if (argc < 1 || !argv) | |
241 { | |
242 Largs: | |
243 error("missing or null command line arguments"); | |
244 fatal(); | |
245 } | |
246 for (i = 0; i < argc; i++) | |
247 { | |
248 if (!argv[i]) | |
249 goto Largs; | |
250 } | |
251 | |
252 #if __DMC__ // DMC unique support for response files | |
253 if (response_expand(&argc,&argv)) // expand response files | |
254 error("can't open response file"); | |
255 #endif | |
256 | |
257 files.reserve(argc - 1); | |
258 | |
259 // Set default values | |
260 global.params.argv0 = argv[0]; | |
261 global.params.link = 1; | |
262 global.params.useAssert = 0; | |
263 global.params.useInvariants = 0; | |
264 global.params.useIn = 1; | |
265 global.params.useOut = 1; | |
266 global.params.useArrayBounds = 0; | |
267 global.params.useSwitchError = 0; | |
268 global.params.useInline = 0; // this one messes things up to a point where codegen breaks | |
269 global.params.llvmInline = 0; // use this one instead to know if inline passes should be run | |
270 global.params.obj = 1; | |
271 global.params.Dversion = 2; | |
272 global.params.quiet = 1; | |
273 | |
274 global.params.linkswitches = new Array(); | |
275 global.params.libfiles = new Array(); | |
276 global.params.objfiles = new Array(); | |
277 global.params.ddocfiles = new Array(); | |
278 | |
279 global.params.is64bit = sizeof(void*) == 8 ? 1 : 0; | |
280 | |
281 uint16_t endiantest = 0xFF00; | |
282 uint8_t endianres = ((uint8_t*)&endiantest)[0]; | |
283 if (endianres == 0x00) | |
284 global.params.isLE = true; | |
285 else if (endianres == 0xFF) | |
286 global.params.isLE = false; | |
287 else { | |
288 error("Endian test is broken"); | |
289 fatal(); | |
290 } | |
291 | |
292 global.params.llvmArch = 0; | |
293 global.params.forceBE = 0; | |
294 global.params.noruntime = 0; | |
295 global.params.novalidate = 0; | |
296 global.params.optimizeLevel = -1; | |
297 global.params.runtimeImppath = 0; | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
298 global.params.useInlineAsm = 1; |
159 | 299 |
300 global.params.defaultlibname = "phobos"; | |
301 global.params.debuglibname = global.params.defaultlibname; | |
302 | |
303 // Predefine version identifiers | |
304 #if IN_LLVM | |
305 VersionCondition::addPredefinedGlobalIdent("LLVM"); | |
306 VersionCondition::addPredefinedGlobalIdent("LLVMDC"); | |
307 #endif | |
308 #if _WIN32 | |
309 VersionCondition::addPredefinedGlobalIdent("Windows"); | |
310 VersionCondition::addPredefinedGlobalIdent("Win32"); | |
279
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
311 VersionCondition::addPredefinedGlobalIdent("mingw32"); |
159 | 312 global.params.isWindows = 1; |
250
fc9c1a0eabbd
[svn r267] Fixed debug info for global variables.
lindquist
parents:
237
diff
changeset
|
313 tt_os = "-pc-mingw32"; |
159 | 314 #elif linux |
315 VersionCondition::addPredefinedGlobalIdent("linux"); | |
316 global.params.isLinux = 1; | |
279
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
317 tt_os = "-pc-linux-gnu"; |
159 | 318 #else |
319 #error | |
320 #endif /* linux */ | |
321 | |
279
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
322 // !win32 == posix for now |
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
323 if (!global.params.isWindows) |
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
324 VersionCondition::addPredefinedGlobalIdent("Posix"); |
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
325 |
159 | 326 //VersionCondition::addPredefinedGlobalIdent("D_Bits"); |
327 VersionCondition::addPredefinedGlobalIdent("all"); | |
328 | |
329 #if _WIN32 | |
330 inifile(argv[0], "llvmdc.ini"); | |
331 #endif | |
332 #if linux | |
333 inifile(argv[0], "llvmdc.conf"); | |
334 #else | |
335 #error | |
336 #endif | |
337 getenv_setargv("DFLAGS", &argc, &argv); | |
338 | |
339 #if 0 | |
340 for (i = 0; i < argc; i++) | |
341 { | |
342 printf("argv[%d] = '%s'\n", i, argv[i]); | |
343 } | |
344 #endif | |
345 | |
346 for (i = 1; i < argc; i++) | |
347 { | |
348 p = argv[i]; | |
349 if (*p == '-') | |
350 { | |
351 if (strcmp(p + 1, "d") == 0) | |
352 global.params.useDeprecated = 1; | |
353 else if (strcmp(p + 1, "c") == 0) | |
354 global.params.link = 0; | |
355 else if (strcmp(p + 1, "cov") == 0) | |
356 global.params.cov = 1; | |
357 else if (strcmp(p + 1, "fPIC") == 0) | |
358 global.params.pic = 1; | |
359 else if (strcmp(p + 1, "g") == 0) | |
360 global.params.symdebug = 1; | |
361 else if (strcmp(p + 1, "gc") == 0) | |
362 global.params.symdebug = 2; | |
363 else if (strcmp(p + 1, "gt") == 0) | |
364 { error("use -profile instead of -gt\n"); | |
365 global.params.trace = 1; | |
366 } | |
367 else if (strcmp(p + 1, "profile") == 0) | |
368 global.params.trace = 1; | |
369 else if (strcmp(p + 1, "v") == 0) | |
370 global.params.verbose = 1; | |
371 else if (strcmp(p + 1, "vv") == 0) { | |
372 Logger::enable(); | |
373 very_verbose = true; | |
374 } | |
375 else if (strcmp(p + 1, "v1") == 0) | |
376 global.params.Dversion = 1; | |
377 else if (strcmp(p + 1, "w") == 0) | |
378 global.params.warnings = 1; | |
379 else if (p[1] == 'O') | |
380 { | |
381 global.params.optimize = 1; | |
382 global.params.optimizeLevel = 2; | |
383 if (p[2] != 0) { | |
384 int optlevel = atoi(p+2); | |
385 if (optlevel < 0 || optlevel > 5) { | |
386 error("Optimization level must be between 0 and 5. Using default (%d)", | |
387 global.params.optimizeLevel); | |
388 } | |
389 else { | |
390 global.params.optimizeLevel = optlevel; | |
391 } | |
392 } | |
393 } | |
394 else if (strcmp(p + 1, "forcebe") == 0) | |
395 global.params.forceBE = 1; | |
396 else if (strcmp(p + 1, "noruntime") == 0) | |
397 global.params.noruntime = 1; | |
398 else if (strcmp(p + 1, "noverify") == 0) | |
399 global.params.novalidate = 1; | |
400 else if (strcmp(p + 1, "dis") == 0) | |
401 global.params.disassemble = 1; | |
402 else if (strcmp(p + 1, "annotate") == 0) | |
403 global.params.llvmAnnotate = 1; | |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
404 else if (strcmp(p + 1, "fp80") == 0) |
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
405 global.params.useFP80 = 1; |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
406 else if (strcmp(p + 1, "noasm") == 0) |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
407 global.params.useInlineAsm = 0; |
159 | 408 else if (p[1] == 'o') |
409 { | |
410 switch (p[2]) | |
411 { | |
412 case '-': | |
413 global.params.obj = 0; | |
414 break; | |
415 | |
416 case 'd': | |
417 if (!p[3]) | |
418 goto Lnoarg; | |
419 global.params.objdir = p + 3; | |
420 break; | |
421 | |
422 case 'f': | |
423 if (!p[3]) | |
424 goto Lnoarg; | |
425 global.params.objname = p + 3; | |
426 break; | |
427 | |
428 case 'p': | |
429 if (p[3]) | |
430 goto Lerror; | |
431 global.params.preservePaths = 1; | |
432 break; | |
433 | |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
434 case 'q': |
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
435 if (p[3]) |
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
436 goto Lerror; |
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
437 global.params.fqnPaths = 1; |
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
438 break; |
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
439 |
159 | 440 case 0: |
441 error("-o no longer supported, use -of or -od"); | |
442 break; | |
443 | |
444 default: | |
445 goto Lerror; | |
446 } | |
447 } | |
448 else if (p[1] == 'D') | |
449 { global.params.doDocComments = 1; | |
450 switch (p[2]) | |
451 { | |
452 case 'd': | |
453 if (!p[3]) | |
454 goto Lnoarg; | |
455 global.params.docdir = p + 3; | |
456 break; | |
457 case 'f': | |
458 if (!p[3]) | |
459 goto Lnoarg; | |
460 global.params.docname = p + 3; | |
461 break; | |
462 | |
463 case 0: | |
464 break; | |
465 | |
466 default: | |
467 goto Lerror; | |
468 } | |
469 } | |
470 #ifdef _DH | |
471 else if (p[1] == 'H') | |
472 { global.params.doHdrGeneration = 1; | |
473 switch (p[2]) | |
474 { | |
475 case 'd': | |
476 if (!p[3]) | |
477 goto Lnoarg; | |
478 global.params.hdrdir = p + 3; | |
479 break; | |
480 | |
481 case 'f': | |
482 if (!p[3]) | |
483 goto Lnoarg; | |
484 global.params.hdrname = p + 3; | |
485 break; | |
486 | |
487 case 0: | |
488 break; | |
489 | |
490 default: | |
491 goto Lerror; | |
492 } | |
493 } | |
494 #endif | |
495 else if (strcmp(p + 1, "ignore") == 0) | |
496 global.params.ignoreUnsupportedPragmas = 1; | |
497 else if (strcmp(p + 1, "inline") == 0) { | |
498 // TODO | |
499 // the ast rewrites dmd does for inlining messes up the ast. | |
500 // someday maybe we can support it, for now llvm does an excellent job at inlining | |
501 global.params.useInline = 0; //1 | |
502 global.params.llvmInline = 1; | |
503 } | |
504 else if (strcmp(p + 1, "nofloat") == 0) | |
505 global.params.nofloat = 1; | |
506 else if (strcmp(p + 1, "quiet") == 0) | |
507 global.params.quiet = 1; | |
508 else if (strcmp(p + 1, "release") == 0) | |
509 global.params.release = 1; | |
510 else if (strcmp(p + 1, "unittest") == 0) | |
511 global.params.useUnitTests = 1; | |
512 else if (p[1] == 'I') | |
513 { | |
514 if (!global.params.imppath) | |
515 global.params.imppath = new Array(); | |
516 global.params.imppath->push(p + 2); | |
517 } | |
518 else if (p[1] == 'J') | |
519 { | |
520 if (!global.params.fileImppath) | |
521 global.params.fileImppath = new Array(); | |
522 global.params.fileImppath->push(p + 2); | |
523 } | |
524 else if (p[1] == 'R') | |
525 { | |
526 global.params.runtimePath = p+2; | |
527 } | |
528 else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l') | |
529 { | |
530 // Parse: | |
531 // -debug | |
532 // -debug=number | |
533 // -debug=identifier | |
534 if (p[6] == '=') | |
535 { | |
536 if (isdigit(p[7])) | |
537 { long level; | |
538 | |
539 errno = 0; | |
540 level = strtol(p + 7, &p, 10); | |
541 if (*p || errno || level > INT_MAX) | |
542 goto Lerror; | |
543 DebugCondition::setGlobalLevel((int)level); | |
544 } | |
545 else if (Lexer::isValidIdentifier(p + 7)) | |
546 DebugCondition::addGlobalIdent(p + 7); | |
547 else | |
548 goto Lerror; | |
549 } | |
550 else if (p[6]) | |
551 goto Lerror; | |
552 else | |
553 global.params.debuglevel = 1; | |
554 } | |
555 else if (memcmp(p + 1, "version", 5) == 0) | |
556 { | |
557 // Parse: | |
558 // -version=number | |
559 // -version=identifier | |
560 if (p[8] == '=') | |
561 { | |
562 if (isdigit(p[9])) | |
563 { long level; | |
564 | |
565 errno = 0; | |
566 level = strtol(p + 9, &p, 10); | |
567 if (*p || errno || level > INT_MAX) | |
568 goto Lerror; | |
569 VersionCondition::setGlobalLevel((int)level); | |
570 } | |
571 else if (Lexer::isValidIdentifier(p + 9)) | |
572 VersionCondition::addGlobalIdent(p + 9); | |
573 else | |
574 goto Lerror; | |
575 } | |
576 else | |
577 goto Lerror; | |
578 } | |
579 else if (strcmp(p + 1, "-b") == 0) | |
580 global.params.debugb = 1; | |
581 else if (strcmp(p + 1, "-c") == 0) | |
582 global.params.debugc = 1; | |
583 else if (strcmp(p + 1, "-f") == 0) | |
584 global.params.debugf = 1; | |
585 else if (strcmp(p + 1, "-help") == 0) | |
586 { usage(); | |
587 exit(EXIT_SUCCESS); | |
588 } | |
589 else if (strcmp(p + 1, "-r") == 0) | |
590 global.params.debugr = 1; | |
591 else if (strcmp(p + 1, "-x") == 0) | |
592 global.params.debugx = 1; | |
593 else if (strcmp(p + 1, "-y") == 0) | |
594 global.params.debugy = 1; | |
595 else if (p[1] == 'L') | |
596 { | |
597 global.params.linkswitches->push(p + 2); | |
598 } | |
599 else if (memcmp(p + 1, "defaultlib=", 11) == 0) | |
600 { | |
601 global.params.defaultlibname = p + 1 + 11; | |
602 } | |
603 else if (memcmp(p + 1, "debuglib=", 9) == 0) | |
604 { | |
605 global.params.debuglibname = p + 1 + 9; | |
606 } | |
607 else if (strcmp(p + 1, "run") == 0) | |
608 { global.params.run = 1; | |
609 global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1; | |
610 if (global.params.runargs_length) | |
611 { | |
612 files.push(argv[i + 1]); | |
613 global.params.runargs = &argv[i + 2]; | |
614 i += global.params.runargs_length; | |
615 global.params.runargs_length--; | |
616 } | |
617 else | |
618 { global.params.run = 0; | |
619 goto Lnoarg; | |
620 } | |
621 } | |
622 else if (p[1] == 'm') | |
623 { | |
624 global.params.llvmArch = p+2; | |
625 } | |
626 else | |
627 { | |
628 Lerror: | |
629 error("unrecognized switch '%s'", argv[i]); | |
630 continue; | |
631 | |
632 Lnoarg: | |
633 error("argument expected for switch '%s'", argv[i]); | |
634 continue; | |
635 } | |
636 } | |
637 else | |
638 files.push(p); | |
639 } | |
640 if (global.errors) | |
641 { | |
642 fatal(); | |
643 } | |
644 if (files.dim == 0) | |
645 { usage(); | |
646 return EXIT_FAILURE; | |
647 } | |
648 | |
649 if (global.params.release) | |
650 { global.params.useInvariants = 0; | |
651 global.params.useIn = 0; | |
652 global.params.useOut = 0; | |
653 global.params.useAssert = 0; | |
654 global.params.useArrayBounds = 0; | |
655 global.params.useSwitchError = 0; | |
656 } | |
657 | |
658 if (global.params.run) | |
659 global.params.quiet = 1; | |
660 | |
661 if (global.params.useUnitTests) | |
662 global.params.useAssert = 1; | |
663 | |
664 if (!global.params.obj) | |
665 global.params.link = 0; | |
666 | |
667 if (global.params.link) | |
668 { | |
669 global.params.exefile = global.params.objname; | |
670 global.params.objname = NULL; | |
671 } | |
672 else if (global.params.run) | |
673 { | |
674 error("flags conflict with -run"); | |
675 fatal(); | |
676 } | |
677 else | |
678 { | |
679 if (global.params.objname && files.dim > 1) | |
680 { | |
681 error("multiple source files, but only one .obj name"); | |
682 fatal(); | |
683 } | |
684 } | |
685 if (global.params.cov) | |
686 VersionCondition::addPredefinedGlobalIdent("D_Coverage"); | |
687 | |
688 bool allowForceEndianness = false; | |
689 | |
690 if (global.params.llvmArch == 0) { | |
284
70c370e97944
[svn r305] Started support for custom class allocators/deallocators. Allocators with more than one argument still need to be fixed.
lindquist
parents:
279
diff
changeset
|
691 findDefaultTarget(); |
159 | 692 } |
693 | |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
694 bool is_x86 = false; |
159 | 695 if (strcmp(global.params.llvmArch,"x86")==0) { |
696 VersionCondition::addPredefinedGlobalIdent("X86"); | |
697 //VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86"); | |
698 global.params.isLE = true; | |
699 global.params.is64bit = false; | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
700 global.params.cpu = ARCHx86; |
159 | 701 tt_arch = "i686"; |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
702 data_layout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-f80:32:32-v64:64:64-v128:128:128-a0:0:64"; |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
703 is_x86 = true; |
159 | 704 } |
705 else if (strcmp(global.params.llvmArch,"x86-64")==0) { | |
706 VersionCondition::addPredefinedGlobalIdent("X86_64"); | |
707 //VersionCondition::addPredefinedGlobalIdent("LLVM_InlineAsm_X86_64"); | |
708 global.params.isLE = true; | |
709 global.params.is64bit = true; | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
710 global.params.cpu = ARCHx86_64; |
159 | 711 tt_arch = "x86_64"; |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
712 data_layout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"; |
159 | 713 } |
714 else if (strcmp(global.params.llvmArch,"ppc32")==0) { | |
715 VersionCondition::addPredefinedGlobalIdent("PPC"); | |
716 global.params.isLE = false; | |
717 global.params.is64bit = false; | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
718 global.params.cpu = ARCHppc; |
159 | 719 tt_arch = "powerpc"; |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
720 data_layout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"; |
159 | 721 } |
722 else if (strcmp(global.params.llvmArch,"ppc64")==0) { | |
723 VersionCondition::addPredefinedGlobalIdent("PPC64"); | |
724 global.params.isLE = false; | |
725 global.params.is64bit = true; | |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
726 global.params.cpu = ARCHppc_64; |
159 | 727 tt_arch = "powerpc64"; |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
728 data_layout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"; |
159 | 729 } |
730 else { | |
731 assert(0 && "Invalid arch"); | |
732 } | |
733 | |
734 if (allowForceEndianness && global.params.forceBE) { | |
735 VersionCondition::addPredefinedGlobalIdent("BigEndian"); | |
736 global.params.isLE = false; | |
737 } | |
738 else if (global.params.isLE) { | |
739 VersionCondition::addPredefinedGlobalIdent("LittleEndian"); | |
740 } | |
741 else { | |
742 VersionCondition::addPredefinedGlobalIdent("BigEndian"); | |
743 } | |
744 | |
745 if (global.params.is64bit) { | |
746 VersionCondition::addPredefinedGlobalIdent("LLVM64"); | |
747 } | |
748 | |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
749 if (global.params.useFP80) { |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
750 if (!is_x86) { |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
751 error("the -fp80 option is only valid for the x86 32bit architecture"); |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
752 fatal(); |
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
753 } |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
754 VersionCondition::addPredefinedGlobalIdent("LLVM_X86_FP80"); |
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
755 } |
237
a168a2c3ea48
[svn r253] Removed -inlineasm option. inline asm is now enabled by default unless the new -noasm option is passed.
lindquist
parents:
220
diff
changeset
|
756 if (is_x86 && global.params.useInlineAsm) { |
220
ccc2e6898a78
[svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents:
219
diff
changeset
|
757 VersionCondition::addPredefinedGlobalIdent("D_InlineAsm"); |
ccc2e6898a78
[svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents:
219
diff
changeset
|
758 VersionCondition::addPredefinedGlobalIdent("D_InlineAsm_X86"); |
ccc2e6898a78
[svn r236] added initial codegen of inline asm, pretty buggy and incomplete still. see the tangotests/asm1.d test for a sample of what does
lindquist
parents:
219
diff
changeset
|
759 } |
217
0806379a5eca
[svn r233] Added: -oq command line option for writing fully qualified object names.
lindquist
parents:
205
diff
changeset
|
760 |
159 | 761 assert(tt_arch != 0); |
762 assert(tt_os != 0); | |
763 assert(data_layout != 0); | |
764 global.params.tt_arch = tt_arch; | |
765 global.params.tt_os = tt_os; | |
766 global.params.data_layout = data_layout; | |
767 | |
768 // Initialization | |
769 Type::init(); | |
770 Id::initialize(); | |
771 Module::init(); | |
772 initPrecedence(); | |
773 | |
774 backend_init(); | |
775 | |
776 //printf("%d source files\n",files.dim); | |
777 | |
778 // Build import search path | |
779 if (global.params.imppath) | |
780 { | |
781 for (i = 0; i < global.params.imppath->dim; i++) | |
782 { | |
783 char *path = (char *)global.params.imppath->data[i]; | |
784 Array *a = FileName::splitPath(path); | |
785 | |
786 if (a) | |
787 { | |
788 if (!global.path) | |
789 global.path = new Array(); | |
790 global.path->append(a); | |
791 } | |
792 } | |
793 } | |
794 | |
795 // Build string import search path | |
796 if (global.params.fileImppath) | |
797 { | |
798 for (i = 0; i < global.params.fileImppath->dim; i++) | |
799 { | |
800 char *path = (char *)global.params.fileImppath->data[i]; | |
801 Array *a = FileName::splitPath(path); | |
802 | |
803 if (a) | |
804 { | |
805 if (!global.filePath) | |
806 global.filePath = new Array(); | |
807 global.filePath->append(a); | |
808 } | |
809 } | |
810 } | |
811 | |
812 // Create Modules | |
813 Array modules; | |
814 modules.reserve(files.dim); | |
815 for (i = 0; i < files.dim; i++) | |
816 { Identifier *id; | |
817 char *ext; | |
818 char *name; | |
819 | |
820 p = (char *) files.data[i]; | |
821 | |
822 p = FileName::name(p); // strip path | |
823 ext = FileName::ext(p); | |
824 if (ext) | |
825 { | |
826 #if IN_LLVM | |
827 if (strcmp(ext, global.nativeobj_ext) == 0 || | |
828 strcmp(ext, global.obj_ext) == 0) | |
829 #elif TARGET_LINUX | |
830 if (strcmp(ext, global.obj_ext) == 0) | |
831 #else | |
832 if (stricmp(ext, global.obj_ext) == 0) | |
833 #endif | |
834 { | |
835 global.params.objfiles->push(files.data[i]); | |
836 continue; | |
837 } | |
838 | |
279
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
839 #if TARGET_LINUX || __MINGW32__ |
159 | 840 if (strcmp(ext, "a") == 0) |
841 #else | |
842 if (stricmp(ext, "lib") == 0) | |
843 #endif | |
844 { | |
845 global.params.libfiles->push(files.data[i]); | |
846 continue; | |
847 } | |
848 | |
849 if (strcmp(ext, global.ddoc_ext) == 0) | |
850 { | |
851 global.params.ddocfiles->push(files.data[i]); | |
852 continue; | |
853 } | |
854 | |
855 #if !TARGET_LINUX | |
856 if (stricmp(ext, "res") == 0) | |
857 { | |
858 global.params.resfile = (char *)files.data[i]; | |
859 continue; | |
860 } | |
861 | |
862 if (stricmp(ext, "def") == 0) | |
863 { | |
864 global.params.deffile = (char *)files.data[i]; | |
865 continue; | |
866 } | |
867 | |
868 if (stricmp(ext, "exe") == 0) | |
869 { | |
870 global.params.exefile = (char *)files.data[i]; | |
871 continue; | |
872 } | |
873 #endif | |
874 | |
875 if (stricmp(ext, global.mars_ext) == 0 || | |
876 stricmp(ext, "htm") == 0 || | |
877 stricmp(ext, "html") == 0 || | |
878 stricmp(ext, "xhtml") == 0) | |
879 { | |
880 ext--; // skip onto '.' | |
881 assert(*ext == '.'); | |
882 name = (char *)mem.malloc((ext - p) + 1); | |
883 memcpy(name, p, ext - p); | |
884 name[ext - p] = 0; // strip extension | |
885 | |
886 if (name[0] == 0 || | |
887 strcmp(name, "..") == 0 || | |
888 strcmp(name, ".") == 0) | |
889 { | |
890 Linvalid: | |
891 error("invalid file name '%s'", (char *)files.data[i]); | |
892 fatal(); | |
893 } | |
894 } | |
895 else | |
896 { error("unrecognized file extension %s\n", ext); | |
897 fatal(); | |
898 } | |
899 } | |
900 else | |
901 { name = p; | |
902 if (!*name) | |
903 goto Linvalid; | |
904 } | |
905 | |
906 id = new Identifier(name, 0); | |
907 m = new Module((char *) files.data[i], id, global.params.doDocComments, global.params.doHdrGeneration); | |
908 modules.push(m); | |
909 | |
910 global.params.objfiles->push(m->objfile->name->str); | |
911 } | |
912 | |
913 // Read files, parse them | |
914 for (i = 0; i < modules.dim; i++) | |
915 { | |
916 m = (Module *)modules.data[i]; | |
917 if (global.params.verbose) | |
918 printf("parse %s\n", m->toChars()); | |
919 if (!Module::rootModule) | |
920 Module::rootModule = m; | |
921 m->importedFrom = m; | |
922 m->deleteObjFile(); | |
923 m->read(0); | |
924 m->parse(); | |
925 if (m->isDocFile) | |
926 { | |
927 m->gendocfile(); | |
928 | |
929 // Remove m from list of modules | |
930 modules.remove(i); | |
931 i--; | |
932 | |
933 // Remove m's object file from list of object files | |
934 for (int j = 0; j < global.params.objfiles->dim; j++) | |
935 { | |
936 if (m->objfile->name->str == global.params.objfiles->data[j]) | |
937 { | |
938 global.params.objfiles->remove(j); | |
939 break; | |
940 } | |
941 } | |
942 | |
943 if (global.params.objfiles->dim == 0) | |
944 global.params.link = 0; | |
945 } | |
946 } | |
947 if (global.errors) | |
948 fatal(); | |
949 #ifdef _DH | |
950 if (global.params.doHdrGeneration) | |
951 { | |
952 /* Generate 'header' import files. | |
953 * Since 'header' import files must be independent of command | |
954 * line switches and what else is imported, they are generated | |
955 * before any semantic analysis. | |
956 */ | |
957 for (i = 0; i < modules.dim; i++) | |
958 { | |
959 m = (Module *)modules.data[i]; | |
960 if (global.params.verbose) | |
961 printf("import %s\n", m->toChars()); | |
962 m->genhdrfile(); | |
963 } | |
964 } | |
965 if (global.errors) | |
966 fatal(); | |
967 #endif | |
968 | |
969 // Do semantic analysis | |
970 for (i = 0; i < modules.dim; i++) | |
971 { | |
972 m = (Module *)modules.data[i]; | |
973 if (global.params.verbose) | |
974 printf("semantic %s\n", m->toChars()); | |
975 m->semantic(); | |
976 } | |
977 if (global.errors) | |
978 fatal(); | |
979 | |
980 // Do pass 2 semantic analysis | |
981 for (i = 0; i < modules.dim; i++) | |
982 { | |
983 m = (Module *)modules.data[i]; | |
984 if (global.params.verbose) | |
985 printf("semantic2 %s\n", m->toChars()); | |
986 m->semantic2(); | |
987 } | |
988 if (global.errors) | |
989 fatal(); | |
990 | |
991 // Do pass 3 semantic analysis | |
992 for (i = 0; i < modules.dim; i++) | |
993 { | |
994 m = (Module *)modules.data[i]; | |
995 if (global.params.verbose) | |
996 printf("semantic3 %s\n", m->toChars()); | |
997 m->semantic3(); | |
998 } | |
999 if (global.errors) | |
1000 fatal(); | |
1001 | |
1002 #if !IN_LLVM | |
1003 // Scan for functions to inline | |
1004 if (global.params.useInline) | |
1005 { | |
1006 /* The problem with useArrayBounds and useAssert is that the | |
1007 * module being linked to may not have generated them, so if | |
1008 * we inline functions from those modules, the symbols for them will | |
1009 * not be found at link time. | |
1010 */ | |
1011 if (!global.params.useArrayBounds && !global.params.useAssert) | |
1012 { | |
1013 #endif | |
1014 // Do pass 3 semantic analysis on all imported modules, | |
1015 // since otherwise functions in them cannot be inlined | |
1016 for (i = 0; i < Module::amodules.dim; i++) | |
1017 { | |
1018 m = (Module *)Module::amodules.data[i]; | |
1019 if (global.params.verbose) | |
1020 printf("semantic3 %s\n", m->toChars()); | |
1021 m->semantic3(); | |
1022 } | |
1023 if (global.errors) | |
1024 fatal(); | |
1025 #if !IN_LLVM | |
1026 } | |
1027 | |
1028 for (i = 0; i < modules.dim; i++) | |
1029 { | |
1030 m = (Module *)modules.data[i]; | |
1031 if (global.params.verbose) | |
1032 printf("inline scan %s\n", m->toChars()); | |
1033 m->inlineScan(); | |
1034 } | |
1035 } | |
1036 if (global.errors) | |
1037 fatal(); | |
1038 #endif | |
1039 | |
1040 // Generate output files | |
1041 for (i = 0; i < modules.dim; i++) | |
1042 { | |
1043 m = (Module *)modules.data[i]; | |
1044 if (global.params.verbose) | |
1045 printf("code %s\n", m->toChars()); | |
1046 if (global.params.obj) | |
1047 m->genobjfile(); | |
1048 if (global.errors) | |
1049 m->deleteObjFile(); | |
1050 else | |
1051 { | |
1052 if (global.params.doDocComments) | |
1053 m->gendocfile(); | |
1054 } | |
1055 } | |
279
a137ed004205
[svn r300] Removed some win32 stuff that was causing problems on mingw32.
lindquist
parents:
277
diff
changeset
|
1056 |
159 | 1057 backend_term(); |
1058 if (global.errors) | |
1059 fatal(); | |
1060 | |
1061 if (!global.params.objfiles->dim) | |
1062 { | |
1063 if (global.params.link) | |
1064 error("no object files to link"); | |
1065 } | |
1066 else | |
1067 { | |
1068 if (global.params.link) | |
276
21f85bac0b1a
[svn r297] Fixed: rewrote linker code to use LLVM's Program facilities instead of DMD's oldschool broken "native" approach.
lindquist
parents:
262
diff
changeset
|
1069 //status = runLINK(); |
21f85bac0b1a
[svn r297] Fixed: rewrote linker code to use LLVM's Program facilities instead of DMD's oldschool broken "native" approach.
lindquist
parents:
262
diff
changeset
|
1070 linkExecutable(); |
159 | 1071 |
1072 if (global.params.run) | |
1073 { | |
1074 if (!status) | |
1075 { | |
277
90a8c798b0db
[svn r298] Eliminated the dmd/link.c source file entirely in favor of a llvm::sys based approach to the same functionality.
lindquist
parents:
276
diff
changeset
|
1076 status = runExectuable(); |
159 | 1077 |
1078 /* Delete .obj files and .exe file | |
1079 */ | |
1080 for (i = 0; i < modules.dim; i++) | |
1081 { | |
1082 m = (Module *)modules.data[i]; | |
1083 m->deleteObjFile(); | |
1084 } | |
277
90a8c798b0db
[svn r298] Eliminated the dmd/link.c source file entirely in favor of a llvm::sys based approach to the same functionality.
lindquist
parents:
276
diff
changeset
|
1085 deleteExecutable(); |
159 | 1086 } |
1087 } | |
1088 } | |
1089 | |
1090 return status; | |
1091 } | |
1092 | |
1093 | |
1094 | |
1095 /*********************************** | |
1096 * Parse and append contents of environment variable envvar | |
1097 * to argc and argv[]. | |
1098 * The string is separated into arguments, processing \ and ". | |
1099 */ | |
1100 | |
1101 void getenv_setargv(const char *envvar, int *pargc, char** *pargv) | |
1102 { | |
1103 char *env; | |
1104 char *p; | |
1105 Array *argv; | |
1106 int argc; | |
1107 | |
1108 int wildcard; // do wildcard expansion | |
1109 int instring; | |
1110 int slash; | |
1111 char c; | |
1112 int j; | |
1113 | |
1114 env = getenv(envvar); | |
1115 if (!env) | |
1116 return; | |
1117 | |
1118 env = mem.strdup(env); // create our own writable copy | |
1119 | |
1120 argc = *pargc; | |
1121 argv = new Array(); | |
1122 argv->setDim(argc); | |
1123 | |
1124 for (int i = 0; i < argc; i++) | |
1125 argv->data[i] = (void *)(*pargv)[i]; | |
1126 | |
1127 j = 1; // leave argv[0] alone | |
1128 while (1) | |
1129 { | |
1130 wildcard = 1; | |
1131 switch (*env) | |
1132 { | |
1133 case ' ': | |
1134 case '\t': | |
1135 env++; | |
1136 break; | |
1137 | |
1138 case 0: | |
1139 goto Ldone; | |
1140 | |
1141 case '"': | |
1142 wildcard = 0; | |
1143 default: | |
1144 argv->push(env); // append | |
1145 //argv->insert(j, env); // insert at position j | |
1146 j++; | |
1147 argc++; | |
1148 p = env; | |
1149 slash = 0; | |
1150 instring = 0; | |
1151 c = 0; | |
1152 | |
1153 while (1) | |
1154 { | |
1155 c = *env++; | |
1156 switch (c) | |
1157 { | |
1158 case '"': | |
1159 p -= (slash >> 1); | |
1160 if (slash & 1) | |
1161 { p--; | |
1162 goto Laddc; | |
1163 } | |
1164 instring ^= 1; | |
1165 slash = 0; | |
1166 continue; | |
1167 | |
1168 case ' ': | |
1169 case '\t': | |
1170 if (instring) | |
1171 goto Laddc; | |
1172 *p = 0; | |
1173 //if (wildcard) | |
1174 //wildcardexpand(); // not implemented | |
1175 break; | |
1176 | |
1177 case '\\': | |
1178 slash++; | |
1179 *p++ = c; | |
1180 continue; | |
1181 | |
1182 case 0: | |
1183 *p = 0; | |
1184 //if (wildcard) | |
1185 //wildcardexpand(); // not implemented | |
1186 goto Ldone; | |
1187 | |
1188 default: | |
1189 Laddc: | |
1190 slash = 0; | |
1191 *p++ = c; | |
1192 continue; | |
1193 } | |
1194 break; | |
1195 } | |
1196 } | |
1197 } | |
1198 | |
1199 Ldone: | |
1200 *pargc = argc; | |
1201 *pargv = (char **)argv->data; | |
1202 } |