|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.