Annotation of GNUtools/cc/g++.c, revision 1.1

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

unix.superglobalmegacorp.com

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