Annotation of gcc/cp/g++.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.