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