imake.c revision 39f9c979
1
2/***************************************************************************
3 *                                                                         *
4 *                                Porting Note                             *
5 *                                                                         *
6 * Add the value of BOOTSTRAPCFLAGS to the cpp_argv table so that it will  *
7 * be passed to the template file.                                         *
8 *                                                                         *
9 ***************************************************************************/
10/*
11 *
12Copyright (c) 1985, 1986, 1987, 1998 The Open Group
13
14Permission to use, copy, modify, distribute, and sell this software and its
15documentation for any purpose is hereby granted without fee, provided that
16the above copyright notice appear in all copies and that both that
17copyright notice and this permission notice appear in supporting
18documentation.
19
20The above copyright notice and this permission notice shall be included in
21all copies or substantial portions of the Software.
22
23THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
27AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30Except as contained in this notice, the name of The Open Group shall not be
31used in advertising or otherwise to promote the sale, use or other dealings
32in this Software without prior written authorization from The Open Group.
33 *
34 * Original Author:
35 *	Todd Brunhoff
36 *	Tektronix, inc.
37 *	While a guest engineer at Project Athena, MIT
38 *
39 * imake: the include-make program.
40 *
41 * Usage: imake [-Idir] [-Ddefine] [-T template] [-f imakefile ] [-C Imakefile.c ] [-s] [-e] [-v] [make flags]
42 *
43 * Imake takes a template file (Imake.tmpl) and a prototype (Imakefile)
44 * and runs cpp on them producing a Makefile.  It then optionally runs make
45 * on the Makefile.
46 * Options:
47 *		-D	define.  Same as cpp -D argument.
48 *		-U	undefine.  Same as cpp -U argument.
49 *		-W	warning.  Same as cpp -W argument.
50 *		-I	Include directory.  Same as cpp -I argument.
51 *		-T	template.  Designate a template other
52 *			than Imake.tmpl
53 *		-f	specify the Imakefile file
54 *		-C	specify the name to use instead of Imakefile.c
55 *		-s[F]	show.  Show the produced makefile on the standard
56 *			output.  Make is not run is this case.  If a file
57 *			argument is provided, the output is placed there.
58 *		-e[F]	execute instead of show; optionally name Makefile F
59 *		-v	verbose.  Show the make command line executed.
60 *
61 * Environment variables:
62 *
63 *		IMAKEINCLUDE	Include directory to use in addition to "."
64 *		IMAKECPP	Cpp to use instead of /lib/cpp
65 *		IMAKEMAKE	make program to use other than what is
66 *				found by searching the $PATH variable.
67 * Other features:
68 *	imake reads the entire cpp output into memory and then scans it
69 *	for occurences of "@@".  If it encounters them, it replaces it with
70 *	a newline.  It also trims any trailing white space on output lines
71 *	(because make gets upset at them).  This helps when cpp expands
72 *	multi-line macros but you want them to appear on multiple lines.
73 *	It also changes occurences of "XCOMM" to "#", to avoid problems
74 *	with treating commands as invalid preprocessor commands.
75 *
76 *	The macros MAKEFILE and MAKE are provided as macros
77 *	to make.  MAKEFILE is set to imake's makefile (not the constructed,
78 *	preprocessed one) and MAKE is set to argv[0], i.e. the name of
79 *	the imake program.
80 *
81 * Theory of operation:
82 *   1. Determine the name of the imakefile from the command line (-f)
83 *	or from the content of the current directory (Imakefile or imakefile).
84 *	Call this <imakefile>.  This gets added to the arguments for
85 *	make as MAKEFILE=<imakefile>.
86 *   2. Determine the name of the template from the command line (-T)
87 *	or the default, Imake.tmpl.  Call this <template>
88 *   3. Determine the name of the imakeCfile from the command line (-C)
89 *	or the default, Imakefile.c.  Call this <imakeCfile>
90 *   4. Store lines of input into <imakeCfile>:
91 *	- A c-style comment header (see ImakefileCHeader below), used
92 *	  to recognize temporary files generated by imake.
93 *	- If DEFAULT_OS_NAME is defined, format the utsname struct and
94 *	  call the result <defaultOsName>.  Add:
95 *		#define DefaultOSName <defaultOsName>
96 *	- If DEFAULT_OS_MAJOR_REV is defined, format the utsname struct
97 *	  and call the result <defaultOsMajorVersion>.  Add:
98 *		#define DefaultOSMajorVersion <defaultOsMajorVersion>
99 *	- If DEFAULT_OS_MINOR_REV is defined, format the utsname struct
100 *	  and call the result <defaultOsMinorVersion>.  Add:
101 *		#define DefaultOSMinorVersion <defaultOsMinorVersion>
102 *	- If DEFAULT_OS_TEENY_REV is defined, format the utsname struct
103 *	  and call the result <defaultOsTeenyVersion>.  Add:
104 *		#define DefaultOSTeenyVersion <defaultOsTeenyVersion>
105 *	- If DEFAULT_MACHINE_ARCITECTURE is defined, format the utsname struct
106 *	  and define the corresponding macro.  (For example on the amiga,
107 *	  this will define amiga in addition to m68k).
108 *	- If the file "localdefines" is readable in the current
109 *	  directory, print a warning message to stderr and add:
110 *		#define IMAKE_LOCAL_DEFINES	"localdefines"
111 *		#include IMAKE_LOCAL_DEFINES
112 *	- If the file "admindefines" is readable in the current
113 *	  directory, print a warning message to stderr and add:
114 *		#define IMAKE_ADMIN_DEFINES	"admindefines"
115 *		#include IMAKE_ADMIN_DEFINES
116 *	- The following lines:
117 *		#define INCLUDE_IMAKEFILE	< <imakefile> >
118 *		#define IMAKE_TEMPLATE		" <template> "
119 *		#include IMAKE_TEMPLATE
120 *	- If the file "adminmacros" is readable in the current
121 *	  directory, print a warning message to stderr and add:
122 *		#define IMAKE_ADMIN_MACROS	"adminmacros"
123 *		#include IMAKE_ADMIN_MACROS
124 *	- If the file "localmacros" is readable in the current
125 *	  directory, print a warning message to stderr and add:
126 *		#define IMAKE_LOCAL_MACROS	"localmacros"
127 *		#include IMAKE_LOCAL_MACROS
128 *   5. Start up cpp and provide it with this file.
129 *	Note that the define for INCLUDE_IMAKEFILE is intended for
130 *	use in the template file.  This implies that the imake is
131 *	useless unless the template file contains at least the line
132 *		#include INCLUDE_IMAKEFILE
133 *   6. Gather the output from cpp, and clean it up, expanding @@ to
134 *	newlines, stripping trailing white space, cpp control lines,
135 *	and extra blank lines, and changing XCOMM to #.  This cleaned
136 *	output is placed in a new file, default "Makefile", but can
137 *	be specified with -s or -e options.
138 *   7. Optionally start up make on the resulting file.
139 *
140 * The design of the template makefile should therefore be:
141 *	<set global macros like CFLAGS, etc.>
142 *	<include machine dependent additions>
143 *	#include INCLUDE_IMAKEFILE
144 *	<add any global targets like 'clean' and long dependencies>
145 */
146
147#include "config.h"
148
149#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
150/* This needs to be before _POSIX_SOURCE gets defined */
151# include <sys/param.h>
152# include <sys/types.h>
153# include <sys/sysctl.h>
154#endif
155#include <stdlib.h>
156#include <stdio.h>
157#include <stdarg.h>
158#include <X11/Xfuncproto.h>
159#include <X11/Xosdefs.h>
160#include <string.h>
161#include <ctype.h>
162#ifdef WIN32
163# include "Xw32defs.h"
164#endif
165#include <sys/types.h>
166#include <fcntl.h>
167#ifdef X_NOT_POSIX
168# ifndef WIN32
169#  include <sys/file.h>
170# endif
171#else
172# include <unistd.h>
173#endif
174#ifdef ISC
175# include <unistd.h>
176#endif
177#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
178# include <signal.h>
179#else
180# define _POSIX_SOURCE
181# include <signal.h>
182# undef _POSIX_SOURCE
183#endif
184#if !defined(SIGCHLD) && defined(SIGCLD)
185# define SIGCHLD		SIGCLD
186#endif
187#include <sys/stat.h>
188#ifndef X_NOT_POSIX
189# ifdef _POSIX_SOURCE
190#  ifdef __SCO__
191#   include <sys/procset.h>
192#   include <sys/siginfo.h>
193#  endif
194#  include <sys/wait.h>
195# else
196#  define _POSIX_SOURCE
197#  include <sys/wait.h>
198#  undef _POSIX_SOURCE
199# endif
200# define waitCode(w)	WEXITSTATUS(w)
201# define waitSig(w)	WTERMSIG(w)
202typedef int		waitType;
203#else /* X_NOT_POSIX */
204# ifdef SYSV
205#  define waitCode(w)	(((w) >> 8) & 0x7f)
206#  define waitSig(w)	((w) & 0xff)
207typedef int		waitType;
208# else /* SYSV */
209#  ifdef WIN32
210#   include <process.h>
211typedef int		waitType;
212#  else
213#   include <sys/wait.h>
214#   define waitCode(w)	((w).w_T.w_Retcode)
215#   define waitSig(w)	((w).w_T.w_Termsig)
216typedef union wait	waitType;
217#  endif
218# endif
219# ifndef WIFSIGNALED
220#  define WIFSIGNALED(w) waitSig(w)
221# endif
222# ifndef WIFEXITED
223#  define WIFEXITED(w) waitCode(w)
224# endif
225#endif /* X_NOT_POSIX */
226#include <stdlib.h>
227#include <errno.h>
228#ifdef __minix_vmd
229# define USE_FREOPEN		1
230#endif
231
232#ifndef WIN32
233# include <sys/utsname.h>
234#else
235# include <windows.h>
236#endif
237#ifndef SYS_NMLN
238# ifdef _SYS_NMLN
239#  define SYS_NMLN _SYS_NMLN
240# else
241#  define SYS_NMLN 257
242# endif
243#endif
244#if defined(linux) || defined(__GNU__) || defined(__GLIBC__)
245# include <limits.h>
246# include <stdio.h>
247#endif
248#ifdef __QNX__
249# include <unix.h>
250#endif
251
252#if defined(__NetBSD__)		/* see code clock in init() below */
253# include <sys/utsname.h>
254#endif
255
256typedef unsigned char boolean;
257#define TRUE		1
258#define FALSE		0
259
260#include "imakemdep.h"
261#ifdef CROSSCOMPILE
262# include "imakemdep_cpp.h"
263#endif
264
265#if defined CROSSCOMPILE || defined FIXUP_CPP_WHITESPACE
266int InRule = FALSE;
267#endif
268#if defined CROSSCOMPILE || defined INLINE_SYNTAX
269int InInline = 0;
270#endif
271#if defined CROSSCOMPILE || defined MAGIC_MAKE_VARS
272int xvariable = 0;
273int xvariables[10];
274#endif
275
276#ifndef PATH_MAX
277# define PATH_MAX 1024
278#endif
279
280/*
281 * Some versions of cpp reduce all tabs in macro expansion to a single
282 * space.  In addition, the escaped newline may be replaced with a
283 * space instead of being deleted.  Blech.
284 */
285void KludgeOutputLine(char **), KludgeResetRule(void);
286
287#ifndef CROSSCOMPILE
288# ifdef USE_CC_E
289#  ifndef DEFAULT_CC
290#   define DEFAULT_CC "cc"
291#  endif
292# else
293#  ifndef DEFAULT_CPP
294#   ifdef CPP_PROGRAM
295#    define DEFAULT_CPP CPP_PROGRAM
296#   else
297#    define DEFAULT_CPP "/lib/cpp"
298#   endif
299#  endif
300# endif
301#endif
302
303const char *cpp = NULL;
304
305const char	*tmpMakefile;
306const char	*tmpMakefileTemplate = "/tmp/Imf.XXXXXX";
307const char	*tmpImakefile;
308const char	*tmpImakefileTemplate = "/tmp/IIf.XXXXXX";
309const char	*make_argv[ ARGUMENTS ] = {
310#ifdef WIN32
311    "nmake"
312#else
313    "make"
314#endif
315};
316
317int	make_argindex;
318int	cpp_argindex;
319const char	*Imakefile = NULL;
320const char	*Makefile = "Makefile";
321const char	*Template = "Imake.tmpl";
322const char	*ImakefileC = "Imakefile.c";
323boolean haveImakefileC = FALSE;
324const char	*cleanedImakefile = NULL;
325const char	*program;
326const char	*FindImakefile(const char *Imakefile);
327char	*ReadLine(FILE *tmpfd, const char *tmpfname);
328const char	*CleanCppInput(const char *imakefile);
329char	*Strdup(const char *cp);
330char	*Emalloc(int size);
331void	LogFatal(const char *x0, ...) _X_ATTRIBUTE_PRINTF(1, 2);
332void	LogMsg(const char *x0, ...) _X_ATTRIBUTE_PRINTF(1, 2);
333
334void	showit(FILE *fd);
335void	wrapup(void);
336void	init(void);
337void	AddMakeArg(const char *arg);
338void	AddCppArg(const char *arg);
339#ifdef CROSSCOMPILE
340char	*CrossCompileCPP(void);
341#endif
342void	SetOpts(int argc, char **argv);
343void	CheckImakefileC(const char *masterc);
344void	cppit(const char *imakefile, const char *template, const char *masterc,
345	      FILE *outfd, const char *outfname);
346void	makeit(void);
347void	CleanCppOutput(FILE *tmpfd, const char *tmpfname);
348boolean isempty(char *line);
349void	writetmpfile(FILE *fd, const char *buf, int cnt, const char *fname);
350#ifdef SIGNALRETURNSINT
351int	catch(int sig);
352#else
353void	catch(int sig);
354#endif
355void	showargs(const char **argv);
356boolean optional_include(FILE *inFile, const char *defsym, const char *fname);
357void	  doit(FILE *outfd, const char *cmd, const char **argv);
358boolean define_os_defaults(FILE *inFile);
359#ifdef CROSSCOMPILE
360static void get_cross_compile_dir(FILE *inFile);
361#endif
362#ifdef CROSSCOMPILEDIR
363const char *CrossCompileDir = CROSSCOMPILEDIR;
364#else
365const char *CrossCompileDir = "";
366#endif
367boolean CrossCompiling = FALSE;
368
369
370
371boolean verbose = FALSE;
372boolean show = TRUE;
373
374int
375main(int argc, char *argv[])
376{
377	FILE	*tmpfd = NULL;
378	char	makeMacro[ BUFSIZ ];
379	char	makefileMacro[ BUFSIZ ];
380	int	lenCrossCompileDir = 0;
381
382	program = argv[0];
383	init();
384
385	lenCrossCompileDir = strlen(CrossCompileDir);
386	if (lenCrossCompileDir) {
387	    if (lenCrossCompileDir > (PATH_MAX - 20))
388	      LogFatal("Cross compile directory path too long %s\n",
389		       CrossCompileDir);
390	    else
391		CrossCompiling = TRUE;
392	}
393
394	SetOpts(argc, argv);
395	Imakefile = FindImakefile(Imakefile);
396	CheckImakefileC(ImakefileC);
397	if (Makefile) {
398		tmpMakefile = Makefile;
399		if ((tmpfd = fopen(tmpMakefile, "w+")) == NULL)
400		   LogFatal("Cannot create temporary file %s.", tmpMakefile);
401	} else {
402#ifdef HAVE_MKSTEMP
403		int fd;
404#endif
405		char *tmpMakefileName = Strdup(tmpMakefileTemplate);
406#ifndef HAVE_MKSTEMP
407		if (mktemp(tmpMakefileName) == NULL ||
408		    (tmpfd = fopen(tmpMakefileName, "w+")) == NULL) {
409		   LogFatal("Cannot create temporary file %s.", tmpMakefileName);
410		}
411#else
412		fd = mkstemp(tmpMakefileName);
413		if (fd == -1 || (tmpfd = fdopen(fd, "w+")) == NULL) {
414		   if (fd != -1) {
415		      unlink(tmpMakefileName); close(fd);
416		   }
417		   LogFatal("Cannot create temporary file %s.", tmpMakefileName);
418		}
419#endif
420		tmpMakefile = tmpMakefileName;
421	}
422	AddMakeArg("-f");
423	AddMakeArg( tmpMakefile );
424	sprintf(makeMacro, "MAKE=%s", program);
425	AddMakeArg( makeMacro );
426	sprintf(makefileMacro, "MAKEFILE=%s", Imakefile);
427	AddMakeArg( makefileMacro );
428
429	cleanedImakefile = CleanCppInput(Imakefile);
430	cppit(cleanedImakefile, Template, ImakefileC, tmpfd, tmpMakefile);
431
432	if (show) {
433		if (Makefile == NULL)
434			showit(tmpfd);
435	} else
436		makeit();
437	wrapup();
438	exit(0);
439}
440
441void
442showit(FILE *fd)
443{
444	char	buf[ BUFSIZ ];
445	int	red;
446
447	fseek(fd, 0, 0);
448	while ((red = fread(buf, 1, BUFSIZ, fd)) > 0)
449		writetmpfile(stdout, buf, red, "stdout");
450	if (red < 0)
451	    LogFatal("Cannot read %s.", tmpMakefile);
452}
453
454void
455wrapup(void)
456{
457	if (tmpMakefile != Makefile)
458		unlink(tmpMakefile);
459	if (cleanedImakefile && cleanedImakefile != Imakefile)
460		unlink(cleanedImakefile);
461	if (haveImakefileC)
462		unlink(ImakefileC);
463}
464
465#ifdef SIGNALRETURNSINT
466int
467#else
468void
469#endif
470catch(int sig)
471{
472	errno = 0;
473	LogFatal("Signal %d.", sig);
474}
475
476/*
477 * Initialize some variables.
478 */
479void
480init(void)
481{
482	register char	*p;
483
484	make_argindex=0;
485	while (make_argv[ make_argindex ] != NULL)
486		make_argindex++;
487	cpp_argindex = 0;
488	while (cpp_argv[ cpp_argindex ] != NULL)
489		cpp_argindex++;
490
491#if defined CROSSCOMPILE
492	if (sys == netBSD)
493	  if (CrossCompiling) {
494	    LogFatal("fix imake to do crosscompiling for NetBSD\n","");
495	  } else
496#endif
497#if defined(__NetBSD__) || defined CROSSCOMPILE
498	{
499		struct utsname uts;
500		static char argument[512];
501
502		/*
503		 * Sharable imake configurations require a
504		 * machine identifier.
505		 */
506		if (uname(&uts) != 0)
507			LogFatal("uname(3) failed; can't tell what %s",
508			    "kind of machine you have.");
509
510		memset(argument, 0, sizeof(argument));
511		(void)snprintf(argument, sizeof(argument) - 1,
512		    "-D__%s__", uts.machine);
513
514		AddCppArg(argument);
515	}
516#endif /* __NetBSD__ */
517
518	/*
519	 * See if the standard include directory is different than
520	 * the default.  Or if cpp is not the default.  Or if the make
521	 * found by the PATH variable is not the default.
522	 */
523	if ((p = getenv("IMAKEINCLUDE"))) {
524		if (*p != '-' || *(p+1) != 'I')
525			LogFatal("Environment var IMAKEINCLUDE %s",
526				"must begin with -I");
527		AddCppArg(p);
528		for (; *p; p++)
529			if (*p == ' ') {
530				*p++ = '\0';
531				AddCppArg(p);
532			}
533	}
534	if ((p = getenv("IMAKECPP")))
535		cpp = p;
536	if ((p = getenv("IMAKEMAKE")))
537		make_argv[0] = p;
538
539	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
540		signal(SIGINT, catch);
541#ifdef SIGCHLD
542	signal(SIGCHLD, SIG_DFL);
543#endif
544}
545
546void
547AddMakeArg(const char *arg)
548{
549	errno = 0;
550	if (make_argindex >= ARGUMENTS-1)
551		LogFatal("Out of internal storage.");
552	make_argv[ make_argindex++ ] = arg;
553	make_argv[ make_argindex ] = NULL;
554}
555
556void
557AddCppArg(const char *arg)
558{
559	errno = 0;
560	if (cpp_argindex >= ARGUMENTS-1)
561		LogFatal("Out of internal storage.");
562	cpp_argv[ cpp_argindex++ ] = arg;
563	cpp_argv[ cpp_argindex ] = NULL;
564}
565
566void
567SetOpts(int argc, char **argv)
568{
569
570	errno = 0;
571	/*
572	 * Now gather the arguments for make
573	 */
574	for(argc--, argv++; argc; argc--, argv++) {
575	    /*
576	     * We intercept these flags.
577	     */
578	    if (argv[0][0] == '-') {
579		if (argv[0][1] == 'D') {
580		    AddCppArg(argv[0]);
581		} else if (argv[0][1] == 'I') {
582		    AddCppArg(argv[0]);
583		} else if (argv[0][1] == 'U') {
584		    AddCppArg(argv[0]);
585		} else if (argv[0][1] == 'W') {
586		    AddCppArg(argv[0]);
587		} else if (argv[0][1] == 'f') {
588		    if (argv[0][2])
589			Imakefile = argv[0]+2;
590		    else {
591			argc--, argv++;
592			if (! argc)
593			    LogFatal("No description arg after -f flag");
594			Imakefile = argv[0];
595		    }
596		} else if (argv[0][1] == 's') {
597		    if (argv[0][2])
598			Makefile = ((argv[0][2] == '-') && !argv[0][3]) ?
599			    NULL : argv[0]+2;
600		    else {
601			argc--, argv++;
602			if (!argc)
603			    LogFatal("No description arg after -s flag");
604			Makefile = ((argv[0][0] == '-') && !argv[0][1]) ?
605			    NULL : argv[0];
606		    }
607		    show = TRUE;
608		} else if (argv[0][1] == 'e') {
609		   Makefile = (argv[0][2] ? argv[0]+2 : NULL);
610		   show = FALSE;
611		} else if (argv[0][1] == 'T') {
612		    if (argv[0][2])
613			Template = argv[0]+2;
614		    else {
615			argc--, argv++;
616			if (! argc)
617			    LogFatal("No description arg after -T flag");
618			Template = argv[0];
619		    }
620		} else if (argv[0][1] == 'C') {
621		    if (argv[0][2])
622			ImakefileC = argv[0]+2;
623		    else {
624			argc--, argv++;
625			if (! argc)
626			    LogFatal("No imakeCfile arg after -C flag");
627			ImakefileC = argv[0];
628		    }
629		} else if (argv[0][1] == 'v') {
630		    verbose = TRUE;
631		} else
632		    AddMakeArg(argv[0]);
633	    } else
634		AddMakeArg(argv[0]);
635	}
636
637#ifndef CROSSCOMPILE
638# ifdef USE_CC_E
639	    if (!cpp)
640	    {
641		AddCppArg("-E");
642#  ifdef __GNUC__
643		if (verbose)
644		    AddCppArg("-v");
645#  endif
646		cpp = DEFAULT_CC;
647	    }
648# else
649	    if (!cpp)
650		cpp = DEFAULT_CPP;
651# endif
652#else
653	    if (!cpp)
654		cpp = CrossCompileCPP();
655#endif
656
657	cpp_argv[0] = cpp;
658	AddCppArg(ImakefileC);
659}
660
661const char *
662FindImakefile(const char *Imakefile)
663{
664	if (Imakefile) {
665		if (access(Imakefile, R_OK) < 0)
666			LogFatal("Cannot find %s.", Imakefile);
667	} else {
668		if (access("Imakefile", R_OK) < 0) {
669			if (access("imakefile", R_OK) < 0)
670				LogFatal("No description file.");
671			else
672				Imakefile = "imakefile";
673		} else
674			Imakefile = "Imakefile";
675	}
676	return(Imakefile);
677}
678
679static void _X_ATTRIBUTE_PRINTF(1, 0)
680vLogMsg(const char *fmt, va_list args)
681{
682	int error_number = errno;
683
684	if (error_number) {
685		fprintf(stderr, "%s: ", program);
686		fprintf(stderr, "%s\n", strerror(error_number));
687	}
688	fprintf(stderr, "%s: ", program);
689	vfprintf(stderr, fmt, args);
690	fprintf(stderr, "\n");
691}
692
693void
694LogFatal(const char *fmt, ...)
695{
696	static boolean entered = FALSE;
697	va_list args;
698
699	if (entered)
700		return;
701	entered = TRUE;
702
703	va_start(args, fmt);
704	vLogMsg(fmt, args);
705	va_end(args);
706	fprintf(stderr, "  Stop.\n");
707	wrapup();
708	exit(1);
709}
710
711void
712LogMsg(const char *fmt, ...)
713{
714	va_list args;
715
716	va_start(args, fmt);
717	vLogMsg(fmt, args);
718	va_end(args);
719}
720
721void
722showargs(const char **argv)
723{
724	for (; *argv; argv++)
725		fprintf(stderr, "%s ", *argv);
726	fprintf(stderr, "\n");
727}
728
729#define ImakefileCHeader "/* imake - temporary file */"
730
731void
732CheckImakefileC(const char *masterc)
733{
734	char mkcbuf[1024];
735	FILE *inFile;
736
737	if (access(masterc, F_OK) == 0) {
738		inFile = fopen(masterc, "r");
739		if (inFile == NULL)
740			LogFatal("Refuse to overwrite: %s", masterc);
741		if ((fgets(mkcbuf, sizeof(mkcbuf), inFile) &&
742		     strncmp(mkcbuf, ImakefileCHeader,
743			     sizeof(ImakefileCHeader)-1)))
744		{
745			fclose(inFile);
746			LogFatal("Refuse to overwrite: %s", masterc);
747		}
748		else
749			fclose(inFile);
750	}
751}
752
753#define LocalDefineFmt	"#define %s \"%s\"\n"
754#define IncludeFmt	"#include %s\n"
755#define ImakeDefSym	"INCLUDE_IMAKEFILE"
756#define ImakeTmplSym	"IMAKE_TEMPLATE"
757#define OverrideWarning "Warning: local file \"%s\" overrides global macros."
758
759boolean
760optional_include(FILE *inFile, const char *defsym, const char *fname)
761{
762	errno = 0;
763	if (access(fname, R_OK) == 0) {
764		LogMsg(OverrideWarning, fname);
765		return (fprintf(inFile, LocalDefineFmt, defsym, fname) < 0 ||
766			fprintf(inFile, IncludeFmt, defsym) < 0);
767	}
768	return FALSE;
769}
770
771void
772doit(FILE *outfd, const char *cmd, const char **argv)
773{
774	int		pid;
775	waitType	status;
776
777	/*
778	 * Fork and exec the command.
779	 */
780#ifdef WIN32
781	if (outfd)
782		dup2(fileno(outfd), 1);
783	status = _spawnvp(_P_WAIT, cmd, argv);
784	if (status < 0)
785		LogFatal("Cannot spawn %s.", cmd);
786	if (status > 0)
787		LogFatal("Exit code %d.", status);
788#else
789	pid = fork();
790	if (pid < 0)
791		LogFatal("Cannot fork.");
792	if (pid) {	/* parent... simply wait */
793		while (wait(&status) > 0) {
794			errno = 0;
795			if (WIFSIGNALED(status))
796				LogFatal("Signal %d.", waitSig(status));
797			if (WIFEXITED(status) && waitCode(status))
798				LogFatal("Exit code %d.", waitCode(status));
799		}
800	}
801	else {	/* child... dup and exec cmd */
802		if (verbose)
803			showargs(argv);
804		if (outfd)
805			dup2(fileno(outfd), 1);
806		execvp(cmd, argv);
807		LogFatal("Cannot exec %s.", cmd);
808	}
809#endif
810}
811
812#if !defined WIN32
813static void
814parse_utsname(struct utsname *name, const char *fmt, char *result, const char *msg)
815{
816  char buf[SYS_NMLN * 5 + 1];
817  char *ptr = buf;
818  int arg;
819
820  if (!name)
821      LogFatal(msg,fmt);
822
823  /* Assemble all the pieces into a buffer. */
824  for (arg = 0; fmt[arg] != ' '; arg++)
825    {
826      /* Our buffer is only guaranteed to hold 5 arguments. */
827      if (arg >= 5)
828	LogFatal(msg, fmt);
829
830      switch (fmt[arg])
831	{
832	case 's':
833	  if (arg > 0)
834	    *ptr++ = ' ';
835	  strcpy(ptr, name->sysname);
836	  ptr += strlen(ptr);
837	  break;
838
839	case 'n':
840	  if (arg > 0)
841	    *ptr++ = ' ';
842	  strcpy(ptr, name->nodename);
843	  ptr += strlen(ptr);
844	  break;
845
846	case 'r':
847	  if (arg > 0)
848	    *ptr++ = ' ';
849	  strcpy(ptr, name->release);
850	  ptr += strlen(ptr);
851	  break;
852
853	case 'v':
854	  if (arg > 0)
855	    *ptr++ = ' ';
856	  strcpy(ptr, name->version);
857	  ptr += strlen(ptr);
858	  break;
859
860	case 'm':
861	  if (arg > 0)
862	    *ptr++ = ' ';
863	  strcpy(ptr, name->machine);
864	  ptr += strlen(ptr);
865	  break;
866
867	default:
868	  LogFatal(msg, fmt);
869	}
870    }
871
872  /* Just in case... */
873  if (strlen(buf) >= sizeof(buf))
874    LogFatal("Buffer overflow parsing uname.");
875
876  /* Parse the buffer.  The sscanf() return value is rarely correct. */
877  *result = '\0';
878  (void) sscanf(buf, fmt + arg + 1, result);
879}
880
881/* Trim leading 0's and periods from version names.  The 0's cause
882   the number to be interpreted as octal numbers.  Some version strings
883   have the potential for different numbers of .'s in them.
884 */
885
886static char *
887trim_version(char *p)
888{
889
890	if (p != 0 && *p != '\0')
891	{
892		while ((*p == '0' || *p == '.') && *(p + 1) != '\0')
893			++p;
894	}
895	return (p);
896}
897#endif
898
899#if defined(linux) || defined(__GLIBC__)
900const char *libc_c=
901"#include <stdio.h>\n"
902"#include <ctype.h>\n"
903"\n"
904"#if 1\n"
905"#pragma weak gnu_get_libc_version\n"
906"#pragma weak __libc_version\n"
907"#pragma weak __linux_C_lib_version\n"
908"#endif\n"
909"\n"
910"extern const char * gnu_get_libc_version (void);\n"
911"extern const char * __linux_C_lib_version;\n"
912"extern const char __libc_version [];\n"
913"\n"
914"int\n"
915"main ()\n"
916"{\n"
917"  int libcmajor = 0, libcminor = 0, libcteeny = 0;\n"
918"  const char * ptr = NULL;\n"
919"  int glibcmajor = 0;\n"
920"\n"
921"  if (gnu_get_libc_version != 0)\n"
922"  {\n"
923"    ptr = gnu_get_libc_version ();\n"
924"    glibcmajor = 4;\n"
925"  }\n"
926"  else if (&__libc_version != 0)\n"
927"  {\n"
928"    ptr = __libc_version;\n"
929"    glibcmajor = 4;\n"
930"  }\n"
931"  else if (&__linux_C_lib_version != 0)\n"
932"  {\n"
933"    ptr = __linux_C_lib_version;\n"
934"  }\n"
935"  else\n"
936"  {\n"
937"    libcmajor = 0; libcminor = 0; libcteeny = 0;\n"
938"  }\n"
939"\n"
940"  if (ptr)\n"
941"  {\n"
942"    while (!isdigit (*ptr))\n"
943"      ptr++;\n"
944"\n"
945"    sscanf (ptr, \"%d.%d.%d\", &libcmajor, &libcminor, &libcteeny);\n"
946"    libcmajor += glibcmajor;\n"
947"  }\n"
948"\n"
949"  printf(\"#define DefaultLinuxCLibMajorVersion %d\\n\", libcmajor);\n"
950"  printf(\"#define DefaultLinuxCLibMinorVersion %d\\n\", libcminor);\n"
951"  printf(\"#define DefaultLinuxCLibTeenyVersion %d\\n\", libcteeny);\n"
952"\n"
953"  return 0;\n"
954"}\n"
955;
956
957static void
958get_libc_version(FILE *inFile)
959{
960  char aout[4096], *tmpdir;
961  FILE *fp;
962  const char *format = "%s -o %s -x c -";
963  char *cc;
964  int len;
965  char *command;
966
967  /* If $TMPDIR is defined and has an acceptable length,
968   * use that as tmp dir, else use /tmp.  That fixes
969   * problems with /tmp mounted "noexec".
970   */
971  if((tmpdir = getenv("TMPDIR")) != NULL && strlen(tmpdir) < (4096-13))
972    strcpy(aout, tmpdir);
973  else
974    strcpy(aout, "/tmp");
975  strcat(aout, "/imakeXXXXXX");
976
977  /* Pre-create temp file safely */
978  {
979    /* Linux + ELF has mkstemp() */
980    int tmpfd;
981    if ((tmpfd = mkstemp(aout)) == -1) {
982      perror("mkstemp");
983      abort();
984    }
985    close(tmpfd);
986  }
987  cc = getenv ("CC");
988  if (cc == NULL)
989    cc = "gcc";
990  len = strlen (aout) + strlen (format) + strlen (cc);
991  if (len < 128) len = 128;
992  if((command = alloca (len)) == NULL)
993    abort();
994
995  if (snprintf (command , len, format, cc, aout) == len)
996    abort ();
997
998  fp = popen (command, "w");
999  if (fp == NULL || fprintf (fp, "%s\n", libc_c) < 0
1000      || pclose (fp) != 0)
1001    abort ();
1002
1003  fp = popen (aout, "r");
1004  if (fp == NULL)
1005    abort ();
1006
1007  while (fgets (command, len, fp))
1008    fprintf (inFile, command);
1009
1010  len = pclose (fp);
1011  remove (aout);
1012  if (len)
1013    abort ();
1014}
1015#endif
1016
1017#if defined(__OpenBSD__) || defined(__DragonFly__)
1018static void
1019get_stackprotector(FILE *inFile)
1020{
1021  FILE *fp;
1022  char *cc;
1023  char command[1024], buf[1024];
1024
1025  cc = getenv("CC");
1026  if (cc == NULL) {
1027    cc = "cc";
1028  }
1029  snprintf(command, sizeof(command), "%s -v 2>&1", cc);
1030  fp = popen(command, "r");
1031  if (fp == NULL)
1032    abort();
1033  while (fgets(buf, sizeof(buf), fp)) {
1034    if (strstr(buf, "propolice") != NULL) {
1035      fprintf(inFile, "#define ProPoliceSupport YES\n");
1036      break;
1037    }
1038  }
1039  pclose(fp);
1040}
1041#endif
1042
1043
1044#if defined CROSSCOMPILE || defined linux || defined(__GLIBC__)
1045static void
1046get_distrib(FILE *inFile)
1047{
1048  struct stat sb;
1049
1050  static const char*   suse = "/etc/SuSE-release";
1051  static const char* redhat = "/etc/redhat-release";
1052  static const char* debian = "/etc/debian_version";
1053
1054  fprintf (inFile, "%s\n", "#define LinuxUnknown    0");
1055  fprintf (inFile, "%s\n", "#define LinuxSuSE       1");
1056  fprintf (inFile, "%s\n", "#define LinuxCaldera    2");
1057  fprintf (inFile, "%s\n", "#define LinuxCraftworks 3");
1058  fprintf (inFile, "%s\n", "#define LinuxDebian     4");
1059  fprintf (inFile, "%s\n", "#define LinuxInfoMagic  5");
1060  fprintf (inFile, "%s\n", "#define LinuxKheops     6");
1061  fprintf (inFile, "%s\n", "#define LinuxPro        7");
1062  fprintf (inFile, "%s\n", "#define LinuxRedHat     8");
1063  fprintf (inFile, "%s\n", "#define LinuxSlackware  9");
1064  fprintf (inFile, "%s\n", "#define LinuxTurbo      10");
1065  fprintf (inFile, "%s\n", "#define LinuxWare       11");
1066  fprintf (inFile, "%s\n", "#define LinuxYggdrasil  12");
1067
1068# ifdef CROSSCOMPILE
1069  if (CrossCompiling) {
1070      fprintf (inFile, "%s\n",
1071	       "#define DefaultLinuxDistribution LinuxUnknown");
1072      fprintf (inFile, "%s\n", "#define DefaultLinuxDistName Unknown");
1073      return;
1074  }
1075# endif
1076  if (lstat (suse, &sb) == 0) {
1077    fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxSuSE");
1078    fprintf (inFile, "%s\n", "#define DefaultLinuxDistName SuSE");
1079    return;
1080  }
1081  if (lstat (redhat, &sb) == 0) {
1082    fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxRedHat");
1083    fprintf (inFile, "%s\n", "#define DefaultLinuxDistName RedHat");
1084    return;
1085  }
1086  if (lstat (debian, &sb) == 0) {
1087    fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxDebian");
1088    fprintf (inFile, "%s\n", "#define DefaultLinuxDistName Debian");
1089    /* You could also try to get the version of the Debian distrib by looking
1090     * at the content of /etc/debian_version */
1091    return;
1092  }
1093  /* what's the definitive way to tell what any particular distribution is? */
1094
1095  fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxUnknown");
1096  fprintf (inFile, "%s\n", "#define DefaultLinuxDistName Unknown");
1097  /* would like to know what version of the distribution it is */
1098}
1099
1100static void
1101get_ld_version(FILE *inFile)
1102{
1103  FILE* ldprog;
1104  signed char c;
1105  int ldmajor, ldminor;
1106  const char *ld = "ld -v";
1107
1108# ifdef CROSSCOMPILE
1109  if (CrossCompiling) {
1110      char cmd[PATH_MAX];
1111      strcpy (cmd, CrossCompileDir);
1112      strcat (cmd,"/");
1113      strcat (cmd,ld);
1114      ldprog = popen (cmd, "r");
1115  } else
1116# endif
1117      ldprog = popen (ld, "r");
1118
1119  if (ldprog) {
1120    do {
1121      c = fgetc (ldprog);
1122    } while (c != EOF && !isdigit (c));
1123    ungetc (c, ldprog);
1124    (void) fscanf (ldprog, "%d.%d", &ldmajor, &ldminor);
1125    /* Start conversion to a more rational number */
1126    if ((ldmajor > 2) || ((ldmajor == 2) && (ldminor > 9)))
1127	ldmajor *= 100;
1128    else
1129	ldmajor *= 10;
1130
1131    fprintf(inFile, "#define DefaultLinuxBinUtilsMajorVersion %d\n",
1132	    ldmajor + ldminor);
1133    pclose (ldprog);
1134  }
1135}
1136#endif
1137
1138#if defined __FreeBSD__
1139static void
1140get_binary_format(FILE *inFile)
1141{
1142  int mib[2];
1143  size_t len;
1144  int osrel = 0;
1145  FILE *objprog = NULL;
1146  int iself = 0;
1147  char buf[10];
1148  char cmd[PATH_MAX];
1149
1150  mib[0] = CTL_KERN;
1151  mib[1] = KERN_OSRELDATE;
1152  len = sizeof(osrel);
1153  sysctl(mib, 2, &osrel, &len, NULL, 0);
1154  if (CrossCompiling) {
1155      strcpy (cmd, CrossCompileDir);
1156      strcat (cmd, "/");
1157      strcat (cmd,"objformat");
1158  } else
1159      strcpy (cmd, "objformat");
1160
1161  if (osrel >= 300004 &&
1162      (objprog = popen(cmd, "r")) != NULL &&
1163      fgets(buf, sizeof(buf), objprog) != NULL &&
1164      strncmp(buf, "elf", 3) == 0)
1165    iself = 1;
1166  if (objprog)
1167    pclose(objprog);
1168
1169  fprintf(inFile, "#define DefaultToElfFormat %s\n", iself ? "YES" : "NO");
1170}
1171#endif
1172
1173#if defined(sun) && defined(__SVR4)
1174/* Runs Sun compiler command and parses output - this is a bit of a hack
1175 * as it depends on the particular output format of the -V flag, but it's
1176 * worked for many releases.
1177 *
1178 * Input : cmd - command to run (called with -V flag)
1179 *	   path - path to command to run (use $PATH if NULL)
1180 * Output: cmajor & cminor - major and minor versions if found
1181 * Returns: 0 if successful, -1 if not.
1182 */
1183static int
1184ask_sun_compiler_for_versions(const char *cmd, const char *path,
1185  int *cmajor, int *cminor)
1186{
1187  char buf[BUFSIZ];
1188  char cmdtorun[PATH_MAX];
1189  char* vptr;
1190  FILE* ccproc;
1191  const char vflag[] = " -V 2>&1";
1192  int retval = -1;
1193
1194  int len = strlen(cmd) + sizeof(vflag);
1195
1196  if (path != NULL) {
1197      len += strlen(path) + 1;
1198  }
1199
1200  if (len < sizeof(cmdtorun)) {
1201      if (path != NULL) {
1202	  sprintf(cmdtorun, "%s/%s %s", path, cmd, vflag);
1203      } else {
1204	  sprintf(cmdtorun, "%s %s", cmd, vflag);
1205      }
1206
1207      if ((ccproc = popen (cmdtorun, "r")) != NULL) {
1208	  if (fgets (buf, sizeof(buf), ccproc) != NULL) {
1209	      vptr = strrchr (buf, 'C');
1210	      if (vptr) {
1211		  for (; (*vptr != '\0') && !isdigit(*vptr); vptr++) {
1212		      /* Do nothing - just scanning for first digit */
1213		  }
1214		  if (*vptr != '\0') {
1215		      if (sscanf (vptr, "%d.%d", cmajor, cminor) == 2) {
1216			  retval = 0;
1217		      }
1218		  }
1219	      }
1220	      if (retval != 0) {
1221		  fprintf(stderr,
1222		    "warning: could not parse version number in output of:\n"
1223		    "         %s\n", cmdtorun);
1224	      }
1225	      while (fgets (buf, sizeof(buf), ccproc) != NULL) {};
1226	  }
1227	  pclose (ccproc);
1228      }
1229  }
1230  return retval;
1231}
1232
1233/* Find Sun compilers and their versions if present */
1234static void
1235get_sun_compiler_versions (FILE *inFile)
1236{
1237  const char* sunpro_path = "/opt/SUNWspro/bin";
1238  int cmajor, cminor, found = 0;
1239
1240  /* If cross-compiling, only check CrossCompilerDir for compilers.
1241   * If not cross-compiling, first check cc in users $PATH,
1242   * then try /opt/SUNWspro if not found in the users $PATH
1243   */
1244
1245# if defined CROSSCOMPILE
1246  if (CrossCompiling) {
1247      if (ask_sun_compiler_for_versions("cc", CrossCompileDir,
1248	&cmajor, &cminor) == 0) {
1249	      found = 1;
1250      }
1251  }
1252  else
1253# endif
1254  {
1255      if (ask_sun_compiler_for_versions("cc", NULL, &cmajor, &cminor) == 0) {
1256	  found = 1;
1257      } else if (ask_sun_compiler_for_versions("cc", sunpro_path,
1258	&cmajor, &cminor) == 0) {
1259	  found = 1;
1260	  fprintf(inFile, "#define DefaultSunProCCompilerDir %s", sunpro_path);
1261      }
1262  }
1263
1264  if (found) {
1265      fprintf (inFile,
1266	"#define DefaultSunProCCompilerMajorVersion %d\n", cmajor);
1267      fprintf (inFile,
1268	"#define DefaultSunProCCompilerMinorVersion %d\n", cminor);
1269  }
1270
1271  /* Now do it again for C++ compiler (CC) */
1272  found = 0;
1273# if defined CROSSCOMPILE
1274  if (CrossCompiling) {
1275      if (ask_sun_compiler_for_versions("CC", CrossCompileDir,
1276	&cmajor, &cminor) == 0) {
1277	      found = 1;
1278      }
1279  }
1280  else
1281# endif
1282  {
1283      if (ask_sun_compiler_for_versions("CC", NULL, &cmajor, &cminor) == 0) {
1284	  found = 1;
1285      } else if (ask_sun_compiler_for_versions("CC", sunpro_path,
1286	&cmajor, &cminor) == 0) {
1287	  found = 1;
1288	  fprintf(inFile,
1289		"#define DefaultSunProCplusplusCompilerDir %s", sunpro_path);
1290      }
1291  }
1292
1293  if (found) {
1294      fprintf (inFile,
1295	"#define DefaultSunProCplusplusCompilerMajorVersion %d\n",
1296	cmajor);
1297      fprintf (inFile,
1298	"#define DefaultSunProCplusplusCompilerMinorVersion %d\n",
1299	cminor);
1300  }
1301}
1302#endif
1303
1304#if defined CROSSCOMPILE || defined  __GNUC__
1305static void
1306get_gcc_version(FILE *inFile, char *name)
1307{
1308    fprintf (inFile, "#define HasGcc 1\n");
1309# ifdef CROSSCOMPILE
1310    if (CrossCompiling)
1311    {
1312	if (gnu_c > 1) {
1313	    fprintf (inFile, "#define HasGcc2 1\n");
1314	    if (gnu_c > 2)
1315		fprintf (inFile, "#define HasGcc3 1\n");
1316	}
1317	fprintf (inFile, "#define GccMajorVersion %d\n", gnu_c);
1318	fprintf (inFile, "#define GccMinorVersion %d\n", gnu_c_minor);
1319    } else
1320# endif
1321    {
1322# if __GNUC__ > 1
1323	fprintf (inFile, "#define HasGcc2 1\n");
1324#  if __GNUC__ > 2
1325	fprintf (inFile, "#define HasGcc3 1\n");
1326#  endif
1327# endif
1328	fprintf (inFile, "#define GccMajorVersion %d\n", __GNUC__);
1329	fprintf (inFile, "#define GccMinorVersion %d\n", __GNUC_MINOR__);
1330    }
1331# if defined(HAS_MERGE_CONSTANTS)
1332    fprintf (inFile, "#define HasGccMergeConstants %d\n", HAS_MERGE_CONSTANTS);
1333# endif
1334}
1335#endif
1336
1337static boolean
1338get_gcc(char *cmd)
1339{
1340  struct stat sb;
1341    static const char* gcc_path[] = {
1342#if defined(linux) || \
1343     defined(__NetBSD__) || \
1344     defined(__OpenBSD__) || \
1345     defined(__FreeBSD__) || \
1346     defined(__DragonFly__) || \
1347     defined(__APPLE__) || \
1348     defined(__CYGWIN__) || \
1349     defined(__MINGW32__) || \
1350     defined(__GNU__) || \
1351     defined(__GLIBC__)
1352	"/usr/bin/cc",	/* for Linux PostIncDir */
1353#endif
1354	"/usr/local/bin/gcc",
1355	"/opt/gnu/bin/gcc",
1356	"/usr/pkg/bin/gcc"
1357    };
1358
1359#ifdef CROSSCOMPILE
1360    static const char* cross_cc_name[] = {
1361	"cc",
1362	"gcc"
1363    };
1364
1365    if (CrossCompiling) {
1366	int i;
1367	for (i = 0; i < sizeof (cross_cc_name) / sizeof cross_cc_name[0]; i++){
1368	    strcpy (cmd, CrossCompileDir);
1369	    strcat (cmd, "/");
1370	    strcat (cmd, cross_cc_name[i]);
1371	    if (lstat (cmd, &sb) == 0) {
1372		return TRUE;
1373		break;
1374	    }
1375	}
1376    } else
1377#endif
1378      {
1379	int i;
1380	for (i = 0; i < sizeof (gcc_path) / sizeof gcc_path[0]; i++) {
1381	    if (lstat (gcc_path[i], &sb) == 0) {
1382		strcpy (cmd, gcc_path[i]);
1383		return TRUE;
1384	    }
1385	}
1386      }
1387    return FALSE;
1388}
1389
1390#ifdef CROSSCOMPILE
1391static void
1392get_gcc_incdir(FILE *inFile, char* name)
1393{
1394  FILE* gccproc;
1395  char buf[PATH_MAX];
1396  char cmd[PATH_MAX];
1397  char* ptr;
1398
1399  strcpy(cmd,name);
1400
1401  buf[0] = '\0';
1402  strcat (cmd, " --print-libgcc-file-name");
1403  if ((gccproc = popen (cmd, "r")) != NULL) {
1404      if (fgets (buf, PATH_MAX, gccproc) != NULL) {
1405	  ptr = strstr (buf, "libgcc.a");
1406	  if (ptr) strcpy (ptr, "include");
1407      }
1408      (void) pclose (gccproc);
1409  }
1410
1411  if (buf[0])
1412      fprintf (inFile, "#define DefaultGccIncludeDir \"%s\"\n", buf);
1413}
1414#endif
1415
1416boolean
1417define_os_defaults(FILE *inFile)
1418{
1419#if defined CROSSCOMPILE || !defined(WIN32)
1420# ifdef CROSSCOMPILE
1421#  ifdef __GNUC__
1422  if (1)
1423#  else
1424  if ((sys != win32) && (sys != emx))
1425#  endif
1426# endif
1427    {
1428# if (defined(DEFAULT_OS_NAME) || defined(DEFAULT_OS_MAJOR_REV) || \
1429     defined(DEFAULT_OS_MINOR_REV) || defined(DEFAULT_OS_TEENY_REV))
1430	struct utsname *name = NULL;
1431	struct utsname uts_name;
1432	char buf[SYS_NMLN * 5 + 1];
1433
1434	/* Obtain the system information. */
1435#  ifdef CROSSCOMPILE
1436      if (!CrossCompiling)
1437#  endif
1438      {
1439	  if (uname(&uts_name) < 0)
1440	      LogFatal("Cannot invoke uname");
1441	  else
1442	      name = &uts_name;
1443      }
1444#  if defined CROSSCOMPILE && (defined linux || defined(__GLIBC__))
1445      else {
1446	  strncpy(uts_name.sysname,cross_uts_sysname,SYS_NMLN);
1447	  strncpy(uts_name.release,cross_uts_release,SYS_NMLN);
1448	  strncpy(uts_name.version,cross_uts_version,SYS_NMLN);
1449	  strncpy(uts_name.machine,cross_uts_machine,SYS_NMLN);
1450	  name = &uts_name;
1451      }
1452#  endif
1453#  ifdef __FreeBSD__
1454       /* Override for compiling in chroot of other OS version, such as
1455        * in the bento build cluster.
1456        */
1457       {
1458	 char *e;
1459	 if ((e = getenv("OSREL")) != NULL &&
1460	     strlen(name->sysname) + strlen(e) + 1 < SYS_NMLN) {
1461	  strcpy(name->release, e);
1462	  strcpy(name->version, name->sysname);
1463	  strcat(name->version, " ");
1464	  strcat(name->version, e);
1465	 }
1466       }
1467#  endif
1468
1469#  if defined DEFAULT_OS_NAME
1470#   if defined CROSSCOMPILE
1471      if (!CrossCompiling)
1472#   endif
1473	{
1474	  parse_utsname(name, DEFAULT_OS_NAME, buf,
1475			"Bad DEFAULT_OS_NAME syntax %s");
1476#   ifdef DEFAULT_OS_NAME_FROB
1477	  DEFAULT_OS_NAME_FROB(buf, sizeof buf);
1478#   endif
1479	  if (buf[0] != '\0')
1480	    fprintf(inFile, "#define DefaultOSName %s\n", buf);
1481	}
1482#  endif
1483
1484#  if defined CROSSCOMPILE
1485	if (CrossCompiling && defaultOsName) {
1486	  parse_utsname(name, defaultOsName, buf,
1487			"Bad DEFAULT_OS_NAME syntax %s");
1488	  if (defaultOsNameFrob)
1489	    defaultOsNameFrob(buf, sizeof buf);
1490	  if (buf[0] != '\0')
1491	    fprintf(inFile, "#define DefaultOSName %s\n", buf);
1492	}
1493#  endif
1494
1495#  ifdef DEFAULT_OS_MAJOR_REV
1496#   if defined CROSSCOMPILE
1497	if (!CrossCompiling)
1498#   endif
1499	  {
1500	    parse_utsname(name, DEFAULT_OS_MAJOR_REV, buf,
1501			  "Bad DEFAULT_OS_MAJOR_REV syntax %s");
1502#   ifdef DEFAULT_OS_MAJOR_REV_FROB
1503	    DEFAULT_OS_MAJOR_REV_FROB(buf, sizeof buf);
1504#   endif
1505	    fprintf(inFile, "#define DefaultOSMajorVersion %s\n",
1506		    *buf ? trim_version(buf) : "0");
1507	  }
1508#  endif
1509
1510#  if defined CROSSCOMPILE
1511	if (CrossCompiling && defaultOsMajorRev) {
1512	  parse_utsname(name, defaultOsMajorRev, buf,
1513			"Bad defaultOsMajorRev syntax %s");
1514	  if (defaultOsMajorRevFrob)
1515	    defaultOsMajorRevFrob(buf, sizeof buf);
1516	  fprintf(inFile, "#define DefaultOSMajorVersion %s\n",
1517		  *buf ? trim_version(buf) : "0");
1518	}
1519#  endif
1520
1521#  ifdef DEFAULT_OS_MINOR_REV
1522#   if defined CROSSCOMPILE
1523	if (!CrossCompiling)
1524#   endif
1525	  {
1526	    parse_utsname(name, DEFAULT_OS_MINOR_REV, buf,
1527			  "Bad DEFAULT_OS_MINOR_REV syntax %s");
1528#   ifdef DEFAULT_OS_MINOR_REV_FROB
1529	    DEFAULT_OS_MINOR_REV_FROB(buf, sizeof buf);
1530#   endif
1531	    fprintf(inFile, "#define DefaultOSMinorVersion %s\n",
1532		    *buf ? trim_version(buf) : "0");
1533	  }
1534#  endif
1535
1536#  if defined CROSSCOMPILE
1537	if (CrossCompiling && defaultOsMinorRev) {
1538	  parse_utsname(name, defaultOsMinorRev, buf,
1539			"Bad defaultOsMinorRev syntax %s");
1540	  if (defaultOsMinorRevFrob)
1541	    defaultOsMinorRevFrob(buf, sizeof buf);
1542	  fprintf(inFile, "#define DefaultOSMinorVersion %s\n",
1543		  *buf ? trim_version(buf) : "0");
1544	}
1545#  endif
1546
1547#  ifdef DEFAULT_OS_TEENY_REV
1548#   if defined CROSSCOMPILE
1549	if (!CrossCompiling)
1550#   endif
1551	  {
1552	    parse_utsname(name, DEFAULT_OS_TEENY_REV, buf,
1553			  "Bad DEFAULT_OS_TEENY_REV syntax %s");
1554#   ifdef DEFAULT_OS_TEENY_REV_FROB
1555	    DEFAULT_OS_TEENY_REV_FROB(buf, sizeof buf);
1556#   endif
1557	    fprintf(inFile, "#define DefaultOSTeenyVersion %s\n",
1558		    *buf ? trim_version(buf) : "0");
1559	  }
1560#  endif
1561
1562#  if defined CROSSCOMPILE
1563	if (CrossCompiling && defaultOsTeenyRev) {
1564	  parse_utsname(name, defaultOsTeenyRev, buf,
1565			"Bad defaultOsTeenyRev syntax %s");
1566	  if (defaultOsTeenyRevFrob)
1567	    defaultOsTeenyRevFrob(buf, sizeof buf);
1568	  fprintf(inFile, "#define DefaultOSTeenyVersion %s\n",
1569		  *buf ? trim_version(buf) : "0");
1570	}
1571#  endif
1572
1573#  ifdef DEFAULT_MACHINE_ARCHITECTURE
1574#   if defined CROSSCOMPILE
1575	if (!CrossCompiling)
1576#   endif
1577	  {
1578	    parse_utsname(name, DEFAULT_MACHINE_ARCHITECTURE, buf,
1579			  "Bad DEFAULT_MACHINE_ARCHITECTURE %s");
1580	    fprintf(inFile, "#ifndef %s\n# define %s\n#endif\n", buf, buf);
1581	  }
1582#  endif
1583
1584#  if defined CROSSCOMPILE
1585	if (CrossCompiling && defaultMachineArchitecture) {
1586	  parse_utsname(name, defaultMachineArchitecture, buf,
1587			"Bad defaultMachineArchitecture syntax %s");
1588	  fprintf(inFile, "#ifndef %s\n# define %s\n#endif\n", buf, buf);
1589	}
1590#  endif
1591# endif
1592# if defined CROSSCOMPILE
1593      if (CrossCompiling)
1594	get_cross_compile_dir(inFile);
1595      else
1596# endif
1597	  fprintf(inFile, "#define CrossCompiling NO\n");
1598# if defined CROSSCOMPILE
1599      if (CrossCompiling && sys == LinuX)
1600# endif
1601# if defined CROSSCOMPILE || defined linux || defined(__GLIBC__)
1602#  if defined(CROSSCOMPILE) && defined(__linux__)
1603	if (sys == LinuX)
1604#  endif
1605	  get_distrib (inFile);
1606# endif
1607# if defined linux || defined(__GLIBC__)
1608#  if defined CROSSCOMPILE
1609      if (!CrossCompiling)
1610#  endif
1611	  get_libc_version (inFile);
1612#  if defined CROSSCOMPILE
1613      else {
1614	  fprintf(inFile,"#define DefaultLinuxCLibMajorVersion %d\n",
1615		  glibc_major);
1616	  fprintf(inFile,"#define DefaultLinuxCLibMinorVersion %d\n",
1617		  glibc_minor);
1618	  fprintf(inFile,"#define DefaultLinuxCLibTeenyVersion 0\n");
1619      }
1620#  endif
1621# endif /* linux || __GLIBC__ */
1622# if defined CROSSCOMPILE || defined linux || defined(__GLIBC__)
1623#  if defined CROSSCOMPILE && defined(__linux__)
1624      if (sys == LinuX)
1625#  endif
1626	  get_ld_version(inFile);
1627# endif
1628# if defined (sun) && defined(SVR4)
1629      get_sun_compiler_versions (inFile);
1630# endif
1631# if defined CROSSCOMPILE || defined __GNUC__
1632#  if defined CROSSCOMPILE
1633      if (gnu_c)
1634#  endif
1635	{
1636	  char name[PATH_MAX];
1637	  if (get_gcc(name)) {
1638	      get_gcc_version (inFile,name);
1639#  if defined CROSSCOMPILE
1640	      if (sys != emx)
1641		  get_gcc_incdir(inFile,name);
1642#  endif
1643	  }
1644	}
1645# endif
1646# if defined __FreeBSD__
1647#  if defined CROSSCOMPILE
1648      if (sys == freeBSD)
1649#  endif
1650	  get_binary_format(inFile);
1651# endif
1652    }
1653#endif /* !WIN32 */
1654#if defined WIN32
1655# ifdef CROSSCOMPILE
1656  else if (sys == win32 && !CrossCompiling)
1657# endif
1658    {
1659      OSVERSIONINFO osvi;
1660      static char* os_names[] = { "Win32s", "Windows 95", "Windows NT" };
1661
1662      memset(&osvi, 0, sizeof(OSVERSIONINFO));
1663      osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
1664      GetVersionEx (&osvi);
1665
1666      fprintf (inFile, "#define DefaultOSName Microsoft %s\n",
1667	       os_names[osvi.dwPlatformId]);
1668
1669      fprintf(inFile, "#define DefaultOSMajorVersion %d\n", osvi.dwMajorVersion);
1670      fprintf(inFile, "#define DefaultOSMinorVersion %d\n", osvi.dwMinorVersion);
1671      fprintf(inFile, "#define DefaultOSTeenyVersion %d\n",
1672	      osvi.dwBuildNumber & 0xFFFF);
1673    }
1674#endif /* WIN32 */
1675#ifdef CROSSCOMPILE
1676  else if (sys == emx)
1677    {
1678      fprintf(inFile, "#define DefaultOSMajorVersion 4\n");
1679      fprintf(inFile, "#define DefaultOSMinorVersion 0\n");
1680      fprintf(inFile, "#define DefaultOSTeenyVersion 0\n");
1681    }
1682#endif /* EMX */
1683#if defined(__OpenBSD__) || defined(__DragonFly__)
1684  get_stackprotector(inFile);
1685#endif
1686  return FALSE;
1687}
1688
1689void
1690cppit(const char *imakefile, const char *template, const char *masterc,
1691      FILE *outfd, const char *outfname)
1692{
1693	FILE	*inFile;
1694
1695	haveImakefileC = TRUE;
1696	inFile = fopen(masterc, "w");
1697	if (inFile == NULL)
1698		LogFatal("Cannot open %s for output.", masterc);
1699	if (fprintf(inFile, "%s\n", ImakefileCHeader) < 0 ||
1700	    define_os_defaults(inFile) ||
1701	    optional_include(inFile, "IMAKE_LOCAL_DEFINES", "localdefines") ||
1702	    optional_include(inFile, "IMAKE_ADMIN_DEFINES", "admindefines") ||
1703	    fprintf(inFile, "#define %s <%s>\n", ImakeDefSym, imakefile) < 0 ||
1704	    fprintf(inFile, LocalDefineFmt, ImakeTmplSym, template) < 0 ||
1705	    fprintf(inFile, IncludeFmt, ImakeTmplSym) < 0 ||
1706	    optional_include(inFile, "IMAKE_ADMIN_MACROS", "adminmacros") ||
1707	    optional_include(inFile, "IMAKE_LOCAL_MACROS", "localmacros") ||
1708	    fflush(inFile)) {
1709		fclose(inFile);
1710		LogFatal("Cannot write to %s.", masterc);
1711	}
1712	else if (fclose(inFile))
1713		LogFatal("Cannot write to %s.", masterc);
1714	/*
1715	 * Fork and exec cpp
1716	 */
1717	doit(outfd, cpp, cpp_argv);
1718	CleanCppOutput(outfd, outfname);
1719}
1720
1721void
1722makeit(void)
1723{
1724	doit(NULL, make_argv[0], make_argv);
1725}
1726
1727const char *
1728CleanCppInput(const char *imakefile)
1729{
1730	FILE	*outFile = NULL;
1731	FILE	*inFile;
1732	char	*buf,		/* buffer for file content */
1733		*pbuf,		/* walking pointer to buf */
1734		*punwritten,	/* pointer to unwritten portion of buf */
1735		*ptoken,	/* pointer to # token */
1736		*pend,		/* pointer to end of # token */
1737		savec;		/* temporary character holder */
1738	int	count;
1739	struct stat	st;
1740
1741	/*
1742	 * grab the entire file.
1743	 */
1744	if (!(inFile = fopen(imakefile, "r")))
1745		LogFatal("Cannot open %s for input.", imakefile);
1746	if (fstat(fileno(inFile), &st) < 0)
1747		LogFatal("Cannot stat %s for size.", imakefile);
1748	buf = Emalloc((int)st.st_size+3);
1749	count = fread(buf + 2, 1, st.st_size, inFile);
1750	if (count == 0 && st.st_size != 0)
1751		LogFatal("Cannot read %s:", imakefile);
1752	fclose(inFile);
1753	buf[0] = '\n';
1754	buf[1] = '\n';
1755	buf[count + 2] = '\0';
1756
1757	punwritten = pbuf = buf + 2;
1758	while (*pbuf) {
1759	    /* for compatibility, replace make comments for cpp */
1760	    if (*pbuf == '#' && pbuf[-1] == '\n' && pbuf[-2] != '\\') {
1761		ptoken = pbuf+1;
1762		while (*ptoken == ' ' || *ptoken == '\t')
1763			ptoken++;
1764		pend = ptoken;
1765		while (*pend && *pend != ' ' && *pend != '\t' && *pend != '\n' && *pend != '\r')
1766			pend++;
1767		savec = *pend;
1768		*pend = '\0';
1769		if (strcmp(ptoken, "define") &&
1770		    strcmp(ptoken, "if") &&
1771		    strcmp(ptoken, "ifdef") &&
1772		    strcmp(ptoken, "ifndef") &&
1773		    strcmp(ptoken, "include") &&
1774		    strcmp(ptoken, "line") &&
1775		    strcmp(ptoken, "else") &&
1776		    strcmp(ptoken, "elif") &&
1777		    strcmp(ptoken, "endif") &&
1778		    strcmp(ptoken, "error") &&
1779		    strcmp(ptoken, "pragma") &&
1780		    strcmp(ptoken, "undef")) {
1781		    if (outFile == NULL) {
1782#ifdef HAVE_MKSTEMP
1783			int fd;
1784#endif
1785			char *tmpImakefileName = Strdup(tmpImakefileTemplate);
1786#ifndef HAVE_MKSTEMP
1787			if (mktemp(tmpImakefileName) == NULL ||
1788			    (outFile = fopen(tmpImakefileName, "w+")) == NULL) {
1789			    LogFatal("Cannot open %s for write.",
1790				tmpImakefileName);
1791			}
1792#else
1793			fd=mkstemp(tmpImakefileName);
1794			if (fd != -1)
1795			    outFile = fdopen(fd, "w");
1796			if (outFile == NULL) {
1797			    if (fd != -1) {
1798			       unlink(tmpImakefileName); close(fd);
1799			    }
1800			    LogFatal("Cannot open %s for write.",
1801				tmpImakefileName);
1802			}
1803#endif
1804			tmpImakefile = tmpImakefileName;
1805		    }
1806		    writetmpfile(outFile, punwritten, pbuf-punwritten,
1807				 tmpImakefile);
1808		    if (ptoken > pbuf + 1)
1809			writetmpfile(outFile, "XCOMM", 5, tmpImakefile);
1810		    else
1811			writetmpfile(outFile, "XCOMM ", 6, tmpImakefile);
1812		    punwritten = pbuf + 1;
1813		}
1814		*pend = savec;
1815	    }
1816	    pbuf++;
1817	}
1818	if (outFile) {
1819	    writetmpfile(outFile, punwritten, pbuf-punwritten, tmpImakefile);
1820	    fclose(outFile);
1821
1822	    return tmpImakefile;
1823	}
1824
1825	return(imakefile);
1826}
1827
1828void
1829CleanCppOutput(FILE *tmpfd, const char *tmpfname)
1830{
1831	char	*input;
1832	int	blankline = 0;
1833
1834	while((input = ReadLine(tmpfd, tmpfname))) {
1835		if (isempty(input)) {
1836			if (blankline++)
1837				continue;
1838#ifdef CROSSCOMPILE
1839			if (fixup_whitespace)
1840#endif
1841#if defined CROSSCOMPILE || defined FIXUP_CPP_WHITESPACE
1842			    KludgeResetRule();
1843#endif
1844		} else {
1845			blankline = 0;
1846#ifdef CROSSCOMPILE
1847			if (fixup_whitespace)
1848#endif
1849#if defined CROSSCOMPILE || defined FIXUP_CPP_WHITESPACE
1850			    KludgeOutputLine(&input);
1851#endif
1852			writetmpfile(tmpfd, input, strlen(input), tmpfname);
1853		}
1854		writetmpfile(tmpfd, "\n", 1, tmpfname);
1855	}
1856	fflush(tmpfd);
1857#ifdef NFS_STDOUT_BUG
1858	/*
1859	 * On some systems, NFS seems to leave a large number of nulls at
1860	 * the end of the file.  Ralph Swick says that this kludge makes the
1861	 * problem go away.
1862	 */
1863	ftruncate (fileno(tmpfd), (off_t)ftell(tmpfd));
1864#endif
1865}
1866
1867/*
1868 * Determine if a line has nothing in it.  As a side effect, we trim white
1869 * space from the end of the line.  Cpp magic cookies are also thrown away.
1870 * "XCOMM" token is transformed to "#".
1871 */
1872boolean
1873isempty(char *line)
1874{
1875	char	*pend;
1876
1877	/*
1878	 * Check for lines of the form
1879	 *	# n "...
1880	 * or
1881	 *	# line n "...
1882	 */
1883	if (*line == '#') {
1884		pend = line+1;
1885		if (*pend == ' ')
1886			pend++;
1887		if (*pend == 'l' && pend[1] == 'i' && pend[2] == 'n' &&
1888		    pend[3] == 'e' && pend[4] == ' ')
1889			pend += 5;
1890		if (isdigit(*pend)) {
1891			do {
1892			    pend++;
1893			} while (isdigit(*pend));
1894			if (*pend == '\n' || *pend == '\0')
1895				return(TRUE);
1896			if (*pend++ == ' ' && *pend == '"')
1897				return(TRUE);
1898		}
1899		while (*pend)
1900		    pend++;
1901	} else {
1902	    for (pend = line; *pend; pend++) {
1903		if (*pend == 'X' && pend[1] == 'C' && pend[2] == 'O' &&
1904		    pend[3] == 'M' && pend[4] == 'M' &&
1905		    (pend == line || pend[-1] == ' ' || pend[-1] == '\t' || pend[-1] == '\r') &&
1906		    (pend[5] == ' ' || pend[5] == '\t' || pend[5] == '\r' || pend[5] == '\0'))
1907		{
1908		    *pend = '#';
1909		    memmove(pend+1, pend+5, strlen(pend+5)+1);
1910		}
1911#ifdef CROSSCOMPILE
1912		if (magic_make_vars)
1913#endif
1914		  {
1915#if defined CROSSCOMPILE || defined MAGIC_MAKE_VARS
1916		    if (*pend == 'X' && pend[1] == 'V' && pend[2] == 'A' &&
1917			pend[3] == 'R')
1918		    {
1919			char varbuf[5];
1920			int i;
1921
1922			if (pend[4] == 'd' && pend[5] == 'e' && pend[6] == 'f' &&
1923			    pend[7] >= '0' && pend[7] <= '9')
1924			{
1925			    i = pend[7] - '0';
1926			    sprintf(varbuf, "%0.4d", xvariable);
1927			    strncpy(pend+4, varbuf, 4);
1928			    xvariables[i] = xvariable;
1929			    xvariable = (xvariable + 1) % 10000;
1930			}
1931			else if (pend[4] == 'u' && pend[5] == 's' &&
1932				 pend[6] == 'e' && pend[7] >= '0' &&
1933				 pend[7] <= '9')
1934			{
1935			    i = pend[7] - '0';
1936			    sprintf(varbuf, "%0.4d", xvariables[i]);
1937			    strncpy(pend+4, varbuf, 4);
1938			}
1939		    }
1940#endif
1941		}
1942	    }
1943	}
1944	while (--pend >= line && (*pend == ' ' || *pend == '\t' || *pend == '\r')) ;
1945	pend[1] = '\0';
1946	return (*line == '\0');
1947}
1948
1949/*ARGSUSED*/
1950char *
1951ReadLine(FILE *tmpfd, const char *tmpfname)
1952{
1953	static boolean	initialized = FALSE;
1954	static char	*buf, *pline, *end;
1955	register char	*p1, *p2;
1956
1957	if (! initialized) {
1958#ifdef WIN32
1959		FILE *fp = tmpfd;
1960#endif
1961		int total_red;
1962		struct stat st;
1963
1964		/*
1965		 * Slurp it all up.
1966		 */
1967		fseek(tmpfd, 0, 0);
1968		if (fstat(fileno(tmpfd), &st) < 0)
1969			LogFatal("cannot stat %s for size", tmpMakefile);
1970		pline = buf = Emalloc((int)st.st_size+1);
1971		total_red = fread(buf, 1, st.st_size, tmpfd);
1972		if (total_red == 0 && st.st_size != 0)
1973			LogFatal("cannot read %s", tmpMakefile);
1974		end = buf + total_red;
1975		*end = '\0';
1976		fseek(tmpfd, 0, 0);
1977#if defined(SYSV) || defined(WIN32) || defined(USE_FREOPEN)
1978		tmpfd = freopen(tmpfname, "w+", tmpfd);
1979# ifdef WIN32
1980		if (! tmpfd) /* if failed try again */
1981			tmpfd = freopen(tmpfname, "w+", fp);
1982# endif
1983		if (! tmpfd)
1984			LogFatal("cannot reopen %s\n", tmpfname);
1985#else	/* !SYSV */
1986		ftruncate(fileno(tmpfd), (off_t) 0);
1987#endif	/* !SYSV */
1988		initialized = TRUE;
1989	    fprintf (tmpfd, "# Makefile generated by imake - do not edit!\n");
1990	}
1991
1992	for (p1 = pline; p1 < end; p1++) {
1993		if (*p1 == '@' && *(p1+1) == '@'
1994		    /* ignore ClearCase version-extended pathnames */
1995		    && !(p1 != pline && !isspace(*(p1-1)) && *(p1+2) == '/'))
1996		{ /* soft EOL */
1997			*p1++ = '\0';
1998			p1++; /* skip over second @ */
1999			break;
2000		}
2001		else if (*p1 == '\n') { /* real EOL */
2002#if defined CROSSCOMPILE || defined WIN32
2003# if defined CROSSCOMPILE
2004		  if (sys == win32)
2005# endif
2006		    {
2007			if (p1 > pline && p1[-1] == '\r')
2008				p1[-1] = '\0';
2009		    }
2010#endif
2011			*p1++ = '\0';
2012			break;
2013		}
2014	}
2015
2016	/*
2017	 * return NULL at the end of the file.
2018	 */
2019	p2 = (pline == p1 ? NULL : pline);
2020	pline = p1;
2021	return(p2);
2022}
2023
2024void
2025writetmpfile(FILE *fd, const char *buf, int cnt, const char *fname)
2026{
2027	if (fwrite(buf, sizeof(char), cnt, fd) == -1)
2028		LogFatal("Cannot write to %s.", fname);
2029}
2030
2031char *
2032Emalloc(int size)
2033{
2034	char	*p;
2035
2036	if ((p = malloc(size)) == NULL)
2037		LogFatal("Cannot allocate %d bytes", size);
2038	return(p);
2039}
2040
2041#if defined CROSSCOMPILE || defined FIXUP_CPP_WHITESPACE
2042void
2043KludgeOutputLine(char **pline)
2044{
2045	char	*p = *pline;
2046	char	quotechar = '\0';
2047
2048	switch (*p) {
2049	    case '#':	/*Comment - ignore*/
2050		break;
2051	    case '\t':	/*Already tabbed - ignore it*/
2052		break;
2053	    case ' ':	/*May need a tab*/
2054	    default:
2055# ifdef CROSSCOMPILE
2056		if (inline_syntax)
2057# endif
2058# if defined CROSSCOMPILE || defined INLINE_SYNTAX
2059		{
2060		    if (*p == '<' && p[1] == '<') { /* inline file close */
2061			InInline--;
2062			InRule = TRUE;
2063			break;
2064		    }
2065		}
2066# endif
2067		/*
2068		 * The following cases should not be treated as beginning of
2069		 * rules:
2070		 * variable := name (GNU make)
2071		 * variable = .*:.* (':' should be allowed as value)
2072		 * sed 's:/a:/b:'   (: used in quoted values)
2073		 */
2074		for (; *p; p++) {
2075		    if (quotechar) {
2076			if (quotechar == '\\' ||
2077			    (*p == quotechar &&
2078# if defined CROSSCOMPILE || defined WIN32
2079			     (
2080#  if defined CROSSCOMPILE
2081			      (sys == win32) &&
2082#  endif
2083			      quotechar != ')') &&
2084# endif
2085			     p[-1] != '\\'))
2086			    quotechar = '\0';
2087			continue;
2088		    }
2089		    switch (*p) {
2090		    case '\\':
2091		    case '"':
2092		    case '\'':
2093			quotechar = *p;
2094			break;
2095		    case '(':
2096			quotechar = ')';
2097			break;
2098		    case '{':
2099			quotechar = '}';
2100			break;
2101		    case '[':
2102			quotechar = ']';
2103			break;
2104		    case '=':
2105# ifdef CROSSCOMPILE
2106			if (remove_cpp_leadspace)
2107# endif
2108# if defined CROSSCOMPILE || defined REMOVE_CPP_LEADSPACE
2109			{
2110			    if (!InRule && **pline == ' ') {
2111				while (**pline == ' ')
2112				    (*pline)++;
2113			    }
2114			}
2115# endif
2116			goto breakfor;
2117# if defined CROSSCOMPILE || defined INLINE_SYNTAX
2118		    case '<':
2119			if (inline_syntax) {
2120			    if (p[1] == '<') /* inline file start */
2121				InInline++;
2122			}
2123			break;
2124# endif
2125		    case ':':
2126			if (p[1] == '=')
2127			    goto breakfor;
2128			while (**pline == ' ')
2129			    (*pline)++;
2130			InRule = TRUE;
2131			return;
2132		    }
2133		}
2134breakfor:
2135		if (InRule && **pline == ' ')
2136		    **pline = '\t';
2137		break;
2138	}
2139}
2140
2141void
2142KludgeResetRule(void)
2143{
2144	InRule = FALSE;
2145}
2146#endif
2147char *
2148Strdup(const char *cp)
2149{
2150	char *new = Emalloc(strlen(cp) + 1);
2151
2152	strcpy(new, cp);
2153	return new;
2154}
2155
2156#ifdef CROSSCOMPILE
2157char*
2158CrossCompileCPP(void)
2159{
2160    char *cpp, *c;
2161    int len ;
2162    if (crosscompile_use_cc_e)
2163	AddCppArg("-E");
2164
2165    cpp = strrchr(crosscompile_cpp,'/');
2166    if (!cpp)
2167	cpp = crosscompile_cpp;
2168    else
2169	cpp++;
2170
2171    len = strlen(cpp) + strlen(CrossCompileDir) + 2;
2172    c = Emalloc(len);
2173
2174    (void)snprintf(c, len,"%s/%s",CrossCompileDir,cpp);
2175
2176    return c;
2177}
2178
2179#endif
2180
2181#ifdef CROSSCOMPILE
2182static void
2183get_cross_compile_dir(FILE *inFile)
2184{
2185	fprintf(inFile, "#define CrossCompileDir %s\n",
2186		CrossCompileDir);
2187	fprintf(inFile, "#define CrossCompiling YES\n");
2188}
2189#endif
2190