Annotation of gcc/cp/g++.c, revision 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.