source: trunk/third/gcc/cp/g++.c @ 8834

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