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