imake.c revision 1114aea8
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		}
748bb2e14f3Smrg		fclose(inFile);
749bb2e14f3Smrg	}
750bb2e14f3Smrg}
751bb2e14f3Smrg
752bb2e14f3Smrg#define LocalDefineFmt	"#define %s \"%s\"\n"
753bb2e14f3Smrg#define IncludeFmt	"#include %s\n"
754bb2e14f3Smrg#define ImakeDefSym	"INCLUDE_IMAKEFILE"
755bb2e14f3Smrg#define ImakeTmplSym	"IMAKE_TEMPLATE"
756bb2e14f3Smrg#define OverrideWarning "Warning: local file \"%s\" overrides global macros."
757bb2e14f3Smrg
758bb2e14f3Smrgboolean
7591114aea8Smrgoptional_include(FILE *inFile, const char *defsym, const char *fname)
760bb2e14f3Smrg{
761bb2e14f3Smrg	errno = 0;
762bb2e14f3Smrg	if (access(fname, R_OK) == 0) {
763bb2e14f3Smrg		LogMsg(OverrideWarning, fname);
764bb2e14f3Smrg		return (fprintf(inFile, LocalDefineFmt, defsym, fname) < 0 ||
765bb2e14f3Smrg			fprintf(inFile, IncludeFmt, defsym) < 0);
766bb2e14f3Smrg	}
767bb2e14f3Smrg	return FALSE;
768bb2e14f3Smrg}
769bb2e14f3Smrg
770bb2e14f3Smrgvoid
7711114aea8Smrgdoit(FILE *outfd, const char *cmd, const char **argv)
772bb2e14f3Smrg{
773bb2e14f3Smrg	int		pid;
774bb2e14f3Smrg	waitType	status;
775bb2e14f3Smrg
776bb2e14f3Smrg	/*
777bb2e14f3Smrg	 * Fork and exec the command.
778bb2e14f3Smrg	 */
779bb2e14f3Smrg#ifdef WIN32
780bb2e14f3Smrg	if (outfd)
781bb2e14f3Smrg		dup2(fileno(outfd), 1);
782bb2e14f3Smrg	status = _spawnvp(_P_WAIT, cmd, argv);
783bb2e14f3Smrg	if (status < 0)
784bb2e14f3Smrg		LogFatal("Cannot spawn %s.", cmd);
785bb2e14f3Smrg	if (status > 0)
7861114aea8Smrg		LogFatal("Exit code %d.", status);
787bb2e14f3Smrg#else
788bb2e14f3Smrg	pid = fork();
789bb2e14f3Smrg	if (pid < 0)
7901114aea8Smrg		LogFatal("Cannot fork.");
791bb2e14f3Smrg	if (pid) {	/* parent... simply wait */
792bb2e14f3Smrg		while (wait(&status) > 0) {
793bb2e14f3Smrg			errno = 0;
794bb2e14f3Smrg			if (WIFSIGNALED(status))
7951114aea8Smrg				LogFatal("Signal %d.", waitSig(status));
796bb2e14f3Smrg			if (WIFEXITED(status) && waitCode(status))
7971114aea8Smrg				LogFatal("Exit code %d.", waitCode(status));
798bb2e14f3Smrg		}
799bb2e14f3Smrg	}
800bb2e14f3Smrg	else {	/* child... dup and exec cmd */
801bb2e14f3Smrg		if (verbose)
802bb2e14f3Smrg			showargs(argv);
803bb2e14f3Smrg		if (outfd)
804bb2e14f3Smrg			dup2(fileno(outfd), 1);
805bb2e14f3Smrg		execvp(cmd, argv);
806bb2e14f3Smrg		LogFatal("Cannot exec %s.", cmd);
807bb2e14f3Smrg	}
808bb2e14f3Smrg#endif
809bb2e14f3Smrg}
810bb2e14f3Smrg
811bb2e14f3Smrg#if !defined WIN32
812bb2e14f3Smrgstatic void
8131114aea8Smrgparse_utsname(struct utsname *name, const char *fmt, char *result, const char *msg)
814bb2e14f3Smrg{
815bb2e14f3Smrg  char buf[SYS_NMLN * 5 + 1];
816bb2e14f3Smrg  char *ptr = buf;
817bb2e14f3Smrg  int arg;
818bb2e14f3Smrg
819bb2e14f3Smrg  if (!name)
820bb2e14f3Smrg      LogFatal(msg,fmt);
821bb2e14f3Smrg
822bb2e14f3Smrg  /* Assemble all the pieces into a buffer. */
823bb2e14f3Smrg  for (arg = 0; fmt[arg] != ' '; arg++)
824bb2e14f3Smrg    {
825bb2e14f3Smrg      /* Our buffer is only guaranteed to hold 5 arguments. */
826bb2e14f3Smrg      if (arg >= 5)
827bb2e14f3Smrg	LogFatal(msg, fmt);
828bb2e14f3Smrg
829bb2e14f3Smrg      switch (fmt[arg])
830bb2e14f3Smrg	{
831bb2e14f3Smrg	case 's':
832bb2e14f3Smrg	  if (arg > 0)
833bb2e14f3Smrg	    *ptr++ = ' ';
834bb2e14f3Smrg	  strcpy(ptr, name->sysname);
835bb2e14f3Smrg	  ptr += strlen(ptr);
836bb2e14f3Smrg	  break;
837bb2e14f3Smrg
838bb2e14f3Smrg	case 'n':
839bb2e14f3Smrg	  if (arg > 0)
840bb2e14f3Smrg	    *ptr++ = ' ';
841bb2e14f3Smrg	  strcpy(ptr, name->nodename);
842bb2e14f3Smrg	  ptr += strlen(ptr);
843bb2e14f3Smrg	  break;
844bb2e14f3Smrg
845bb2e14f3Smrg	case 'r':
846bb2e14f3Smrg	  if (arg > 0)
847bb2e14f3Smrg	    *ptr++ = ' ';
848bb2e14f3Smrg	  strcpy(ptr, name->release);
849bb2e14f3Smrg	  ptr += strlen(ptr);
850bb2e14f3Smrg	  break;
851bb2e14f3Smrg
852bb2e14f3Smrg	case 'v':
853bb2e14f3Smrg	  if (arg > 0)
854bb2e14f3Smrg	    *ptr++ = ' ';
855bb2e14f3Smrg	  strcpy(ptr, name->version);
856bb2e14f3Smrg	  ptr += strlen(ptr);
857bb2e14f3Smrg	  break;
858bb2e14f3Smrg
859bb2e14f3Smrg	case 'm':
860bb2e14f3Smrg	  if (arg > 0)
861bb2e14f3Smrg	    *ptr++ = ' ';
862bb2e14f3Smrg	  strcpy(ptr, name->machine);
863bb2e14f3Smrg	  ptr += strlen(ptr);
864bb2e14f3Smrg	  break;
865bb2e14f3Smrg
866bb2e14f3Smrg	default:
867bb2e14f3Smrg	  LogFatal(msg, fmt);
868bb2e14f3Smrg	}
869bb2e14f3Smrg    }
870bb2e14f3Smrg
871bb2e14f3Smrg  /* Just in case... */
872bb2e14f3Smrg  if (strlen(buf) >= sizeof(buf))
8731114aea8Smrg    LogFatal("Buffer overflow parsing uname.");
874bb2e14f3Smrg
875bb2e14f3Smrg  /* Parse the buffer.  The sscanf() return value is rarely correct. */
876bb2e14f3Smrg  *result = '\0';
877bb2e14f3Smrg  (void) sscanf(buf, fmt + arg + 1, result);
878bb2e14f3Smrg}
879bb2e14f3Smrg
880bb2e14f3Smrg/* Trim leading 0's and periods from version names.  The 0's cause
881bb2e14f3Smrg   the number to be interpreted as octal numbers.  Some version strings
882bb2e14f3Smrg   have the potential for different numbers of .'s in them.
883bb2e14f3Smrg */
884bb2e14f3Smrg
885bb2e14f3Smrgstatic char *
886bb2e14f3Smrgtrim_version(char *p)
887bb2e14f3Smrg{
888bb2e14f3Smrg
889bb2e14f3Smrg	if (p != 0 && *p != '\0')
890bb2e14f3Smrg	{
891bb2e14f3Smrg		while ((*p == '0' || *p == '.') && *(p + 1) != '\0')
892bb2e14f3Smrg			++p;
893bb2e14f3Smrg	}
894bb2e14f3Smrg	return (p);
895bb2e14f3Smrg}
896bb2e14f3Smrg#endif
897bb2e14f3Smrg
898bb2e14f3Smrg#if defined(linux) || defined(__GLIBC__)
899bb2e14f3Smrgconst char *libc_c=
900bb2e14f3Smrg"#include <stdio.h>\n"
901bb2e14f3Smrg"#include <ctype.h>\n"
902bb2e14f3Smrg"\n"
903bb2e14f3Smrg"#if 1\n"
904bb2e14f3Smrg"#pragma weak gnu_get_libc_version\n"
905bb2e14f3Smrg"#pragma weak __libc_version\n"
906bb2e14f3Smrg"#pragma weak __linux_C_lib_version\n"
907bb2e14f3Smrg"#endif\n"
908bb2e14f3Smrg"\n"
909bb2e14f3Smrg"extern const char * gnu_get_libc_version (void);\n"
910bb2e14f3Smrg"extern const char * __linux_C_lib_version;\n"
911bb2e14f3Smrg"extern const char __libc_version [];\n"
912bb2e14f3Smrg"\n"
913bb2e14f3Smrg"int\n"
914bb2e14f3Smrg"main ()\n"
915bb2e14f3Smrg"{\n"
916bb2e14f3Smrg"  int libcmajor = 0, libcminor = 0, libcteeny = 0;\n"
917bb2e14f3Smrg"  const char * ptr = NULL;\n"
918bb2e14f3Smrg"  int glibcmajor = 0;\n"
919bb2e14f3Smrg"\n"
920bb2e14f3Smrg"  if (gnu_get_libc_version != 0)\n"
921bb2e14f3Smrg"  {\n"
922bb2e14f3Smrg"    ptr = gnu_get_libc_version ();\n"
923bb2e14f3Smrg"    glibcmajor = 4;\n"
924bb2e14f3Smrg"  }\n"
925bb2e14f3Smrg"  else if (&__libc_version != 0)\n"
926bb2e14f3Smrg"  {\n"
927bb2e14f3Smrg"    ptr = __libc_version;\n"
928bb2e14f3Smrg"    glibcmajor = 4;\n"
929bb2e14f3Smrg"  }\n"
930bb2e14f3Smrg"  else if (&__linux_C_lib_version != 0)\n"
931bb2e14f3Smrg"  {\n"
932bb2e14f3Smrg"    ptr = __linux_C_lib_version;\n"
933bb2e14f3Smrg"  }\n"
934bb2e14f3Smrg"  else\n"
935bb2e14f3Smrg"  {\n"
936bb2e14f3Smrg"    libcmajor = 0; libcminor = 0; libcteeny = 0;\n"
937bb2e14f3Smrg"  }\n"
938bb2e14f3Smrg"\n"
939bb2e14f3Smrg"  if (ptr)\n"
940bb2e14f3Smrg"  {\n"
941bb2e14f3Smrg"    while (!isdigit (*ptr))\n"
942bb2e14f3Smrg"      ptr++;\n"
943bb2e14f3Smrg"\n"
944bb2e14f3Smrg"    sscanf (ptr, \"%d.%d.%d\", &libcmajor, &libcminor, &libcteeny);\n"
945bb2e14f3Smrg"    libcmajor += glibcmajor;\n"
946bb2e14f3Smrg"  }\n"
947bb2e14f3Smrg"\n"
948bb2e14f3Smrg"  printf(\"#define DefaultLinuxCLibMajorVersion %d\\n\", libcmajor);\n"
949bb2e14f3Smrg"  printf(\"#define DefaultLinuxCLibMinorVersion %d\\n\", libcminor);\n"
950bb2e14f3Smrg"  printf(\"#define DefaultLinuxCLibTeenyVersion %d\\n\", libcteeny);\n"
951bb2e14f3Smrg"\n"
952bb2e14f3Smrg"  return 0;\n"
953bb2e14f3Smrg"}\n"
954bb2e14f3Smrg;
955bb2e14f3Smrg
956bb2e14f3Smrgstatic void
957bb2e14f3Smrgget_libc_version(FILE *inFile)
958bb2e14f3Smrg{
959bb2e14f3Smrg  char aout[4096], *tmpdir;
960bb2e14f3Smrg  FILE *fp;
961bb2e14f3Smrg  const char *format = "%s -o %s -x c -";
962bb2e14f3Smrg  char *cc;
963bb2e14f3Smrg  int len;
964bb2e14f3Smrg  char *command;
965bb2e14f3Smrg
966bb2e14f3Smrg  /* If $TMPDIR is defined and has an acceptable length,
967a5399cb1Smrg   * use that as tmp dir, else use /tmp.  That fixes
968bb2e14f3Smrg   * problems with /tmp mounted "noexec".
969bb2e14f3Smrg   */
970bb2e14f3Smrg  if((tmpdir = getenv("TMPDIR")) != NULL && strlen(tmpdir) < (4096-13))
971bb2e14f3Smrg    strcpy(aout, tmpdir);
972bb2e14f3Smrg  else
973bb2e14f3Smrg    strcpy(aout, "/tmp");
974bb2e14f3Smrg  strcat(aout, "/imakeXXXXXX");
975bb2e14f3Smrg
976bb2e14f3Smrg  /* Pre-create temp file safely */
977bb2e14f3Smrg  {
978bb2e14f3Smrg    /* Linux + ELF has mkstemp() */
979bb2e14f3Smrg    int tmpfd;
980bb2e14f3Smrg    if ((tmpfd = mkstemp(aout)) == -1) {
981bb2e14f3Smrg      perror("mkstemp");
982bb2e14f3Smrg      abort();
983bb2e14f3Smrg    }
984bb2e14f3Smrg    close(tmpfd);
985bb2e14f3Smrg  }
986bb2e14f3Smrg  cc = getenv ("CC");
987bb2e14f3Smrg  if (cc == NULL)
988bb2e14f3Smrg    cc = "gcc";
989bb2e14f3Smrg  len = strlen (aout) + strlen (format) + strlen (cc);
990bb2e14f3Smrg  if (len < 128) len = 128;
991bb2e14f3Smrg  if((command = alloca (len)) == NULL)
992bb2e14f3Smrg    abort();
993bb2e14f3Smrg
994bb2e14f3Smrg  if (snprintf (command , len, format, cc, aout) == len)
995bb2e14f3Smrg    abort ();
996bb2e14f3Smrg
997bb2e14f3Smrg  fp = popen (command, "w");
998bb2e14f3Smrg  if (fp == NULL || fprintf (fp, "%s\n", libc_c) < 0
999bb2e14f3Smrg      || pclose (fp) != 0)
1000bb2e14f3Smrg    abort ();
1001bb2e14f3Smrg
1002bb2e14f3Smrg  fp = popen (aout, "r");
1003bb2e14f3Smrg  if (fp == NULL)
1004bb2e14f3Smrg    abort ();
1005bb2e14f3Smrg
1006bb2e14f3Smrg  while (fgets (command, len, fp))
1007bb2e14f3Smrg    fprintf (inFile, command);
1008bb2e14f3Smrg
1009bb2e14f3Smrg  len = pclose (fp);
1010bb2e14f3Smrg  remove (aout);
1011bb2e14f3Smrg  if (len)
1012bb2e14f3Smrg    abort ();
1013bb2e14f3Smrg}
1014bb2e14f3Smrg#endif
1015bb2e14f3Smrg
1016bb2e14f3Smrg#if defined(__OpenBSD__) || defined(__DragonFly__)
1017bb2e14f3Smrgstatic void
1018bb2e14f3Smrgget_stackprotector(FILE *inFile)
1019bb2e14f3Smrg{
1020bb2e14f3Smrg  FILE *fp;
1021bb2e14f3Smrg  char *cc;
1022bb2e14f3Smrg  char command[1024], buf[1024];
1023a5399cb1Smrg
1024bb2e14f3Smrg  cc = getenv("CC");
1025bb2e14f3Smrg  if (cc == NULL) {
1026bb2e14f3Smrg    cc = "cc";
1027bb2e14f3Smrg  }
1028bb2e14f3Smrg  snprintf(command, sizeof(command), "%s -v 2>&1", cc);
1029bb2e14f3Smrg  fp = popen(command, "r");
1030a5399cb1Smrg  if (fp == NULL)
1031bb2e14f3Smrg    abort();
1032bb2e14f3Smrg  while (fgets(buf, sizeof(buf), fp)) {
1033bb2e14f3Smrg    if (strstr(buf, "propolice") != NULL) {
1034bb2e14f3Smrg      fprintf(inFile, "#define ProPoliceSupport YES\n");
1035bb2e14f3Smrg      break;
1036bb2e14f3Smrg    }
1037bb2e14f3Smrg  }
1038a5399cb1Smrg  pclose(fp);
1039bb2e14f3Smrg}
1040bb2e14f3Smrg#endif
1041a5399cb1Smrg
1042bb2e14f3Smrg
1043bb2e14f3Smrg#if defined CROSSCOMPILE || defined linux || defined(__GLIBC__)
1044bb2e14f3Smrgstatic void
1045bb2e14f3Smrgget_distrib(FILE *inFile)
1046bb2e14f3Smrg{
1047bb2e14f3Smrg  struct stat sb;
1048bb2e14f3Smrg
10491114aea8Smrg  static const char*   suse = "/etc/SuSE-release";
10501114aea8Smrg  static const char* redhat = "/etc/redhat-release";
10511114aea8Smrg  static const char* debian = "/etc/debian_version";
1052bb2e14f3Smrg
1053bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxUnknown    0");
1054bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxSuSE       1");
1055bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxCaldera    2");
1056bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxCraftworks 3");
1057bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxDebian     4");
1058bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxInfoMagic  5");
1059bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxKheops     6");
1060bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxPro        7");
1061bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxRedHat     8");
1062bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxSlackware  9");
1063bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxTurbo      10");
1064bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxWare       11");
1065bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define LinuxYggdrasil  12");
1066bb2e14f3Smrg
1067a5399cb1Smrg# ifdef CROSSCOMPILE
1068bb2e14f3Smrg  if (CrossCompiling) {
1069bb2e14f3Smrg      fprintf (inFile, "%s\n",
1070bb2e14f3Smrg	       "#define DefaultLinuxDistribution LinuxUnknown");
1071bb2e14f3Smrg      fprintf (inFile, "%s\n", "#define DefaultLinuxDistName Unknown");
1072bb2e14f3Smrg      return;
1073bb2e14f3Smrg  }
1074a5399cb1Smrg# endif
1075bb2e14f3Smrg  if (lstat (suse, &sb) == 0) {
1076bb2e14f3Smrg    fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxSuSE");
1077bb2e14f3Smrg    fprintf (inFile, "%s\n", "#define DefaultLinuxDistName SuSE");
1078bb2e14f3Smrg    return;
1079bb2e14f3Smrg  }
1080bb2e14f3Smrg  if (lstat (redhat, &sb) == 0) {
1081bb2e14f3Smrg    fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxRedHat");
1082bb2e14f3Smrg    fprintf (inFile, "%s\n", "#define DefaultLinuxDistName RedHat");
1083bb2e14f3Smrg    return;
1084bb2e14f3Smrg  }
1085bb2e14f3Smrg  if (lstat (debian, &sb) == 0) {
1086bb2e14f3Smrg    fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxDebian");
1087bb2e14f3Smrg    fprintf (inFile, "%s\n", "#define DefaultLinuxDistName Debian");
1088bb2e14f3Smrg    /* You could also try to get the version of the Debian distrib by looking
1089bb2e14f3Smrg     * at the content of /etc/debian_version */
1090bb2e14f3Smrg    return;
1091bb2e14f3Smrg  }
1092bb2e14f3Smrg  /* what's the definitive way to tell what any particular distribution is? */
1093bb2e14f3Smrg
1094bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define DefaultLinuxDistribution LinuxUnknown");
1095bb2e14f3Smrg  fprintf (inFile, "%s\n", "#define DefaultLinuxDistName Unknown");
1096bb2e14f3Smrg  /* would like to know what version of the distribution it is */
1097bb2e14f3Smrg}
1098bb2e14f3Smrg
1099bb2e14f3Smrgstatic void
1100bb2e14f3Smrgget_ld_version(FILE *inFile)
1101bb2e14f3Smrg{
1102bb2e14f3Smrg  FILE* ldprog;
1103bb2e14f3Smrg  signed char c;
1104bb2e14f3Smrg  int ldmajor, ldminor;
1105bb2e14f3Smrg  const char *ld = "ld -v";
1106bb2e14f3Smrg
1107a5399cb1Smrg# ifdef CROSSCOMPILE
1108bb2e14f3Smrg  if (CrossCompiling) {
1109bb2e14f3Smrg      char cmd[PATH_MAX];
1110bb2e14f3Smrg      strcpy (cmd, CrossCompileDir);
1111bb2e14f3Smrg      strcat (cmd,"/");
1112bb2e14f3Smrg      strcat (cmd,ld);
1113bb2e14f3Smrg      ldprog = popen (cmd, "r");
1114bb2e14f3Smrg  } else
1115a5399cb1Smrg# endif
1116bb2e14f3Smrg      ldprog = popen (ld, "r");
1117bb2e14f3Smrg
1118bb2e14f3Smrg  if (ldprog) {
1119bb2e14f3Smrg    do {
1120bb2e14f3Smrg      c = fgetc (ldprog);
1121bb2e14f3Smrg    } while (c != EOF && !isdigit (c));
1122bb2e14f3Smrg    ungetc (c, ldprog);
1123bb2e14f3Smrg    (void) fscanf (ldprog, "%d.%d", &ldmajor, &ldminor);
1124bb2e14f3Smrg    /* Start conversion to a more rational number */
1125bb2e14f3Smrg    if ((ldmajor > 2) || ((ldmajor == 2) && (ldminor > 9)))
1126bb2e14f3Smrg	ldmajor *= 100;
1127bb2e14f3Smrg    else
1128bb2e14f3Smrg	ldmajor *= 10;
1129bb2e14f3Smrg
1130bb2e14f3Smrg    fprintf(inFile, "#define DefaultLinuxBinUtilsMajorVersion %d\n",
1131bb2e14f3Smrg	    ldmajor + ldminor);
1132bb2e14f3Smrg    pclose (ldprog);
1133bb2e14f3Smrg  }
1134bb2e14f3Smrg}
1135bb2e14f3Smrg#endif
1136bb2e14f3Smrg
1137bb2e14f3Smrg#if defined __FreeBSD__
1138bb2e14f3Smrgstatic void
1139bb2e14f3Smrgget_binary_format(FILE *inFile)
1140bb2e14f3Smrg{
1141bb2e14f3Smrg  int mib[2];
1142bb2e14f3Smrg  size_t len;
1143bb2e14f3Smrg  int osrel = 0;
1144bb2e14f3Smrg  FILE *objprog = NULL;
1145bb2e14f3Smrg  int iself = 0;
1146bb2e14f3Smrg  char buf[10];
1147bb2e14f3Smrg  char cmd[PATH_MAX];
1148bb2e14f3Smrg
1149bb2e14f3Smrg  mib[0] = CTL_KERN;
1150bb2e14f3Smrg  mib[1] = KERN_OSRELDATE;
1151bb2e14f3Smrg  len = sizeof(osrel);
1152bb2e14f3Smrg  sysctl(mib, 2, &osrel, &len, NULL, 0);
1153bb2e14f3Smrg  if (CrossCompiling) {
1154bb2e14f3Smrg      strcpy (cmd, CrossCompileDir);
1155bb2e14f3Smrg      strcat (cmd, "/");
1156bb2e14f3Smrg      strcat (cmd,"objformat");
1157bb2e14f3Smrg  } else
1158bb2e14f3Smrg      strcpy (cmd, "objformat");
1159bb2e14f3Smrg
1160bb2e14f3Smrg  if (osrel >= 300004 &&
1161bb2e14f3Smrg      (objprog = popen(cmd, "r")) != NULL &&
1162bb2e14f3Smrg      fgets(buf, sizeof(buf), objprog) != NULL &&
1163bb2e14f3Smrg      strncmp(buf, "elf", 3) == 0)
1164bb2e14f3Smrg    iself = 1;
1165bb2e14f3Smrg  if (objprog)
1166bb2e14f3Smrg    pclose(objprog);
1167bb2e14f3Smrg
1168bb2e14f3Smrg  fprintf(inFile, "#define DefaultToElfFormat %s\n", iself ? "YES" : "NO");
1169bb2e14f3Smrg}
1170bb2e14f3Smrg#endif
1171bb2e14f3Smrg
1172bb2e14f3Smrg#if defined(sun) && defined(__SVR4)
1173bb2e14f3Smrg/* Runs Sun compiler command and parses output - this is a bit of a hack
1174bb2e14f3Smrg * as it depends on the particular output format of the -V flag, but it's
1175bb2e14f3Smrg * worked for many releases.
1176bb2e14f3Smrg *
1177bb2e14f3Smrg * Input : cmd - command to run (called with -V flag)
1178bb2e14f3Smrg *	   path - path to command to run (use $PATH if NULL)
1179bb2e14f3Smrg * Output: cmajor & cminor - major and minor versions if found
1180bb2e14f3Smrg * Returns: 0 if successful, -1 if not.
1181bb2e14f3Smrg */
1182bb2e14f3Smrgstatic int
1183a5399cb1Smrgask_sun_compiler_for_versions(const char *cmd, const char *path,
1184bb2e14f3Smrg  int *cmajor, int *cminor)
1185bb2e14f3Smrg{
1186bb2e14f3Smrg  char buf[BUFSIZ];
1187bb2e14f3Smrg  char cmdtorun[PATH_MAX];
1188bb2e14f3Smrg  char* vptr;
1189bb2e14f3Smrg  FILE* ccproc;
1190bb2e14f3Smrg  const char vflag[] = " -V 2>&1";
1191bb2e14f3Smrg  int retval = -1;
1192a5399cb1Smrg
1193bb2e14f3Smrg  int len = strlen(cmd) + sizeof(vflag);
1194bb2e14f3Smrg
1195bb2e14f3Smrg  if (path != NULL) {
1196bb2e14f3Smrg      len += strlen(path) + 1;
1197bb2e14f3Smrg  }
1198bb2e14f3Smrg
1199bb2e14f3Smrg  if (len < sizeof(cmdtorun)) {
1200bb2e14f3Smrg      if (path != NULL) {
1201bb2e14f3Smrg	  sprintf(cmdtorun, "%s/%s %s", path, cmd, vflag);
1202bb2e14f3Smrg      } else {
1203bb2e14f3Smrg	  sprintf(cmdtorun, "%s %s", cmd, vflag);
1204bb2e14f3Smrg      }
1205bb2e14f3Smrg
1206bb2e14f3Smrg      if ((ccproc = popen (cmdtorun, "r")) != NULL) {
1207bb2e14f3Smrg	  if (fgets (buf, sizeof(buf), ccproc) != NULL) {
1208bb2e14f3Smrg	      vptr = strrchr (buf, 'C');
1209bb2e14f3Smrg	      if (vptr) {
1210bb2e14f3Smrg		  for (; (*vptr != '\0') && !isdigit(*vptr); vptr++) {
1211bb2e14f3Smrg		      /* Do nothing - just scanning for first digit */
1212bb2e14f3Smrg		  }
1213bb2e14f3Smrg		  if (*vptr != '\0') {
1214bb2e14f3Smrg		      if (sscanf (vptr, "%d.%d", cmajor, cminor) == 2) {
1215bb2e14f3Smrg			  retval = 0;
1216bb2e14f3Smrg		      }
1217bb2e14f3Smrg		  }
1218bb2e14f3Smrg	      }
1219bb2e14f3Smrg	      if (retval != 0) {
1220a5399cb1Smrg		  fprintf(stderr,
1221bb2e14f3Smrg		    "warning: could not parse version number in output of:\n"
1222bb2e14f3Smrg		    "         %s\n", cmdtorun);
1223bb2e14f3Smrg	      }
1224bb2e14f3Smrg	      while (fgets (buf, sizeof(buf), ccproc) != NULL) {};
1225bb2e14f3Smrg	  }
1226bb2e14f3Smrg	  pclose (ccproc);
1227bb2e14f3Smrg      }
1228bb2e14f3Smrg  }
1229bb2e14f3Smrg  return retval;
1230bb2e14f3Smrg}
1231bb2e14f3Smrg
1232bb2e14f3Smrg/* Find Sun compilers and their versions if present */
1233bb2e14f3Smrgstatic void
1234bb2e14f3Smrgget_sun_compiler_versions (FILE *inFile)
1235bb2e14f3Smrg{
1236bb2e14f3Smrg  const char* sunpro_path = "/opt/SUNWspro/bin";
1237bb2e14f3Smrg  int cmajor, cminor, found = 0;
1238bb2e14f3Smrg
1239bb2e14f3Smrg  /* If cross-compiling, only check CrossCompilerDir for compilers.
1240a5399cb1Smrg   * If not cross-compiling, first check cc in users $PATH,
1241bb2e14f3Smrg   * then try /opt/SUNWspro if not found in the users $PATH
1242bb2e14f3Smrg   */
1243bb2e14f3Smrg
1244a5399cb1Smrg# if defined CROSSCOMPILE
1245bb2e14f3Smrg  if (CrossCompiling) {
1246bb2e14f3Smrg      if (ask_sun_compiler_for_versions("cc", CrossCompileDir,
1247bb2e14f3Smrg	&cmajor, &cminor) == 0) {
1248bb2e14f3Smrg	      found = 1;
1249bb2e14f3Smrg      }
1250a5399cb1Smrg  }
1251bb2e14f3Smrg  else
1252a5399cb1Smrg# endif
1253a5399cb1Smrg  {
1254bb2e14f3Smrg      if (ask_sun_compiler_for_versions("cc", NULL, &cmajor, &cminor) == 0) {
1255bb2e14f3Smrg	  found = 1;
1256bb2e14f3Smrg      } else if (ask_sun_compiler_for_versions("cc", sunpro_path,
1257bb2e14f3Smrg	&cmajor, &cminor) == 0) {
1258bb2e14f3Smrg	  found = 1;
1259bb2e14f3Smrg	  fprintf(inFile, "#define DefaultSunProCCompilerDir %s", sunpro_path);
1260bb2e14f3Smrg      }
1261bb2e14f3Smrg  }
1262bb2e14f3Smrg
1263bb2e14f3Smrg  if (found) {
1264bb2e14f3Smrg      fprintf (inFile,
1265bb2e14f3Smrg	"#define DefaultSunProCCompilerMajorVersion %d\n", cmajor);
1266bb2e14f3Smrg      fprintf (inFile,
1267bb2e14f3Smrg	"#define DefaultSunProCCompilerMinorVersion %d\n", cminor);
1268bb2e14f3Smrg  }
1269bb2e14f3Smrg
1270bb2e14f3Smrg  /* Now do it again for C++ compiler (CC) */
1271bb2e14f3Smrg  found = 0;
1272a5399cb1Smrg# if defined CROSSCOMPILE
1273bb2e14f3Smrg  if (CrossCompiling) {
1274bb2e14f3Smrg      if (ask_sun_compiler_for_versions("CC", CrossCompileDir,
1275bb2e14f3Smrg	&cmajor, &cminor) == 0) {
1276bb2e14f3Smrg	      found = 1;
1277bb2e14f3Smrg      }
1278a5399cb1Smrg  }
1279bb2e14f3Smrg  else
1280a5399cb1Smrg# endif
1281a5399cb1Smrg  {
1282bb2e14f3Smrg      if (ask_sun_compiler_for_versions("CC", NULL, &cmajor, &cminor) == 0) {
1283bb2e14f3Smrg	  found = 1;
1284bb2e14f3Smrg      } else if (ask_sun_compiler_for_versions("CC", sunpro_path,
1285bb2e14f3Smrg	&cmajor, &cminor) == 0) {
1286bb2e14f3Smrg	  found = 1;
1287a5399cb1Smrg	  fprintf(inFile,
1288bb2e14f3Smrg		"#define DefaultSunProCplusplusCompilerDir %s", sunpro_path);
1289bb2e14f3Smrg      }
1290bb2e14f3Smrg  }
1291bb2e14f3Smrg
1292bb2e14f3Smrg  if (found) {
1293bb2e14f3Smrg      fprintf (inFile,
1294bb2e14f3Smrg	"#define DefaultSunProCplusplusCompilerMajorVersion %d\n",
1295bb2e14f3Smrg	cmajor);
1296bb2e14f3Smrg      fprintf (inFile,
1297bb2e14f3Smrg	"#define DefaultSunProCplusplusCompilerMinorVersion %d\n",
1298bb2e14f3Smrg	cminor);
1299bb2e14f3Smrg  }
1300bb2e14f3Smrg}
1301bb2e14f3Smrg#endif
1302bb2e14f3Smrg
1303bb2e14f3Smrg#if defined CROSSCOMPILE || defined  __GNUC__
1304bb2e14f3Smrgstatic void
1305bb2e14f3Smrgget_gcc_version(FILE *inFile, char *name)
1306bb2e14f3Smrg{
1307bb2e14f3Smrg    fprintf (inFile, "#define HasGcc 1\n");
1308a5399cb1Smrg# ifdef CROSSCOMPILE
1309bb2e14f3Smrg    if (CrossCompiling)
1310bb2e14f3Smrg    {
1311bb2e14f3Smrg	if (gnu_c > 1) {
1312bb2e14f3Smrg	    fprintf (inFile, "#define HasGcc2 1\n");
1313bb2e14f3Smrg	    if (gnu_c > 2)
1314bb2e14f3Smrg		fprintf (inFile, "#define HasGcc3 1\n");
1315bb2e14f3Smrg	}
1316bb2e14f3Smrg	fprintf (inFile, "#define GccMajorVersion %d\n", gnu_c);
1317bb2e14f3Smrg	fprintf (inFile, "#define GccMinorVersion %d\n", gnu_c_minor);
1318bb2e14f3Smrg    } else
1319a5399cb1Smrg# endif
1320bb2e14f3Smrg    {
1321a5399cb1Smrg# if __GNUC__ > 1
1322bb2e14f3Smrg	fprintf (inFile, "#define HasGcc2 1\n");
1323a5399cb1Smrg#  if __GNUC__ > 2
1324bb2e14f3Smrg	fprintf (inFile, "#define HasGcc3 1\n");
1325a5399cb1Smrg#  endif
1326bb2e14f3Smrg# endif
1327bb2e14f3Smrg	fprintf (inFile, "#define GccMajorVersion %d\n", __GNUC__);
1328bb2e14f3Smrg	fprintf (inFile, "#define GccMinorVersion %d\n", __GNUC_MINOR__);
1329bb2e14f3Smrg    }
1330a5399cb1Smrg# if defined(HAS_MERGE_CONSTANTS)
1331bb2e14f3Smrg    fprintf (inFile, "#define HasGccMergeConstants %d\n", HAS_MERGE_CONSTANTS);
1332a5399cb1Smrg# endif
1333bb2e14f3Smrg}
1334bb2e14f3Smrg#endif
1335bb2e14f3Smrg
1336bb2e14f3Smrgstatic boolean
1337bb2e14f3Smrgget_gcc(char *cmd)
1338bb2e14f3Smrg{
1339bb2e14f3Smrg  struct stat sb;
13401114aea8Smrg    static const char* gcc_path[] = {
1341a5399cb1Smrg#if defined(linux) || \
1342bb2e14f3Smrg     defined(__NetBSD__) || \
1343bb2e14f3Smrg     defined(__OpenBSD__) || \
1344bb2e14f3Smrg     defined(__FreeBSD__) || \
1345bb2e14f3Smrg     defined(__DragonFly__) || \
1346bb2e14f3Smrg     defined(__APPLE__) || \
1347bb2e14f3Smrg     defined(__CYGWIN__) || \
1348bb2e14f3Smrg     defined(__MINGW32__) || \
1349bb2e14f3Smrg     defined(__GNU__) || \
1350bb2e14f3Smrg     defined(__GLIBC__)
1351bb2e14f3Smrg	"/usr/bin/cc",	/* for Linux PostIncDir */
1352a5399cb1Smrg#endif
1353bb2e14f3Smrg	"/usr/local/bin/gcc",
1354bb2e14f3Smrg	"/opt/gnu/bin/gcc",
1355bb2e14f3Smrg	"/usr/pkg/bin/gcc"
1356bb2e14f3Smrg    };
1357bb2e14f3Smrg
1358bb2e14f3Smrg#ifdef CROSSCOMPILE
13591114aea8Smrg    static const char* cross_cc_name[] = {
1360bb2e14f3Smrg	"cc",
1361bb2e14f3Smrg	"gcc"
1362bb2e14f3Smrg    };
1363bb2e14f3Smrg
1364bb2e14f3Smrg    if (CrossCompiling) {
1365bb2e14f3Smrg	int i;
1366bb2e14f3Smrg	for (i = 0; i < sizeof (cross_cc_name) / sizeof cross_cc_name[0]; i++){
1367bb2e14f3Smrg	    strcpy (cmd, CrossCompileDir);
1368bb2e14f3Smrg	    strcat (cmd, "/");
1369bb2e14f3Smrg	    strcat (cmd, cross_cc_name[i]);
1370bb2e14f3Smrg	    if (lstat (cmd, &sb) == 0) {
1371bb2e14f3Smrg		return TRUE;
1372bb2e14f3Smrg		break;
1373bb2e14f3Smrg	    }
1374bb2e14f3Smrg	}
1375bb2e14f3Smrg    } else
1376bb2e14f3Smrg#endif
1377bb2e14f3Smrg      {
1378bb2e14f3Smrg	int i;
1379bb2e14f3Smrg	for (i = 0; i < sizeof (gcc_path) / sizeof gcc_path[0]; i++) {
1380bb2e14f3Smrg	    if (lstat (gcc_path[i], &sb) == 0) {
1381bb2e14f3Smrg		strcpy (cmd, gcc_path[i]);
1382bb2e14f3Smrg		return TRUE;
1383bb2e14f3Smrg	    }
1384bb2e14f3Smrg	}
1385bb2e14f3Smrg      }
1386bb2e14f3Smrg    return FALSE;
1387bb2e14f3Smrg}
1388bb2e14f3Smrg
1389bb2e14f3Smrg#if defined CROSSCOMPILE || !defined __UNIXOS2__
1390bb2e14f3Smrgstatic void
1391bb2e14f3Smrgget_gcc_incdir(FILE *inFile, char* name)
1392bb2e14f3Smrg{
1393bb2e14f3Smrg  FILE* gccproc;
1394bb2e14f3Smrg  char buf[PATH_MAX];
1395bb2e14f3Smrg  char cmd[PATH_MAX];
1396bb2e14f3Smrg  char* ptr;
1397bb2e14f3Smrg
1398bb2e14f3Smrg  strcpy(cmd,name);
1399bb2e14f3Smrg
1400bb2e14f3Smrg  buf[0] = '\0';
1401bb2e14f3Smrg  strcat (cmd, " --print-libgcc-file-name");
1402bb2e14f3Smrg  if ((gccproc = popen (cmd, "r")) != NULL) {
1403bb2e14f3Smrg      if (fgets (buf, PATH_MAX, gccproc) != NULL) {
1404bb2e14f3Smrg	  ptr = strstr (buf, "libgcc.a");
1405bb2e14f3Smrg	  if (ptr) strcpy (ptr, "include");
1406bb2e14f3Smrg      }
1407bb2e14f3Smrg      (void) pclose (gccproc);
1408bb2e14f3Smrg  }
1409bb2e14f3Smrg
1410bb2e14f3Smrg  if (buf[0])
1411bb2e14f3Smrg      fprintf (inFile, "#define DefaultGccIncludeDir \"%s\"\n", buf);
1412bb2e14f3Smrg}
1413bb2e14f3Smrg#endif
1414bb2e14f3Smrg
1415bb2e14f3Smrgboolean
1416bb2e14f3Smrgdefine_os_defaults(FILE *inFile)
1417bb2e14f3Smrg{
1418bb2e14f3Smrg#if defined CROSSCOMPILE || ( !defined(WIN32) && !defined(__UNIXOS2__) )
1419a5399cb1Smrg# ifdef CROSSCOMPILE
1420a5399cb1Smrg#  ifdef __GNUC__
1421bb2e14f3Smrg  if (1)
1422a5399cb1Smrg#  else
1423bb2e14f3Smrg  if ((sys != win32) && (sys != emx))
1424a5399cb1Smrg#  endif
1425a5399cb1Smrg# endif
1426bb2e14f3Smrg    {
1427bb2e14f3Smrg# if (defined(DEFAULT_OS_NAME) || defined(DEFAULT_OS_MAJOR_REV) || \
1428bb2e14f3Smrg     defined(DEFAULT_OS_MINOR_REV) || defined(DEFAULT_OS_TEENY_REV))
1429bb2e14f3Smrg	struct utsname *name = NULL;
1430bb2e14f3Smrg	struct utsname uts_name;
1431bb2e14f3Smrg	char buf[SYS_NMLN * 5 + 1];
1432bb2e14f3Smrg
1433bb2e14f3Smrg	/* Obtain the system information. */
1434a5399cb1Smrg#  ifdef CROSSCOMPILE
1435bb2e14f3Smrg      if (!CrossCompiling)
1436a5399cb1Smrg#  endif
1437bb2e14f3Smrg      {
1438bb2e14f3Smrg	  if (uname(&uts_name) < 0)
14391114aea8Smrg	      LogFatal("Cannot invoke uname");
1440bb2e14f3Smrg	  else
1441bb2e14f3Smrg	      name = &uts_name;
1442bb2e14f3Smrg      }
1443a5399cb1Smrg#  if defined CROSSCOMPILE && (defined linux || defined(__GLIBC__))
1444bb2e14f3Smrg      else {
1445bb2e14f3Smrg	  strncpy(uts_name.sysname,cross_uts_sysname,SYS_NMLN);
1446bb2e14f3Smrg	  strncpy(uts_name.release,cross_uts_release,SYS_NMLN);
1447bb2e14f3Smrg	  strncpy(uts_name.version,cross_uts_version,SYS_NMLN);
1448bb2e14f3Smrg	  strncpy(uts_name.machine,cross_uts_machine,SYS_NMLN);
1449bb2e14f3Smrg	  name = &uts_name;
1450bb2e14f3Smrg      }
1451a5399cb1Smrg#  endif
1452a5399cb1Smrg#  ifdef __FreeBSD__
1453bb2e14f3Smrg       /* Override for compiling in chroot of other OS version, such as
1454bb2e14f3Smrg        * in the bento build cluster.
1455bb2e14f3Smrg        */
1456bb2e14f3Smrg       {
1457bb2e14f3Smrg	 char *e;
1458a5399cb1Smrg	 if ((e = getenv("OSREL")) != NULL &&
1459bb2e14f3Smrg	     strlen(name->sysname) + strlen(e) + 1 < SYS_NMLN) {
1460bb2e14f3Smrg	  strcpy(name->release, e);
1461bb2e14f3Smrg	  strcpy(name->version, name->sysname);
1462bb2e14f3Smrg	  strcat(name->version, " ");
1463bb2e14f3Smrg	  strcat(name->version, e);
1464bb2e14f3Smrg	 }
1465bb2e14f3Smrg       }
1466a5399cb1Smrg#  endif
1467bb2e14f3Smrg
1468bb2e14f3Smrg#  if defined DEFAULT_OS_NAME
1469bb2e14f3Smrg#   if defined CROSSCOMPILE
1470bb2e14f3Smrg      if (!CrossCompiling)
1471bb2e14f3Smrg#   endif
1472bb2e14f3Smrg	{
1473bb2e14f3Smrg	  parse_utsname(name, DEFAULT_OS_NAME, buf,
1474bb2e14f3Smrg			"Bad DEFAULT_OS_NAME syntax %s");
1475bb2e14f3Smrg#   ifdef DEFAULT_OS_NAME_FROB
1476bb2e14f3Smrg	  DEFAULT_OS_NAME_FROB(buf, sizeof buf);
1477bb2e14f3Smrg#   endif
1478bb2e14f3Smrg	  if (buf[0] != '\0')
1479bb2e14f3Smrg	    fprintf(inFile, "#define DefaultOSName %s\n", buf);
1480bb2e14f3Smrg	}
1481bb2e14f3Smrg#  endif
1482bb2e14f3Smrg
1483bb2e14f3Smrg#  if defined CROSSCOMPILE
1484bb2e14f3Smrg	if (CrossCompiling && defaultOsName) {
1485bb2e14f3Smrg	  parse_utsname(name, defaultOsName, buf,
1486bb2e14f3Smrg			"Bad DEFAULT_OS_NAME syntax %s");
1487bb2e14f3Smrg	  if (defaultOsNameFrob)
1488bb2e14f3Smrg	    defaultOsNameFrob(buf, sizeof buf);
1489bb2e14f3Smrg	  if (buf[0] != '\0')
1490bb2e14f3Smrg	    fprintf(inFile, "#define DefaultOSName %s\n", buf);
1491bb2e14f3Smrg	}
1492bb2e14f3Smrg#  endif
1493bb2e14f3Smrg
1494bb2e14f3Smrg#  ifdef DEFAULT_OS_MAJOR_REV
1495bb2e14f3Smrg#   if defined CROSSCOMPILE
1496bb2e14f3Smrg	if (!CrossCompiling)
1497bb2e14f3Smrg#   endif
1498bb2e14f3Smrg	  {
1499bb2e14f3Smrg	    parse_utsname(name, DEFAULT_OS_MAJOR_REV, buf,
1500bb2e14f3Smrg			  "Bad DEFAULT_OS_MAJOR_REV syntax %s");
1501bb2e14f3Smrg#   ifdef DEFAULT_OS_MAJOR_REV_FROB
1502bb2e14f3Smrg	    DEFAULT_OS_MAJOR_REV_FROB(buf, sizeof buf);
1503bb2e14f3Smrg#   endif
1504bb2e14f3Smrg	    fprintf(inFile, "#define DefaultOSMajorVersion %s\n",
1505bb2e14f3Smrg		    *buf ? trim_version(buf) : "0");
1506bb2e14f3Smrg	  }
1507bb2e14f3Smrg#  endif
1508bb2e14f3Smrg
1509bb2e14f3Smrg#  if defined CROSSCOMPILE
1510bb2e14f3Smrg	if (CrossCompiling && defaultOsMajorRev) {
1511bb2e14f3Smrg	  parse_utsname(name, defaultOsMajorRev, buf,
1512bb2e14f3Smrg			"Bad defaultOsMajorRev syntax %s");
1513bb2e14f3Smrg	  if (defaultOsMajorRevFrob)
1514bb2e14f3Smrg	    defaultOsMajorRevFrob(buf, sizeof buf);
1515bb2e14f3Smrg	  fprintf(inFile, "#define DefaultOSMajorVersion %s\n",
1516bb2e14f3Smrg		  *buf ? trim_version(buf) : "0");
1517bb2e14f3Smrg	}
1518bb2e14f3Smrg#  endif
1519bb2e14f3Smrg
1520bb2e14f3Smrg#  ifdef DEFAULT_OS_MINOR_REV
1521bb2e14f3Smrg#   if defined CROSSCOMPILE
1522bb2e14f3Smrg	if (!CrossCompiling)
1523bb2e14f3Smrg#   endif
1524bb2e14f3Smrg	  {
1525bb2e14f3Smrg	    parse_utsname(name, DEFAULT_OS_MINOR_REV, buf,
1526bb2e14f3Smrg			  "Bad DEFAULT_OS_MINOR_REV syntax %s");
1527bb2e14f3Smrg#   ifdef DEFAULT_OS_MINOR_REV_FROB
1528bb2e14f3Smrg	    DEFAULT_OS_MINOR_REV_FROB(buf, sizeof buf);
1529bb2e14f3Smrg#   endif
1530bb2e14f3Smrg	    fprintf(inFile, "#define DefaultOSMinorVersion %s\n",
1531bb2e14f3Smrg		    *buf ? trim_version(buf) : "0");
1532bb2e14f3Smrg	  }
1533bb2e14f3Smrg#  endif
1534bb2e14f3Smrg
1535bb2e14f3Smrg#  if defined CROSSCOMPILE
1536bb2e14f3Smrg	if (CrossCompiling && defaultOsMinorRev) {
1537bb2e14f3Smrg	  parse_utsname(name, defaultOsMinorRev, buf,
1538bb2e14f3Smrg			"Bad defaultOsMinorRev syntax %s");
1539bb2e14f3Smrg	  if (defaultOsMinorRevFrob)
1540bb2e14f3Smrg	    defaultOsMinorRevFrob(buf, sizeof buf);
1541bb2e14f3Smrg	  fprintf(inFile, "#define DefaultOSMinorVersion %s\n",
1542bb2e14f3Smrg		  *buf ? trim_version(buf) : "0");
1543bb2e14f3Smrg	}
1544bb2e14f3Smrg#  endif
1545bb2e14f3Smrg
1546bb2e14f3Smrg#  ifdef DEFAULT_OS_TEENY_REV
1547bb2e14f3Smrg#   if defined CROSSCOMPILE
1548bb2e14f3Smrg	if (!CrossCompiling)
1549bb2e14f3Smrg#   endif
1550bb2e14f3Smrg	  {
1551bb2e14f3Smrg	    parse_utsname(name, DEFAULT_OS_TEENY_REV, buf,
1552bb2e14f3Smrg			  "Bad DEFAULT_OS_TEENY_REV syntax %s");
1553bb2e14f3Smrg#   ifdef DEFAULT_OS_TEENY_REV_FROB
1554bb2e14f3Smrg	    DEFAULT_OS_TEENY_REV_FROB(buf, sizeof buf);
1555bb2e14f3Smrg#   endif
1556bb2e14f3Smrg	    fprintf(inFile, "#define DefaultOSTeenyVersion %s\n",
1557bb2e14f3Smrg		    *buf ? trim_version(buf) : "0");
1558bb2e14f3Smrg	  }
1559bb2e14f3Smrg#  endif
1560bb2e14f3Smrg
1561bb2e14f3Smrg#  if defined CROSSCOMPILE
1562bb2e14f3Smrg	if (CrossCompiling && defaultOsTeenyRev) {
1563bb2e14f3Smrg	  parse_utsname(name, defaultOsTeenyRev, buf,
1564bb2e14f3Smrg			"Bad defaultOsTeenyRev syntax %s");
1565bb2e14f3Smrg	  if (defaultOsTeenyRevFrob)
1566bb2e14f3Smrg	    defaultOsTeenyRevFrob(buf, sizeof buf);
1567bb2e14f3Smrg	  fprintf(inFile, "#define DefaultOSTeenyVersion %s\n",
1568bb2e14f3Smrg		  *buf ? trim_version(buf) : "0");
1569bb2e14f3Smrg	}
1570bb2e14f3Smrg#  endif
1571bb2e14f3Smrg
1572bb2e14f3Smrg#  ifdef DEFAULT_MACHINE_ARCHITECTURE
1573bb2e14f3Smrg#   if defined CROSSCOMPILE
1574bb2e14f3Smrg	if (!CrossCompiling)
1575bb2e14f3Smrg#   endif
1576bb2e14f3Smrg	  {
1577bb2e14f3Smrg	    parse_utsname(name, DEFAULT_MACHINE_ARCHITECTURE, buf,
1578bb2e14f3Smrg			  "Bad DEFAULT_MACHINE_ARCHITECTURE %s");
1579bb2e14f3Smrg	    fprintf(inFile, "#ifndef %s\n# define %s\n#endif\n", buf, buf);
1580bb2e14f3Smrg	  }
1581bb2e14f3Smrg#  endif
1582bb2e14f3Smrg
1583bb2e14f3Smrg#  if defined CROSSCOMPILE
1584bb2e14f3Smrg	if (CrossCompiling && defaultMachineArchitecture) {
1585bb2e14f3Smrg	  parse_utsname(name, defaultMachineArchitecture, buf,
1586bb2e14f3Smrg			"Bad defaultMachineArchitecture syntax %s");
1587bb2e14f3Smrg	  fprintf(inFile, "#ifndef %s\n# define %s\n#endif\n", buf, buf);
1588bb2e14f3Smrg	}
1589bb2e14f3Smrg#  endif
1590bb2e14f3Smrg# endif
1591bb2e14f3Smrg# if defined CROSSCOMPILE
1592bb2e14f3Smrg      if (CrossCompiling)
1593bb2e14f3Smrg	get_cross_compile_dir(inFile);
1594bb2e14f3Smrg      else
1595bb2e14f3Smrg# endif
1596bb2e14f3Smrg	  fprintf(inFile, "#define CrossCompiling NO\n");
1597bb2e14f3Smrg# if defined CROSSCOMPILE
1598bb2e14f3Smrg      if (CrossCompiling && sys == LinuX)
1599bb2e14f3Smrg# endif
1600bb2e14f3Smrg# if defined CROSSCOMPILE || defined linux || defined(__GLIBC__)
1601bb2e14f3Smrg#  if defined(CROSSCOMPILE) && defined(__linux__)
1602bb2e14f3Smrg	if (sys == LinuX)
1603bb2e14f3Smrg#  endif
1604bb2e14f3Smrg	  get_distrib (inFile);
1605bb2e14f3Smrg# endif
1606bb2e14f3Smrg# if defined linux || defined(__GLIBC__)
1607bb2e14f3Smrg#  if defined CROSSCOMPILE
1608bb2e14f3Smrg      if (!CrossCompiling)
1609bb2e14f3Smrg#  endif
1610bb2e14f3Smrg	  get_libc_version (inFile);
1611bb2e14f3Smrg#  if defined CROSSCOMPILE
1612bb2e14f3Smrg      else {
1613bb2e14f3Smrg	  fprintf(inFile,"#define DefaultLinuxCLibMajorVersion %d\n",
1614bb2e14f3Smrg		  glibc_major);
1615bb2e14f3Smrg	  fprintf(inFile,"#define DefaultLinuxCLibMinorVersion %d\n",
1616bb2e14f3Smrg		  glibc_minor);
1617bb2e14f3Smrg	  fprintf(inFile,"#define DefaultLinuxCLibTeenyVersion 0\n");
1618bb2e14f3Smrg      }
1619bb2e14f3Smrg#  endif
1620bb2e14f3Smrg# endif /* linux || __GLIBC__ */
1621bb2e14f3Smrg# if defined CROSSCOMPILE || defined linux || defined(__GLIBC__)
1622bb2e14f3Smrg#  if defined CROSSCOMPILE && defined(__linux__)
1623bb2e14f3Smrg      if (sys == LinuX)
1624bb2e14f3Smrg#  endif
1625bb2e14f3Smrg	  get_ld_version(inFile);
1626bb2e14f3Smrg# endif
1627bb2e14f3Smrg# if defined (sun) && defined(SVR4)
1628bb2e14f3Smrg      get_sun_compiler_versions (inFile);
1629bb2e14f3Smrg# endif
1630bb2e14f3Smrg# if defined CROSSCOMPILE || defined __GNUC__
1631bb2e14f3Smrg#  if defined CROSSCOMPILE
1632bb2e14f3Smrg      if (gnu_c)
1633bb2e14f3Smrg#  endif
1634bb2e14f3Smrg	{
1635bb2e14f3Smrg	  char name[PATH_MAX];
1636bb2e14f3Smrg	  if (get_gcc(name)) {
1637bb2e14f3Smrg	      get_gcc_version (inFile,name);
1638bb2e14f3Smrg#  if defined CROSSCOMPILE || !defined __UNIXOS2__
1639bb2e14f3Smrg#   if defined CROSSCOMPILE
1640bb2e14f3Smrg	      if (sys != emx)
1641bb2e14f3Smrg#   endif
1642bb2e14f3Smrg		  get_gcc_incdir(inFile,name);
1643bb2e14f3Smrg#  endif
1644bb2e14f3Smrg	  }
1645bb2e14f3Smrg	}
1646bb2e14f3Smrg# endif
1647bb2e14f3Smrg# if defined __FreeBSD__
1648bb2e14f3Smrg#  if defined CROSSCOMPILE
1649bb2e14f3Smrg      if (sys == freeBSD)
1650bb2e14f3Smrg#  endif
1651bb2e14f3Smrg	  get_binary_format(inFile);
1652bb2e14f3Smrg# endif
1653bb2e14f3Smrg    }
1654bb2e14f3Smrg#endif /* !WIN32 && !__UNIXOS2__*/
1655bb2e14f3Smrg#if defined WIN32
1656bb2e14f3Smrg# ifdef CROSSCOMPILE
1657bb2e14f3Smrg  else if (sys == win32 && !CrossCompiling)
1658bb2e14f3Smrg# endif
1659bb2e14f3Smrg    {
1660bb2e14f3Smrg      OSVERSIONINFO osvi;
1661bb2e14f3Smrg      static char* os_names[] = { "Win32s", "Windows 95", "Windows NT" };
1662bb2e14f3Smrg
1663bb2e14f3Smrg      memset(&osvi, 0, sizeof(OSVERSIONINFO));
1664bb2e14f3Smrg      osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
1665bb2e14f3Smrg      GetVersionEx (&osvi);
1666bb2e14f3Smrg
1667bb2e14f3Smrg      fprintf (inFile, "#define DefaultOSName Microsoft %s\n",
1668bb2e14f3Smrg	       os_names[osvi.dwPlatformId]);
1669bb2e14f3Smrg
1670bb2e14f3Smrg      fprintf(inFile, "#define DefaultOSMajorVersion %d\n", osvi.dwMajorVersion);
1671bb2e14f3Smrg      fprintf(inFile, "#define DefaultOSMinorVersion %d\n", osvi.dwMinorVersion);
1672bb2e14f3Smrg      fprintf(inFile, "#define DefaultOSTeenyVersion %d\n",
1673bb2e14f3Smrg	      osvi.dwBuildNumber & 0xFFFF);
1674bb2e14f3Smrg    }
1675bb2e14f3Smrg#endif /* WIN32 */
1676bb2e14f3Smrg#ifdef CROSSCOMPILE
1677bb2e14f3Smrg  else if (sys == emx)
1678bb2e14f3Smrg#endif
1679bb2e14f3Smrg#if defined CROSSCOMPILE || defined __UNIXOS2__
1680bb2e14f3Smrg    {
1681bb2e14f3Smrg      fprintf(inFile, "#define DefaultOSMajorVersion 4\n");
1682bb2e14f3Smrg      fprintf(inFile, "#define DefaultOSMinorVersion 0\n");
1683bb2e14f3Smrg      fprintf(inFile, "#define DefaultOSTeenyVersion 0\n");
1684bb2e14f3Smrg    }
1685bb2e14f3Smrg#endif /* EMX */
1686bb2e14f3Smrg#if defined(__OpenBSD__) || defined(__DragonFly__)
1687bb2e14f3Smrg  get_stackprotector(inFile);
1688bb2e14f3Smrg#endif
1689bb2e14f3Smrg  return FALSE;
1690bb2e14f3Smrg}
1691bb2e14f3Smrg
1692bb2e14f3Smrgvoid
16931114aea8Smrgcppit(const char *imakefile, const char *template, const char *masterc,
16941114aea8Smrg      FILE *outfd, const char *outfname)
1695bb2e14f3Smrg{
1696bb2e14f3Smrg	FILE	*inFile;
1697bb2e14f3Smrg
1698bb2e14f3Smrg	haveImakefileC = TRUE;
1699bb2e14f3Smrg	inFile = fopen(masterc, "w");
1700bb2e14f3Smrg	if (inFile == NULL)
1701bb2e14f3Smrg		LogFatal("Cannot open %s for output.", masterc);
1702bb2e14f3Smrg	if (fprintf(inFile, "%s\n", ImakefileCHeader) < 0 ||
1703bb2e14f3Smrg	    define_os_defaults(inFile) ||
1704bb2e14f3Smrg	    optional_include(inFile, "IMAKE_LOCAL_DEFINES", "localdefines") ||
1705bb2e14f3Smrg	    optional_include(inFile, "IMAKE_ADMIN_DEFINES", "admindefines") ||
1706bb2e14f3Smrg	    fprintf(inFile, "#define %s <%s>\n", ImakeDefSym, imakefile) < 0 ||
1707bb2e14f3Smrg	    fprintf(inFile, LocalDefineFmt, ImakeTmplSym, template) < 0 ||
1708bb2e14f3Smrg	    fprintf(inFile, IncludeFmt, ImakeTmplSym) < 0 ||
1709bb2e14f3Smrg	    optional_include(inFile, "IMAKE_ADMIN_MACROS", "adminmacros") ||
1710bb2e14f3Smrg	    optional_include(inFile, "IMAKE_LOCAL_MACROS", "localmacros") ||
1711bb2e14f3Smrg	    fflush(inFile) ||
1712bb2e14f3Smrg	    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