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