|
|
1.1 root 1: /* G++ preliminary semantic processing for the compiler driver.
2: Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3: Contributed by Brendan Kehoe ([email protected]).
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21: /* This program is a wrapper to the main `gcc' driver. For GNU C++,
22: we need to do two special things: a) append `-lg++' in situations
23: where it's appropriate, to link in libg++, and b) add `-xc++'..`-xnone'
24: around file arguments named `foo.c' or `foo.i'. So, we do all of
25: this semantic processing then just exec gcc with the new argument
26: list.
27:
28: We used to do all of this in a small shell script, but many users
29: found the performance of this as a shell script to be unacceptable.
30: In situations where your PATH has a lot of NFS-mounted directories,
31: using a script that runs sed and other things would be a nasty
32: performance hit. With this program, we never search the PATH at all. */
33:
34: #include "config.h"
35: #ifdef __STDC__
36: #include <stdarg.h>
37: #else
38: #include <varargs.h>
39: #endif
40: #include <stdio.h>
41: #include <sys/types.h>
42: #include <sys/file.h> /* May get R_OK, etc. on some systems. */
43: #include <errno.h>
44:
45: /* Defined to the name of the compiler; if using a cross compiler, the
46: Makefile should compile this file with the proper name
47: (e.g., "i386-aout-gcc"). */
48: #ifndef GCC_NAME
49: #define GCC_NAME "gcc"
50: #endif
51:
52: /* This bit is set if we saw a `-xfoo' language specification. */
53: #define LANGSPEC (1<<1)
54: /* This bit is set if they did `-lm' or `-lmath'. */
55: #define MATHLIB (1<<2)
56:
57: /* On MSDOS, write temp files in current dir
58: because there's no place else we can expect to use. */
59: #ifdef __MSDOS__
60: #ifndef P_tmpdir
61: #define P_tmpdir "."
62: #endif
63: #ifndef R_OK
64: #define R_OK 4
65: #define W_OK 2
66: #define X_OK 1
67: #endif
68: #endif
69:
70: #ifndef VPROTO
71: #ifdef __STDC__
72: #define PVPROTO(ARGS) ARGS
73: #define VPROTO(ARGS) ARGS
74: #define VA_START(va_list,var) va_start(va_list,var)
75: #else
76: #define PVPROTO(ARGS) ()
77: #define VPROTO(ARGS) (va_alist) va_dcl
78: #define VA_START(va_list,var) va_start(va_list)
79: #endif
80: #endif
81:
82: #ifndef errno
83: extern int errno;
84: #endif
85:
86: extern int sys_nerr;
87: #if defined(bsd4_4) || defined(__NetBSD__)
88: extern const char *const sys_errlist[];
89: #else
90: extern char *sys_errlist[];
91: #endif
92:
93: /* Name with which this program was invoked. */
94: static char *programname;
95:
96: #ifdef HAVE_VPRINTF
97: /* Output an error message and exit */
98:
99: static void
100: fatal VPROTO((char *format, ...))
101: {
102: #ifndef __STDC__
103: char *format;
104: #endif
105: va_list ap;
106:
107: VA_START (ap, format);
108:
109: #ifndef __STDC__
110: format = va_arg (ap, char*);
111: #endif
112:
113: fprintf (stderr, "%s: ", programname);
114: vfprintf (stderr, format, ap);
115: va_end (ap);
116: fprintf (stderr, "\n");
117: #if 0
118: /* XXX Not needed for g++ driver. */
119: delete_temp_files ();
120: #endif
121: exit (1);
122: }
123:
124: static void
125: error VPROTO((char *format, ...))
126: {
127: #ifndef __STDC__
128: char *format;
129: #endif
130: va_list ap;
131:
132: VA_START (ap, format);
133:
134: #ifndef __STDC__
135: format = va_arg (ap, char*);
136: #endif
137:
138: fprintf (stderr, "%s: ", programname);
139: vfprintf (stderr, format, ap);
140: va_end (ap);
141:
142: fprintf (stderr, "\n");
143: }
144:
145: #else /* not HAVE_VPRINTF */
146:
147: static void
148: error (msg, arg1, arg2)
149: char *msg, *arg1, *arg2;
150: {
151: fprintf (stderr, "%s: ", programname);
152: fprintf (stderr, msg, arg1, arg2);
153: fprintf (stderr, "\n");
154: }
155:
156: static void
157: fatal (msg, arg1, arg2)
158: char *msg, *arg1, *arg2;
159: {
160: error (msg, arg1, arg2);
161: #if 0
162: /* XXX Not needed for g++ driver. */
163: delete_temp_files ();
164: #endif
165: exit (1);
166: }
167:
168: #endif /* not HAVE_VPRINTF */
169:
170: /* More 'friendly' abort that prints the line and file.
171: config.h can #define abort fancy_abort if you like that sort of thing. */
172:
173: void
174: fancy_abort ()
175: {
176: fatal ("Internal g++ abort.");
177: }
178:
179: char *
180: xmalloc (size)
181: unsigned size;
182: {
183: register char *value = (char *) malloc (size);
184: if (value == 0)
185: fatal ("virtual memory exhausted");
186: return value;
187: }
188:
189: /* Return a newly-allocated string whose contents concatenate those
190: of s1, s2, s3. */
191: static char *
192: concat (s1, s2, s3)
193: char *s1, *s2, *s3;
194: {
195: int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
196: char *result = xmalloc (len1 + len2 + len3 + 1);
197:
198: strcpy (result, s1);
199: strcpy (result + len1, s2);
200: strcpy (result + len1 + len2, s3);
201: *(result + len1 + len2 + len3) = 0;
202:
203: return result;
204: }
205:
206: static void
207: pfatal_with_name (name)
208: char *name;
209: {
210: char *s;
211:
212: if (errno < sys_nerr)
213: s = concat ("%s: ", sys_errlist[errno], "");
214: else
215: s = "cannot open %s";
216: fatal (s, name);
217: }
218:
219: #ifdef __MSDOS__
220: /* This is the common prefix we use to make temp file names. */
221: char *temp_filename;
222:
223: /* Length of the prefix. */
224: int temp_filename_length;
225:
226: /* Compute a string to use as the base of all temporary file names. */
227: static char *
228: choose_temp_base_try (try, base)
229: char *try;
230: char *base;
231: {
232: char *rv;
233: if (base)
234: rv = base;
235: else if (try == (char *)0)
236: rv = 0;
237: else if (access (try, R_OK | W_OK) != 0)
238: rv = 0;
239: else
240: rv = try;
241: return rv;
242: }
243:
244: static void
245: choose_temp_base ()
246: {
247: char *base = 0;
248: int len;
249:
250: base = choose_temp_base_try (getenv ("TMPDIR"), base);
251: base = choose_temp_base_try (getenv ("TMP"), base);
252: base = choose_temp_base_try (getenv ("TEMP"), base);
253:
254: #ifdef P_tmpdir
255: base = choose_temp_base_try (P_tmpdir, base);
256: #endif
257:
258: base = choose_temp_base_try ("/usr/tmp", base);
259: base = choose_temp_base_try ("/tmp", base);
260:
261: /* If all else fails, use the current directory! */
262: if (base == (char *)0)
263: base = "./";
264:
265: len = strlen (base);
266: temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
267: strcpy (temp_filename, base);
268: if (len > 0 && temp_filename[len-1] != '/')
269: temp_filename[len++] = '/';
270: strcpy (temp_filename + len, "ccXXXXXX");
271:
272: mktemp (temp_filename);
273: temp_filename_length = strlen (temp_filename);
274: if (temp_filename_length == 0)
275: abort ();
276: }
277:
278: static void
279: perror_exec (name)
280: char *name;
281: {
282: char *s;
283:
284: if (errno < sys_nerr)
285: s = concat ("installation problem, cannot exec %s: ",
286: sys_errlist[errno], "");
287: else
288: s = "installation problem, cannot exec %s";
289: error (s, name);
290: }
291:
292: /* This is almost exactly what's in gcc.c:pexecute for MSDOS. */
293: void
294: run_dos (program, argv)
295: char *program;
296: char *argv[];
297: {
298: char *scmd, *rf;
299: FILE *argfile;
300: int i;
301:
302: choose_temp_base (); /* not in gcc.c */
303:
304: scmd = (char *) malloc (strlen (program) + strlen (temp_filename) + 10);
305: rf = scmd + strlen (program) + 6;
306: sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
307:
308: argfile = fopen (rf, "w");
309: if (argfile == 0)
310: pfatal_with_name (rf);
311:
312: for (i=1; argv[i]; i++)
313: {
314: char *cp;
315: for (cp = argv[i]; *cp; cp++)
316: {
317: if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
318: fputc ('\\', argfile);
319: fputc (*cp, argfile);
320: }
321: fputc ('\n', argfile);
322: }
323: fclose (argfile);
324:
325: i = system (scmd);
326:
327: remove (rf);
328:
329: if (i == -1)
330: perror_exec (program);
331: }
332: #endif /* __MSDOS__ */
333:
334: int
335: main (argc, argv)
336: int argc;
337: char **argv;
338: {
339: register int i, j = 0;
340: register char *p;
341: int verbose = 0;
342:
343: /* This will be NULL if we encounter a situation where we should not
344: link in libg++. */
345: char *library = "-lg++";
346:
347: /* Used to track options that take arguments, so we don't go wrapping
348: those with -xc++/-xnone. */
349: char *quote = NULL;
350:
351: /* The new argument list will be contained in this. */
352: char **arglist;
353:
354: /* The name of the compiler we will want to run---by default, it
355: will be the definition of `GCC_NAME', e.g., `gcc'. */
356: char *gcc = GCC_NAME;
357:
358: /* Non-zero if we saw a `-xfoo' language specification on the
359: command line. Used to avoid adding our own -xc++ if the user
360: already gave a language for the file. */
361: int saw_speclang = 0;
362:
363: /* Non-zero if we saw `-lm' or `-lmath' on the command line. */
364: int saw_math = 0;
365:
366: /* The number of arguments being added to what's in argv. By
367: default it's one new argument (adding `-lg++'). We use this
368: to track the number of times we've inserted -xc++/-xnone as well. */
369: int added = 1;
370:
371: /* An array used to flag each argument that needs a bit set for
372: LANGSPEC or MATHLIB. */
373: int *args;
374:
375: p = argv[0] + strlen (argv[0]);
376: while (p != argv[0] && p[-1] != '/')
377: --p;
378: programname = p;
379:
380: if (argc == 1)
381: fatal ("No input files specified.\n");
382:
383: #ifndef __MSDOS__
384: /* We do a little magic to find out where the main gcc executable
385: is. If they ran us as /usr/local/bin/g++, then we will look
386: for /usr/local/bin/gcc; similarly, if they just ran us as `g++',
387: we'll just look for `gcc'. */
388: if (p != argv[0])
389: {
390: *--p = '\0';
391: gcc = (char *) malloc ((strlen (argv[0]) + 1 + strlen (GCC_NAME) + 1)
392: * sizeof (char));
393: sprintf (gcc, "%s/%s", argv[0], GCC_NAME);
394: }
395: #endif
396:
397: args = (int *) malloc (argc * sizeof (int));
398: bzero ((char *) args, argc * sizeof (int));
399:
400: for (i = 1; i < argc; i++)
401: {
402: /* If the previous option took an argument, we swallow it here. */
403: if (quote)
404: {
405: quote = NULL;
406: continue;
407: }
408:
409: if (argv[i][0] == '\0' || argv[i][1] == '\0')
410: continue;
411:
412: if (argv[i][0] == '-')
413: {
414: if (strcmp (argv[i], "-nostdlib") == 0)
415: {
416: added--;
417: library = NULL;
418: }
419: else if (strcmp (argv[i], "-lm") == 0
420: || strcmp (argv[i], "-lmath") == 0)
421: args[i] |= MATHLIB;
422: else if (strcmp (argv[i], "-v") == 0)
423: {
424: verbose = 1;
425: if (argc == 2)
426: {
427: /* If they only gave us `-v', don't try to link
428: in libg++. */
429: added--;
430: library = NULL;
431: }
432: }
433: else if (strncmp (argv[i], "-x", 2) == 0)
434: saw_speclang = 1;
435: else if (((argv[i][2] == '\0'
436: && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
437: || strcmp (argv[i], "-Tdata") == 0))
438: quote = argv[i];
439: else if (library != NULL && ((argv[i][2] == '\0'
440: && (char *) strchr ("cSEM", argv[i][1]) != NULL)
441: || strcmp (argv[i], "-MM") == 0))
442: {
443: /* Don't specify libraries if we won't link, since that would
444: cause a warning. */
445: added--;
446: library = NULL;
447: }
448: else
449: /* Pass other options through. */
450: continue;
451: }
452: else
453: {
454: int len;
455:
456: if (saw_speclang)
457: {
458: saw_speclang = 0;
459: continue;
460: }
461:
462: /* If the filename ends in .c or .i, put options around it.
463: But not if a specified -x option is currently active. */
464: len = strlen (argv[i]);
465: if (len > 2
466: && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
467: && argv[i][len - 2] == '.')
468: {
469: args[i] |= LANGSPEC;
470: added += 2;
471: }
472: }
473: }
474:
475: if (quote)
476: fatal ("argument to `%s' missing\n", quote);
477:
478: if (added)
479: {
480: arglist = (char **) malloc ((argc + added + 1) * sizeof (char *));
481:
482: for (i = 1, j = 1; i < argc; i++, j++)
483: {
484: arglist[j] = argv[i];
485:
486: /* Make sure -lg++ is before the math library, since libg++
487: itself uses those math routines. */
488: if (!saw_math && (args[i] & MATHLIB) && library)
489: {
490: saw_math = 1;
491: arglist[j] = library;
492: arglist[++j] = argv[i];
493: }
494:
495: /* Wrap foo.c and foo.i files in a language specification to
496: force the gcc compiler driver to run cc1plus on them. */
497: if (args[i] & LANGSPEC)
498: {
499: int len = strlen (argv[i]);
500: if (argv[i][len - 1] == 'i')
501: arglist[j++] = "-xc++-cpp-output";
502: else
503: arglist[j++] = "-xc++";
504: arglist[j++] = argv[i];
505: arglist[j] = "-xnone";
506: }
507: }
508:
509: /* Add `-lg++' if we haven't already done so. */
510: if (library && !saw_math)
511: arglist[j++] = library;
512:
513: arglist[j] = NULL;
514: }
515: else
516: /* No need to copy 'em all. */
517: arglist = argv;
518:
519: arglist[0] = gcc;
520:
521: if (verbose)
522: {
523: if (j == 0)
524: j = argc;
525:
526: for (i = 0; i < j; i++)
527: fprintf (stderr, " %s", arglist[i]);
528: fprintf (stderr, "\n");
529: }
530: #ifndef OS2
531: #ifdef __MSDOS__
532: run_dos (gcc, arglist);
533: #else /* !__MSDOS__ */
534: if (execvp (gcc, arglist) < 0)
535: pfatal_with_name (gcc);
536: #endif /* __MSDOS__ */
537: #else /* OS2 */
538: if (spawnvp (gcc, arglist) < 0)
539: pfatal_with_name (gcc);
540: #endif
541:
542: return 0;
543: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.