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