1 /* $TOG: imake.c /main/97 1997/06/20 20:23:51 kaleb $ */
3 /***************************************************************************
7 * Add the value of BOOTSTRAPCFLAGS to the cpp_argv table so that it will *
8 * be passed to the template file. *
10 ***************************************************************************/
11 /* $XFree86: xc/config/imake/imake.c,v 3.13.2.16 1998/03/01 00:34:54 dawes Exp $ */
15 Copyright (c) 1985, 1986, 1987 X Consortium
17 Permission is hereby granted, free of charge, to any person obtaining a copy
18 of this software and associated documentation files (the "Software"), to deal
19 in the Software without restriction, including without limitation the rights
20 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 copies of the Software, and to permit persons to whom the Software is
22 furnished to do so, subject to the following conditions:
24 The above copyright notice and this permission notice shall be included in
25 all copies or substantial portions of the Software.
27 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
31 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 Except as contained in this notice, the name of the X Consortium shall not be
35 used in advertising or otherwise to promote the sale, use or other dealings
36 in this Software without prior written authorization from the X Consortium.
41 * While a guest engineer at Project Athena, MIT
43 * imake: the include-make program.
45 * Usage: imake [-Idir] [-Ddefine] [-T template] [-f imakefile ] [-C Imakefile.c ] [-s] [-e] [-v] [make flags]
47 * Imake takes a template file (Imake.tmpl) and a prototype (Imakefile)
48 * and runs cpp on them producing a Makefile. It then optionally runs make
51 * -D define. Same as cpp -D argument.
52 * -I Include directory. Same as cpp -I argument.
53 * -T template. Designate a template other
55 * -f specify the Imakefile file
56 * -C specify the name to use instead of Imakefile.c
57 * -s[F] show. Show the produced makefile on the standard
58 * output. Make is not run is this case. If a file
59 * argument is provided, the output is placed there.
60 * -e[F] execute instead of show; optionally name Makefile F
61 * -v verbose. Show the make command line executed.
63 * Environment variables:
65 * IMAKEINCLUDE Include directory to use in addition to "."
66 * IMAKECPP Cpp to use instead of /lib/cpp
67 * IMAKEMAKE make program to use other than what is
68 * found by searching the $PATH variable.
70 * imake reads the entire cpp output into memory and then scans it
71 * for occurences of "@@". If it encounters them, it replaces it with
72 * a newline. It also trims any trailing white space on output lines
73 * (because make gets upset at them). This helps when cpp expands
74 * multi-line macros but you want them to appear on multiple lines.
75 * It also changes occurences of "XCOMM" to "#", to avoid problems
76 * with treating commands as invalid preprocessor commands.
78 * The macros MAKEFILE and MAKE are provided as macros
79 * to make. MAKEFILE is set to imake's makefile (not the constructed,
80 * preprocessed one) and MAKE is set to argv[0], i.e. the name of
83 * Theory of operation:
84 * 1. Determine the name of the imakefile from the command line (-f)
85 * or from the content of the current directory (Imakefile or imakefile).
86 * Call this <imakefile>. This gets added to the arguments for
87 * make as MAKEFILE=<imakefile>.
88 * 2. Determine the name of the template from the command line (-T)
89 * or the default, Imake.tmpl. Call this <template>
90 * 3. Determine the name of the imakeCfile from the command line (-C)
91 * or the default, Imakefile.c. Call this <imakeCfile>
92 * 4. Store lines of input into <imakeCfile>:
93 * - A c-style comment header (see ImakefileCHeader below), used
94 * to recognize temporary files generated by imake.
95 * - If DEFAULT_OS_NAME is defined, format the utsname struct and
96 * call the result <defaultOsName>. Add:
97 * #define DefaultOSName <defaultOsName>
98 * - If DEFAULT_OS_MAJOR_REV is defined, format the utsname struct
99 * and call the result <defaultOsMajorVersion>. Add:
100 * #define DefaultOSMajorVersion <defaultOsMajorVersion>
101 * - If DEFAULT_OS_MINOR_REV is defined, format the utsname struct
102 * and call the result <defaultOsMinorVersion>. Add:
103 * #define DefaultOSMinorVersion <defaultOsMinorVersion>
104 * - If DEFAULT_OS_TEENY_REV is defined, format the utsname struct
105 * and call the result <defaultOsTeenyVersion>. Add:
106 * #define DefaultOSTeenyVersion <defaultOsTeenyVersion>
107 * - If DEFAULT_MACHINE_ARCITECTURE is defined, format the utsname struct
108 * and define the corresponding macro. (For example on the amiga,
109 * this will define amiga in addition to m68k).
110 * - If the file "localdefines" is readable in the current
111 * directory, print a warning message to stderr and add:
112 * #define IMAKE_LOCAL_DEFINES "localdefines"
113 * #include IMAKE_LOCAL_DEFINES
114 * - If the file "admindefines" is readable in the current
115 * directory, print a warning message to stderr and add:
116 * #define IMAKE_ADMIN_DEFINES "admindefines"
117 * #include IMAKE_ADMIN_DEFINES
118 * - The following lines:
119 * #define INCLUDE_IMAKEFILE < <imakefile> >
120 * #define IMAKE_TEMPLATE " <template> "
121 * #include IMAKE_TEMPLATE
122 * - If the file "adminmacros" is readable in the current
123 * directory, print a warning message to stderr and add:
124 * #define IMAKE_ADMIN_MACROS "adminmacros"
125 * #include IMAKE_ADMIN_MACROS
126 * - If the file "localmacros" is readable in the current
127 * directory, print a warning message to stderr and add:
128 * #define IMAKE_LOCAL_MACROS "localmacros"
129 * #include IMAKE_LOCAL_MACROS
130 * 5. Start up cpp and provide it with this file.
131 * Note that the define for INCLUDE_IMAKEFILE is intended for
132 * use in the template file. This implies that the imake is
133 * useless unless the template file contains at least the line
134 * #include INCLUDE_IMAKEFILE
135 * 6. Gather the output from cpp, and clean it up, expanding @@ to
136 * newlines, stripping trailing white space, cpp control lines,
137 * and extra blank lines, and changing XCOMM to #. This cleaned
138 * output is placed in a new file, default "Makefile", but can
139 * be specified with -s or -e options.
140 * 7. Optionally start up make on the resulting file.
142 * The design of the template makefile should therefore be:
143 * <set global macros like CFLAGS, etc.>
144 * <include machine dependent additions>
145 * #include INCLUDE_IMAKEFILE
146 * <add any global targets like 'clean' and long dependencies>
148 #if defined(__FreeBSD__) || defined(__NetBSD__)
149 /* This needs to be before _POSIX_SOURCE gets defined */
150 # include <sys/param.h>
151 # include <sys/types.h>
152 # include <sys/sysctl.h>
156 #ifndef X_NOT_STDC_ENV
161 # include "Xw32defs.h"
164 # ifndef _POSIX_SOURCE
165 # define _POSIX_SOURCE
168 #include <sys/types.h>
172 # include <sys/file.h>
180 #if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
183 # define _POSIX_SOURCE
185 # undef _POSIX_SOURCE
187 #if !defined(SIGCHLD) && defined(SIGCLD)
188 # define SIGCHLD SIGCLD
190 #include <sys/stat.h>
192 # ifdef _POSIX_SOURCE
194 # include <sys/procset.h>
195 # include <sys/siginfo.h>
197 # include <sys/wait.h>
199 # define _POSIX_SOURCE
200 # include <sys/wait.h>
201 # undef _POSIX_SOURCE
203 # define waitCode(w) WEXITSTATUS(w)
204 # define waitSig(w) WTERMSIG(w)
205 typedef int waitType;
206 #else /* X_NOT_POSIX */
208 # define waitCode(w) (((w) >> 8) & 0x7f)
209 # define waitSig(w) ((w) & 0xff)
210 typedef int waitType;
213 # include <process.h>
214 typedef int waitType;
216 # include <sys/wait.h>
217 # define waitCode(w) ((w).w_T.w_Retcode)
218 # define waitSig(w) ((w).w_T.w_Termsig)
219 typedef union wait waitType;
223 # define WIFSIGNALED(w) waitSig(w)
226 # define WIFEXITED(w) waitCode(w)
228 #endif /* X_NOT_POSIX */
229 #ifndef X_NOT_STDC_ENV
232 char *malloc(), *realloc();
235 #if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */
236 char *malloc(), *realloc();
238 #ifdef X_NOT_STDC_ENV
239 extern char *getenv();
242 #ifdef X_NOT_STDC_ENV
246 #define USE_FREOPEN 1
249 #if !(defined(X_NOT_STDC_ENV) || (defined(sun) && !defined(SVR4)) || defined(macII))
250 #define USE_STRERROR 1
253 #define USE_STRERROR 1
256 #include <sys/utsname.h>
260 # define SYS_NMLN _SYS_NMLN
262 # define SYS_NMLN 257
269 * is strstr() in <strings.h> on X_NOT_STDC_ENV?
270 * are there any X_NOT_STDC_ENV machines left in the world?
273 #include "imakemdep.h"
276 * This define of strerror is copied from (and should be identical to)
277 * Xos.h, which we don't want to include here for bootstrapping reasons.
281 extern char *sys_errlist[];
283 # define strerror(n) \
284 (((n) >= 0 && (n) < sys_nerr) ? sys_errlist[n] : "unknown error")
291 #ifdef FIXUP_CPP_WHITESPACE
293 # ifdef INLINE_SYNTAX
297 #ifdef MAGIC_MAKE_VARS
303 * Some versions of cpp reduce all tabs in macro expansion to a single
304 * space. In addition, the escaped newline may be replaced with a
305 * space instead of being deleted. Blech.
307 #ifdef FIXUP_CPP_WHITESPACE
308 void KludgeOutputLine(), KludgeResetRule();
310 # define KludgeOutputLine(arg)
311 # define KludgeResetRule()
314 typedef unsigned char boolean;
318 # define DEFAULT_CC "cc"
323 # define DEFAULT_CPP CPP_PROGRAM
325 # define DEFAULT_CPP "/lib/cpp"
332 char *tmpMakefile = "/tmp/Imf.XXXXXX";
333 char *tmpImakefile = "/tmp/IIf.XXXXXX";
334 char *make_argv[ ARGUMENTS ] = {
344 char *Imakefile = NULL;
345 char *Makefile = "Makefile";
346 char *Template = "Imake.tmpl";
347 char *ImakefileC = "Imakefile.c";
348 boolean haveImakefileC = FALSE;
349 char *cleanedImakefile = NULL;
351 char *FindImakefile();
353 char *CleanCppInput();
356 void LogFatalI(), LogFatal(), LogMsg();
364 void CheckImakefileC();
367 void CleanCppOutput();
371 boolean verbose = FALSE;
380 char makeMacro[ BUFSIZ ];
381 char makefileMacro[ BUFSIZ ];
387 Imakefile = FindImakefile(Imakefile);
388 CheckImakefileC(ImakefileC);
390 tmpMakefile = Makefile;
392 tmpMakefile = Strdup(tmpMakefile);
393 (void) mktemp(tmpMakefile);
396 AddMakeArg( tmpMakefile );
397 sprintf(makeMacro, "MAKE=%s", program);
398 AddMakeArg( makeMacro );
399 sprintf(makefileMacro, "MAKEFILE=%s", Imakefile);
400 AddMakeArg( makefileMacro );
402 if ((tmpfd = fopen(tmpMakefile, "w+")) == NULL)
403 LogFatal("Cannot create temporary file %s.", tmpMakefile);
405 cleanedImakefile = CleanCppInput(Imakefile);
406 cppit(cleanedImakefile, Template, ImakefileC, tmpfd, tmpMakefile);
409 if (Makefile == NULL)
425 while ((red = fread(buf, 1, BUFSIZ, fd)) > 0)
426 writetmpfile(stdout, buf, red, "stdout");
428 LogFatal("Cannot read %s.", tmpMakefile);
434 if (tmpMakefile != Makefile)
436 if (cleanedImakefile && cleanedImakefile != Imakefile)
437 unlink(cleanedImakefile);
442 #ifdef SIGNALRETURNSINT
451 LogFatalI("Signal %d.", sig);
455 * Initialize some variables.
463 while (make_argv[ make_argindex ] != NULL)
466 while (cpp_argv[ cpp_argindex ] != NULL)
470 * See if the standard include directory is different than
471 * the default. Or if cpp is not the default. Or if the make
472 * found by the PATH variable is not the default.
474 if (p = getenv("IMAKEINCLUDE")) {
475 if (*p != '-' || *(p+1) != 'I')
476 LogFatal("Environment var IMAKEINCLUDE %s",
477 "must begin with -I");
485 if (p = getenv("IMAKECPP"))
487 if (p = getenv("IMAKEMAKE"))
490 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
491 signal(SIGINT, catch);
493 signal(SIGCHLD, SIG_DFL);
502 if (make_argindex >= ARGUMENTS-1)
503 LogFatal("Out of internal storage.", "");
504 make_argv[ make_argindex++ ] = arg;
505 make_argv[ make_argindex ] = NULL;
513 if (cpp_argindex >= ARGUMENTS-1)
514 LogFatal("Out of internal storage.", "");
515 cpp_argv[ cpp_argindex++ ] = arg;
516 cpp_argv[ cpp_argindex ] = NULL;
526 * Now gather the arguments for make
528 for(argc--, argv++; argc; argc--, argv++) {
530 * We intercept these flags.
532 if (argv[0][0] == '-') {
533 if (argv[0][1] == 'D') {
535 } else if (argv[0][1] == 'I') {
537 } else if (argv[0][1] == 'f') {
539 Imakefile = argv[0]+2;
543 LogFatal("No description arg after -f flag", "");
546 } else if (argv[0][1] == 's') {
548 Makefile = ((argv[0][2] == '-') && !argv[0][3]) ?
553 LogFatal("No description arg after -s flag", "");
554 Makefile = ((argv[0][0] == '-') && !argv[0][1]) ?
558 } else if (argv[0][1] == 'e') {
559 Makefile = (argv[0][2] ? argv[0]+2 : NULL);
561 } else if (argv[0][1] == 'T') {
563 Template = argv[0]+2;
567 LogFatal("No description arg after -T flag", "");
570 } else if (argv[0][1] == 'C') {
572 ImakefileC = argv[0]+2;
576 LogFatal("No imakeCfile arg after -C flag", "");
577 ImakefileC = argv[0];
579 } else if (argv[0][1] == 'v') {
597 AddCppArg(ImakefileC);
601 FindImakefile(Imakefile)
605 if (access(Imakefile, R_OK) < 0)
606 LogFatal("Cannot find %s.", Imakefile);
608 if (access("Imakefile", R_OK) < 0)
609 if (access("imakefile", R_OK) < 0)
610 LogFatal("No description file.", "");
612 Imakefile = "imakefile";
614 Imakefile = "Imakefile";
625 LogFatal(s, (char *)(long)i);
632 static boolean entered = FALSE;
639 fprintf(stderr, " Stop.\n");
648 int error_number = errno;
651 fprintf(stderr, "%s: ", program);
652 fprintf(stderr, "%s\n", strerror(error_number));
654 fprintf(stderr, "%s: ", program);
655 fprintf(stderr, x0, x1);
656 fprintf(stderr, "\n");
663 for (; *argv; argv++)
664 fprintf(stderr, "%s ", *argv);
665 fprintf(stderr, "\n");
668 #define ImakefileCHeader "/* imake - temporary file */"
671 CheckImakefileC(masterc)
677 if (access(masterc, F_OK) == 0) {
678 inFile = fopen(masterc, "r");
680 LogFatal("Refuse to overwrite: %s", masterc);
681 if ((fgets(mkcbuf, sizeof(mkcbuf), inFile) &&
682 strncmp(mkcbuf, ImakefileCHeader,
683 sizeof(ImakefileCHeader)-1)))
686 LogFatal("Refuse to overwrite: %s", masterc);
692 #define LocalDefineFmt "#define %s \"%s\"\n"
693 #define IncludeFmt "#include %s\n"
694 #define ImakeDefSym "INCLUDE_IMAKEFILE"
695 #define ImakeTmplSym "IMAKE_TEMPLATE"
696 #define OverrideWarning "Warning: local file \"%s\" overrides global macros."
699 optional_include(inFile, defsym, fname)
705 if (access(fname, R_OK) == 0) {
706 LogMsg(OverrideWarning, fname);
707 return (fprintf(inFile, LocalDefineFmt, defsym, fname) < 0 ||
708 fprintf(inFile, IncludeFmt, defsym) < 0);
714 doit(outfd, cmd, argv)
723 * Fork and exec the command.
727 dup2(fileno(outfd), 1);
728 status = _spawnvp(_P_WAIT, cmd, argv);
730 LogFatal("Cannot spawn %s.", cmd);
732 LogFatalI("Exit code %d.", status);
736 LogFatal("Cannot fork.", "");
737 if (pid) { /* parent... simply wait */
738 while (wait(&status) > 0) {
740 if (WIFSIGNALED(status))
741 LogFatalI("Signal %d.", waitSig(status));
742 if (WIFEXITED(status) && waitCode(status))
743 LogFatalI("Exit code %d.", waitCode(status));
746 else { /* child... dup and exec cmd */
750 dup2(fileno(outfd), 1);
752 LogFatal("Cannot exec %s.", cmd);
759 parse_utsname(name, fmt, result, msg)
760 struct utsname *name;
765 char buf[SYS_NMLN * 5 + 1];
769 /* Assemble all the pieces into a buffer. */
770 for (arg = 0; fmt[arg] != ' '; arg++)
772 /* Our buffer is only guaranteed to hold 5 arguments. */
781 strcpy(ptr, name->sysname);
788 strcpy(ptr, name->nodename);
795 strcpy(ptr, name->release);
802 strcpy(ptr, name->version);
809 strcpy(ptr, name->machine);
818 /* Just in case... */
819 if (strlen(buf) >= sizeof(buf))
820 LogFatal("Buffer overflow parsing uname.", "");
822 /* Parse the buffer. The sscanf() return value is rarely correct. */
824 (void) sscanf(buf, fmt + arg + 1, result);
827 /* Trim leading 0's and periods from version names. The 0's cause
828 the number to be interpreted as octal numbers. Some version strings
829 have the potential for different numbers of .'s in them.
837 if (p != 0 && *p != '\0')
839 while ((*p == '0' || *p == '.') && *(p + 1) != '\0')
849 "#include <stdio.h>\n"
850 "#include <ctype.h>\n"
853 "#pragma weak gnu_get_libc_version\n"
854 "#pragma weak __libc_version\n"
855 "#pragma weak __linux_C_lib_version\n"
857 "asm (\".weak gnu_get_libc_version\");\n"
858 "asm (\".weak __libc_version\");\n"
859 "asm (\".weak __linux_C_lib_version\");\n"
862 "extern const char * gnu_get_libc_version (void);\n"
863 "extern const char * __linux_C_lib_version;\n"
864 "extern const char __libc_version [];\n"
869 " int libcmajor = 0, libcminor = 0, libcteeny = 0;\n"
871 " if (((&__linux_C_lib_version != 0)\n"
872 " && ((&__libc_version != 0) || (gnu_get_libc_version != 0)))\n"
873 " || (!(&__linux_C_lib_version != 0) && !(&__libc_version != 0)\n"
874 " && !(gnu_get_libc_version != 0)))\n"
882 " const char * ptr;\n"
883 " int glibcmajor = 0;\n"
885 " if (gnu_get_libc_version != 0)\n"
887 " ptr = gnu_get_libc_version ();\n"
890 " else if (&__libc_version != 0)\n"
892 " ptr = __libc_version;\n"
896 " ptr = __linux_C_lib_version;\n"
898 " while (!isdigit (*ptr))\n"
901 " sscanf (ptr, \"%d.%d.%d\", &libcmajor, &libcminor, &libcteeny);\n"
902 " libcmajor += glibcmajor;\n"
905 " printf(\"#define DefaultLinuxCLibMajorVersion %d\\n\", libcmajor);\n"
906 " printf(\"#define DefaultLinuxCLibMinorVersion %d\\n\", libcminor);\n"
907 " printf(\"#define DefaultLinuxCLibTeenyVersion %d\\n\", libcteeny);\n"
913 static void get_libc_version(inFile)
916 char *aout = tmpnam (NULL);
918 const char *format = "%s -o %s -x c -";
926 len = strlen (aout) + strlen (format) + strlen (cc);
927 if (len < 128) len = 128;
928 command = alloca (len);
930 if (snprintf (command , len, format, cc, aout) == len)
933 fp = popen (command, "w");
934 if (fp == NULL || fprintf (fp, "%s\n", libc_c) < 0
938 fp = popen (aout, "r");
942 while (fgets (command, len, fp))
943 fprintf (inFile, command);
951 static void get_ld_version(inFile)
954 FILE* ldprog = popen ("ld -v", "r");
956 int ldmajor, ldminor;
961 } while (c != EOF && !isdigit (c));
963 (void) fscanf (ldprog, "%d.%d", &ldmajor, &ldminor);
964 fprintf(inFile, "#define DefaultLinuxBinUtilsMajorVersion %d\n",
965 ldmajor * 10 + ldminor);
972 #define PATH_MAX 1024
976 static void get_gcc_incdir(inFile)
979 static char* gcc_path[] = {
980 #if defined(linux) || defined(__OpenBSD__)
981 "/usr/bin/cc", /* for Linux PostIncDir */
983 "/usr/local/bin/gcc",
994 for (i = 0; i < sizeof gcc_path / sizeof gcc_path[0]; i++) {
995 if (lstat (gcc_path[i], &sb) == 0) {
996 strcpy (cmd, gcc_path[i]);
997 strcat (cmd, " --print-libgcc-file-name");
998 if ((gccproc = popen (cmd, "r")) != NULL) {
999 if (fgets (buf, PATH_MAX, gccproc) != NULL) {
1000 ptr = strstr (buf, "libgcc.a");
1001 if (ptr) strcpy (ptr, "include");
1003 (void) pclose (gccproc);
1009 fprintf (inFile, "#define DefaultGccIncludeDir %s\n", buf);
1014 define_os_defaults(inFile)
1017 #if !defined(WIN32) && !defined(__EMX__)
1018 #if (defined(DEFAULT_OS_NAME) || defined(DEFAULT_OS_MAJOR_REV) || \
1019 defined(DEFAULT_OS_MINOR_REV) || defined(DEFAUL_OS_TEENY_REV))
1020 struct utsname name;
1021 char buf[SYS_NMLN * 5 + 1];
1023 /* Obtain the system information. */
1024 if (uname(&name) < 0)
1025 LogFatal("Cannot invoke uname", "");
1027 # ifdef DEFAULT_OS_NAME
1028 parse_utsname(&name, DEFAULT_OS_NAME, buf,
1029 "Bad DEFAULT_OS_NAME syntax %s");
1030 # ifdef DEFAULT_OS_NAME_FROB
1031 DEFAULT_OS_NAME_FROB(buf, sizeof buf);
1034 fprintf(inFile, "#define DefaultOSName %s\n", buf);
1037 # ifdef DEFAULT_OS_MAJOR_REV
1038 parse_utsname(&name, DEFAULT_OS_MAJOR_REV, buf,
1039 "Bad DEFAULT_OS_MAJOR_REV syntax %s");
1040 # ifdef DEFAULT_OS_MAJOR_REV_FROB
1041 DEFAULT_OS_MAJOR_REV_FROB(buf, sizeof buf);
1043 fprintf(inFile, "#define DefaultOSMajorVersion %s\n",
1044 *buf ? trim_version(buf) : "0");
1047 # ifdef DEFAULT_OS_MINOR_REV
1048 parse_utsname(&name, DEFAULT_OS_MINOR_REV, buf,
1049 "Bad DEFAULT_OS_MINOR_REV syntax %s");
1050 # ifdef DEFAULT_OS_MINOR_REV_FROB
1051 DEFAULT_OS_MINOR_REV_FROB(buf, sizeof buf);
1053 fprintf(inFile, "#define DefaultOSMinorVersion %s\n",
1054 *buf ? trim_version(buf) : "0");
1057 # ifdef DEFAULT_OS_TEENY_REV
1058 parse_utsname(&name, DEFAULT_OS_TEENY_REV, buf,
1059 "Bad DEFAULT_OS_TEENY_REV syntax %s");
1060 # ifdef DEFAULT_OS_TEENY_REV_FROB
1061 DEFAULT_OS_TEENY_REV_FROB(buf, sizeof buf);
1063 fprintf(inFile, "#define DefaultOSTeenyVersion %s\n",
1064 *buf ? trim_version(buf) : "0");
1066 # ifdef DEFAULT_MACHINE_ARCHITECTURE
1067 parse_utsname(&name, DEFAULT_MACHINE_ARCHITECTURE, buf,
1068 "Bad DEFAULT_MACHINE_ARCHITECTURE %s");
1069 fprintf(inFile, "#ifndef %s\n# define %s\n#endif\n", buf, buf);
1073 get_libc_version (inFile);
1074 get_ld_version(inFile);
1076 get_gcc_incdir(inFile);
1082 cppit(imakefile, template, masterc, outfd, outfname)
1091 haveImakefileC = TRUE;
1092 inFile = fopen(masterc, "w");
1094 LogFatal("Cannot open %s for output.", masterc);
1095 if (fprintf(inFile, "%s\n", ImakefileCHeader) < 0 ||
1096 define_os_defaults(inFile) ||
1097 optional_include(inFile, "IMAKE_LOCAL_DEFINES", "localdefines") ||
1098 optional_include(inFile, "IMAKE_ADMIN_DEFINES", "admindefines") ||
1099 fprintf(inFile, "#define %s <%s>\n", ImakeDefSym, imakefile) < 0 ||
1100 fprintf(inFile, LocalDefineFmt, ImakeTmplSym, template) < 0 ||
1101 fprintf(inFile, IncludeFmt, ImakeTmplSym) < 0 ||
1102 optional_include(inFile, "IMAKE_ADMIN_MACROS", "adminmacros") ||
1103 optional_include(inFile, "IMAKE_LOCAL_MACROS", "localmacros") ||
1106 LogFatal("Cannot write to %s.", masterc);
1110 doit(outfd, cpp, cpp_argv);
1111 CleanCppOutput(outfd, outfname);
1117 doit(NULL, make_argv[0], make_argv);
1121 CleanCppInput(imakefile)
1124 FILE *outFile = NULL;
1126 char *buf, /* buffer for file content */
1127 *pbuf, /* walking pointer to buf */
1128 *punwritten, /* pointer to unwritten portion of buf */
1129 *ptoken, /* pointer to # token */
1130 *pend, /* pointer to end of # token */
1131 savec; /* temporary character holder */
1136 * grab the entire file.
1138 if (!(inFile = fopen(imakefile, "r")))
1139 LogFatal("Cannot open %s for input.", imakefile);
1140 if (fstat(fileno(inFile), &st) < 0)
1141 LogFatal("Cannot stat %s for size.", imakefile);
1142 buf = Emalloc((int)st.st_size+3);
1143 count = fread(buf + 2, 1, st.st_size, inFile);
1144 if (count == 0 && st.st_size != 0)
1145 LogFatal("Cannot read %s:", imakefile);
1149 buf[count + 2] = '\0';
1151 punwritten = pbuf = buf + 2;
1153 /* for compatibility, replace make comments for cpp */
1154 if (*pbuf == '#' && pbuf[-1] == '\n' && pbuf[-2] != '\\') {
1156 while (*ptoken == ' ' || *ptoken == '\t')
1159 while (*pend && *pend != ' ' && *pend != '\t' && *pend != '\n')
1163 if (strcmp(ptoken, "define") &&
1164 strcmp(ptoken, "if") &&
1165 strcmp(ptoken, "ifdef") &&
1166 strcmp(ptoken, "ifndef") &&
1167 strcmp(ptoken, "include") &&
1168 strcmp(ptoken, "line") &&
1169 strcmp(ptoken, "else") &&
1170 strcmp(ptoken, "elif") &&
1171 strcmp(ptoken, "endif") &&
1172 strcmp(ptoken, "error") &&
1173 strcmp(ptoken, "pragma") &&
1174 strcmp(ptoken, "undef")) {
1175 if (outFile == NULL) {
1176 tmpImakefile = Strdup(tmpImakefile);
1177 (void) mktemp(tmpImakefile);
1178 outFile = fopen(tmpImakefile, "w");
1179 if (outFile == NULL)
1180 LogFatal("Cannot open %s for write.",
1183 writetmpfile(outFile, punwritten, pbuf-punwritten,
1185 if (ptoken > pbuf + 1)
1186 writetmpfile(outFile, "XCOMM", 5, tmpImakefile);
1188 writetmpfile(outFile, "XCOMM ", 6, tmpImakefile);
1189 punwritten = pbuf + 1;
1196 writetmpfile(outFile, punwritten, pbuf-punwritten, tmpImakefile);
1198 return tmpImakefile;
1205 CleanCppOutput(tmpfd, tmpfname)
1212 while(input = ReadLine(tmpfd, tmpfname)) {
1213 if (isempty(input)) {
1219 KludgeOutputLine(&input);
1220 writetmpfile(tmpfd, input, strlen(input), tmpfname);
1222 writetmpfile(tmpfd, "\n", 1, tmpfname);
1225 #ifdef NFS_STDOUT_BUG
1227 * On some systems, NFS seems to leave a large number of nulls at
1228 * the end of the file. Ralph Swick says that this kludge makes the
1231 ftruncate (fileno(tmpfd), (off_t)ftell(tmpfd));
1236 * Determine if a line has nothing in it. As a side effect, we trim white
1237 * space from the end of the line. Cpp magic cookies are also thrown away.
1238 * "XCOMM" token is transformed to "#".
1242 register char *line;
1244 register char *pend;
1247 * Check for lines of the form
1256 if (*pend == 'l' && pend[1] == 'i' && pend[2] == 'n' &&
1257 pend[3] == 'e' && pend[4] == ' ')
1259 if (isdigit(*pend)) {
1262 } while (isdigit(*pend));
1263 if (*pend == '\n' || *pend == '\0')
1265 if (*pend++ == ' ' && *pend == '"')
1271 for (pend = line; *pend; pend++) {
1272 if (*pend == 'X' && pend[1] == 'C' && pend[2] == 'O' &&
1273 pend[3] == 'M' && pend[4] == 'M' &&
1274 (pend == line || pend[-1] == ' ' || pend[-1] == '\t') &&
1275 (pend[5] == ' ' || pend[5] == '\t' || pend[5] == '\0'))
1278 strcpy(pend+1, pend+5);
1280 #ifdef MAGIC_MAKE_VARS
1281 if (*pend == 'X' && pend[1] == 'V' && pend[2] == 'A' &&
1287 if (pend[4] == 'd' && pend[5] == 'e' && pend[6] == 'f' &&
1288 pend[7] >= '0' && pend[7] <= '9')
1291 sprintf(varbuf, "%0.4d", xvariable);
1292 strncpy(pend+4, varbuf, 4);
1293 xvariables[i] = xvariable;
1294 xvariable = (xvariable + 1) % 10000;
1296 else if (pend[4] == 'u' && pend[5] == 's' &&
1297 pend[6] == 'e' && pend[7] >= '0' &&
1301 sprintf(varbuf, "%0.4d", xvariables[i]);
1302 strncpy(pend+4, varbuf, 4);
1308 while (--pend >= line && (*pend == ' ' || *pend == '\t')) ;
1310 return (*line == '\0');
1315 ReadLine(tmpfd, tmpfname)
1319 static boolean initialized = FALSE;
1320 static char *buf, *pline, *end;
1321 register char *p1, *p2;
1323 if (! initialized) {
1334 if (fstat(fileno(tmpfd), &st) < 0)
1335 LogFatal("cannot stat %s for size", tmpMakefile);
1336 pline = buf = Emalloc((int)st.st_size+1);
1337 total_red = fread(buf, 1, st.st_size, tmpfd);
1338 if (total_red == 0 && st.st_size != 0)
1339 LogFatal("cannot read %s", tmpMakefile);
1340 end = buf + total_red;
1343 #if defined(SYSV) || defined(WIN32) || defined(USE_FREOPEN)
1344 tmpfd = freopen(tmpfname, "w+", tmpfd);
1346 if (! tmpfd) /* if failed try again */
1347 tmpfd = freopen(tmpfname, "w+", fp);
1350 LogFatal("cannot reopen %s\n", tmpfname);
1352 ftruncate(fileno(tmpfd), (off_t) 0);
1355 fprintf (tmpfd, "# Makefile generated by imake - do not edit!\n");
1356 fprintf (tmpfd, "# %s\n",
1357 "$TOG: imake.c /main/97 1997/06/20 20:23:51 kaleb $");
1360 for (p1 = pline; p1 < end; p1++) {
1361 if (*p1 == '@' && *(p1+1) == '@'
1362 /* ignore ClearCase version-extended pathnames */
1363 && !(p1 != pline && !isspace(*(p1-1)) && *(p1+2) == '/'))
1366 p1++; /* skip over second @ */
1369 else if (*p1 == '\n') { /* real EOL */
1371 if (p1 > pline && p1[-1] == '\r')
1380 * return NULL at the end of the file.
1382 p2 = (pline == p1 ? NULL : pline);
1388 writetmpfile(fd, buf, cnt, fname)
1394 if (fwrite(buf, sizeof(char), cnt, fd) == -1)
1395 LogFatal("Cannot write to %s.", fname);
1404 if ((p = malloc(size)) == NULL)
1405 LogFatalI("Cannot allocate %d bytes", size);
1409 #ifdef FIXUP_CPP_WHITESPACE
1411 KludgeOutputLine(pline)
1415 char quotechar = '\0';
1418 case '#': /*Comment - ignore*/
1420 case '\t': /*Already tabbed - ignore it*/
1422 case ' ': /*May need a tab*/
1424 # ifdef INLINE_SYNTAX
1425 if (*p == '<' && p[1] == '<') { /* inline file close */
1432 * The following cases should not be treated as beginning of
1434 * variable := name (GNU make)
1435 * variable = .*:.* (':' should be allowed as value)
1436 * sed 's:/a:/b:' (: used in quoted values)
1440 if (quotechar == '\\' ||
1465 # ifdef REMOVE_CPP_LEADSPACE
1466 if (!InRule && **pline == ' ') {
1467 while (**pline == ' ')
1472 # ifdef INLINE_SYNTAX
1474 if (p[1] == '<') /* inline file start */
1481 while (**pline == ' ')
1488 if (InRule && **pline == ' ')
1499 #endif /* FIXUP_CPP_WHITESPACE */
1505 register char *new = Emalloc(strlen(cp) + 1);