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