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