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