Allow returning something of type void in a function that returns void
[delight/core.git] / d-spec.c
blobf780d584af57d6ae713ddc1d3a7604dff1ff83d8
1 /* GDC -- D front-end for GCC
2 Copyright (C) 2004 David Friedman
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /* Much taken from g++spec.c */
21 TODO: Remove C++ stuff from lang_specific_driver
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
29 #include "gcc.h"
31 /* This bit is set if we saw a `-xfoo' language specification. */
32 #define LANGSPEC (1<<1)
33 /* This bit is set if they did `-lm' or `-lmath'. */
34 #define MATHLIB (1<<2)
35 /* This bit is set if they did `-lc'. */
36 #define WITHLIBC (1<<3)
37 /* This bit is set if the arguments is a D source file. */
38 #define D_SOURCE_FILE (1<<4)
39 /* This bit is set when the argument should not be passed to gcc or the backend */
40 #define REMOVE_ARG (1<<6)
42 #ifndef MATH_LIBRARY
43 #define MATH_LIBRARY "-lm"
44 #endif
45 #ifndef MATH_LIBRARY_PROFILE
46 #define MATH_LIBRARY_PROFILE "-lm"
47 #endif
49 #ifndef LIBPHOBOS
50 #define LIBPHOBOS "-lgphobos"
51 #endif
52 #ifndef LIBPHOBOS_PROFILE
53 #define LIBPHOBOS_PROFILE "-lgphobos"
54 #endif
56 static char** all_d_sources = NULL;
57 static unsigned n_all_d_sources = 0;
58 static char * output_directory_option = NULL;
59 static int output_parents_option = 0;
60 static char * only_source_option = NULL;
62 extern int need_pthreads;
64 void
65 lang_specific_driver (int *in_argc, const char *const **in_argv,
66 int *in_added_libraries)
69 int i, j;
71 /* If nonzero, the user gave us the `-p' or `-pg' flag. */
72 int saw_profile_flag = 0;
74 /* If nonzero, the user gave us the `-v' flag. */
75 int saw_verbose_flag = 0;
77 /* This is a tristate:
78 -1 means we should not link in libstdc++
79 0 means we should link in libstdc++ if it is needed
80 1 means libstdc++ is needed and should be linked in. */
81 int library = 0;
83 /* If nonzero, use the standard D runtime library when linking with
84 stanard libraries. */
85 int phobos = 1;
87 /* The number of arguments being added to what's in argv, other than
88 libraries. We use this to track the number of times we've inserted
89 -xc++/-xnone. */
90 int added = 0;
92 /* Used to track options that take arguments, so we don't go wrapping
93 those with -xc++/-xnone. */
94 const char *quote = NULL;
96 /* The new argument list will be contained in this. */
97 const char **arglist;
99 /* Nonzero if we saw a `-xfoo' language specification on the
100 command line. Used to avoid adding our own -xc++ if the user
101 already gave a language for the file. */
102 int saw_speclang = 0;
104 /* "-lm" or "-lmath" if it appears on the command line. */
105 const char *saw_math = 0;
107 /* "-lc" if it appears on the command line. */
108 const char *saw_libc = 0;
110 /* An array used to flag each argument that needs a bit set for
111 LANGSPEC, MATHLIB, or WITHLIBC. */
112 int *args;
114 /* By default, we throw on the math library if we have one. */
115 int need_math = (MATH_LIBRARY[0] != '\0');
117 /* True if we should add -shared-libgcc to the command-line. */
118 int shared_libgcc = 1;
120 /* The total number of arguments with the new stuff. */
121 int argc;
123 /* The argument list. */
124 const char *const *argv;
126 /* The number of libraries added in. */
127 int added_libraries;
129 /* The total number of arguments with the new stuff. */
130 int num_args = 1;
132 /* If we add libraries, should we read $(libdir)/phobos-threadlib and add that */
133 int add_thread_lib = 1;
135 argc = *in_argc;
136 argv = *in_argv;
137 added_libraries = *in_added_libraries;
139 args = xcalloc (argc, sizeof (int));
141 /* Keep track of all source files */
142 n_all_d_sources = 0;
144 for (i = 1; i < argc; i++)
146 /* If the previous option took an argument, we swallow it here. */
147 if (quote)
149 quote = NULL;
150 continue;
153 /* We don't do this anymore, since we don't get them with minus
154 signs on them. */
155 if (argv[i][0] == '\0' || argv[i][1] == '\0')
156 continue;
158 if (argv[i][0] == '-')
160 if (strcmp (argv[i], "-nostdlib") == 0
161 || strcmp (argv[i], "-nodefaultlibs") == 0)
163 library = -1;
165 else if (strcmp (argv[i], "-nophoboslib") == 0)
167 added = 1; // force argument rebuild
168 phobos = 0;
169 args[i] |= REMOVE_ARG;
171 else if (strcmp (argv[i], "-lm") == 0
172 || strcmp (argv[i], "-lmath") == 0
173 || strcmp (argv[i], MATH_LIBRARY) == 0
176 args[i] |= MATHLIB;
177 need_math = 0;
179 else if (strcmp (argv[i], "-lc") == 0)
180 args[i] |= WITHLIBC;
181 else if (strcmp (argv[i], "-pg") == 0 || strcmp (argv[i], "-p") == 0)
182 saw_profile_flag++;
183 else if (strcmp (argv[i], "-v") == 0)
184 saw_verbose_flag = 1;
185 else if (strncmp (argv[i], "-x", 2) == 0)
187 if (library == 0)
189 const char * arg;
190 if (argv[i][2] != '\0')
191 arg = argv[i]+2;
192 else if (argv[i+1] != NULL)
193 arg = argv[i+1];
194 else /* Error condition, message will be printed later. */
195 arg = "";
196 if (strcmp (arg, "c++") == 0
197 || strcmp (arg, "c++-cpp-output") == 0)
198 library = 1;
200 saw_speclang = 1;
202 else if (((argv[i][2] == '\0'
203 && strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
204 || strcmp (argv[i], "-Xlinker") == 0
205 || strcmp (argv[i], "-Tdata") == 0))
206 quote = argv[i];
207 else if ((argv[i][2] == '\0'
208 && strchr ("cSEM", argv[i][1]) != NULL)
209 || strcmp (argv[i], "-MM") == 0
210 || strcmp (argv[i], "-fsyntax-only") == 0)
212 /* Don't specify libraries if we won't link, since that would
213 cause a warning. */
214 library = -1;
216 else if (strcmp (argv[i], "-static-libgcc") == 0
217 || strcmp (argv[i], "-static") == 0)
218 shared_libgcc = 0;
219 else if (strncmp (argv[i], "-fonly=", 7) == 0)
221 int len;
223 args[i] |= REMOVE_ARG;
224 only_source_option = argv[i]; //%%TODO: copy/const
226 len = strlen(only_source_option);
227 if (len <= 2 || only_source_option[len-1] != 'd' ||
228 only_source_option[len-2] != '.') {
229 only_source_option = concat(only_source_option, ".d", NULL);
230 } else {
231 only_source_option = xstrdup(only_source_option);
234 else if (strncmp (argv[i], "-fod=", 5) == 0)
236 args[i] |= REMOVE_ARG;
237 output_directory_option = xstrdup(argv[i] + 5);
238 fprintf(stderr, "** outputdir = '%s'\n", output_directory_option);
240 else if (strcmp (argv[i], "-fop") == 0)
242 args[i] |= REMOVE_ARG;
243 output_parents_option = 1;
244 fprintf(stderr, "** output parents\n");
246 else if (DEFAULT_WORD_SWITCH_TAKES_ARG (&argv[i][1]))
247 i++;
248 else
249 /* Pass other options through. */
250 continue;
252 else
254 int len;
256 if (saw_speclang)
258 saw_speclang = 0;
259 continue;
262 len = strlen (argv[i]);
263 if (len > 2
264 && (argv[i][len - 1] == 'd')
265 && (argv[i][len - 2] == '.'))
267 n_all_d_sources++;
268 args[i] |= D_SOURCE_FILE;
271 /* If we don't know that this is a header file, we might
272 need to be linking in the libraries. */
273 if (library == 0)
275 if ((len <= 2 || strcmp (argv[i] + (len - 2), ".H") != 0)
276 && (len <= 2 || strcmp (argv[i] + (len - 2), ".h") != 0)
277 && (len <= 3 || strcmp (argv[i] + (len - 3), ".hh") != 0))
278 library = 1;
283 if (quote)
284 fatal ("argument to `%s' missing\n", quote);
286 if (only_source_option) {
287 all_d_sources = (char **) xmalloc (n_all_d_sources * sizeof(char *));
288 n_all_d_sources = 0; /* will be incremented again below */
291 /* If we know we don't have to do anything, bail now. */
292 if (! added && library <= 0 && ! only_source_option)
294 free (args);
295 return;
298 /* There's no point adding -shared-libgcc if we don't have a shared
299 libgcc. */
300 #ifndef ENABLE_SHARED_LIBGCC
301 shared_libgcc = 0;
302 #endif
304 /* Make sure to have room for the trailing NULL argument. */
305 /* There is one extra argument added here for the runtime
306 library: -lgphobos. The -pthread argument is added by
307 setting need_pthreads. */
308 num_args = argc + added + need_math + shared_libgcc + (library > 0 ? 1 : 0) + 1;
309 arglist = xmalloc (num_args * sizeof (char *));
311 i = 0;
312 j = 0;
314 /* Copy the 0th argument, i.e., the name of the program itself. */
315 arglist[i++] = argv[j++];
317 /* NOTE: We start at 1 now, not 0. */
318 while (i < argc)
320 if ( args[i] & REMOVE_ARG )
322 ++i;
323 continue;
326 arglist[j] = argv[i];
328 /* Make sure -lstdc++ is before the math library, since libstdc++
329 itself uses those math routines. */
330 if (!saw_math && (args[i] & MATHLIB) && library > 0)
332 --j;
333 saw_math = argv[i];
336 if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
338 --j;
339 saw_libc = argv[i];
342 if (args[i] & D_SOURCE_FILE)
344 if (all_d_sources)
345 all_d_sources[n_all_d_sources++] = xstrdup(arglist[j]);
346 if ( only_source_option )
348 j--;
353 i++;
354 j++;
357 if (only_source_option)
359 arglist[j++] = only_source_option;
360 arglist[j++] = only_source_option + 7;
363 /* Add `-lstdc++' if we haven't already done so. */
364 if (library > 0 && phobos)
366 arglist[j++] = saw_profile_flag ? LIBPHOBOS_PROFILE : LIBPHOBOS;
367 added_libraries++;
368 need_pthreads = 1;
370 if (saw_math)
371 arglist[j++] = saw_math;
372 else if (library > 0 && need_math)
374 arglist[j++] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY;
375 added_libraries++;
377 if (saw_libc)
378 arglist[j++] = saw_libc;
379 if (shared_libgcc)
380 arglist[j++] = "-shared-libgcc";
382 arglist[j] = NULL;
384 *in_argc = j;
385 *in_argv = arglist;
386 *in_added_libraries = added_libraries;
389 /* Called before linking. Returns 0 on success and -1 on failure. */
390 int lang_specific_pre_link (void) /* Not used for D. */
392 return 0;
396 static const char *
397 d_all_sources_spec_function (int argc , const char ** argv)
399 unsigned result_len = 0;
400 unsigned i;
402 if (only_source_option) {
403 char * result;
405 for (i = 0; i < n_all_d_sources; i++)
406 result_len += strlen(all_d_sources[i]);
407 result_len += n_all_d_sources + 1; /* once space to separate each file and terminating null
408 ... really n_all_d_sources - 1 + 1, but ignores n=0 case */
409 result = (char *) xmalloc(result_len);
410 result[0] = '\0';
411 for (i = 0; i < n_all_d_sources; i++) {
412 if ( i )
413 strcat(result, " ");
414 strcat(result, all_d_sources[i]);
417 return result;
418 } else {
419 return "";
423 static const char *
424 d_output_prefix_spec_function (int argc , const char ** argv)
426 char * result = "";
427 fprintf(stderr, "** d_output_prefix_spec_function(%s)\n", argv[0]);
428 if (argc != 1)
429 return ""; /* %% should abort */
430 if (output_directory_option)
431 result = concat(output_directory_option, "/", NULL);
432 if (output_parents_option) {
433 char *p;
434 /* %% sloppy */
435 /* Append the whole input filename and search backwards for
436 the directory separator. */
437 result = concat(result, argv[0], NULL);
438 p = result + strlen(result) - 1;
439 while (p >= result) {
440 if (IS_DIR_SEPARATOR(*p)) {
441 *(p+1) = '\0';
442 break;
446 fprintf(stderr, "** -> '%s'\n", result);
447 return result;
451 /* Number of extra output files that lang_specific_pre_link may generate. */
452 int lang_specific_extra_outfiles = 0; /* Not used for D. */
454 /* Table of language-specific spec functions. */
455 const struct spec_function lang_specific_spec_functions[] =
457 { "d-all-sources", d_all_sources_spec_function },
458 { "d-output-prefix", d_output_prefix_spec_function },
459 { 0, 0 }