1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
21 *************************************************************************/
25 this program discovers some system configuration stuff, prior to compiling
28 configurator <config.h-file-to-generate> <compiler-command-line>
29 <delete-command-line> <THIS_DIR-variable>
31 this program looks long, but it really has an extremely simple structure and
32 should be very easy for anyone to modify. it should be very portable as it
33 is written in straight ANSI C and only uses the following library functions:
35 * fopen (assumes 0 returned on failure)
40 except where stated, we do not assume anything about the return codes from
43 why didn't i just use GNU autoconf? :
44 * autoconf needs a bourne shell and a bunch of other tools that windows
46 * i like reinventing the wheel.
52 /****************************************************************************/
53 /* project constants */
55 #define SETUP_SHLIB_DEFS \
56 "#ifndef SHAREDLIBIMPORT\n" \
57 "#define SHAREDLIBIMPORT\n" \
59 "#ifndef SHAREDLIBEXPORT\n" \
60 "#define SHAREDLIBEXPORT\n" \
63 /* the config.h header */
64 char *config_h_part1 =
65 "/* per-machine configuration. this file is automatically generated. */\n"
67 "#ifndef _ODE_CONFIG_H_\n"
68 "#define _ODE_CONFIG_H_\n"
70 "/* shared lib definitions */\n"
73 "/* standard system headers */\n";
76 char *config_h_part2 =
78 "#ifdef __cplusplus\n"
83 /* the config.h footer */
84 char *config_h_footer =
85 "#ifdef __cplusplus\n"
90 /****************************************************************************/
91 /* implementations of some string functions. these are prefixed with 'x'
92 * to prevent any conflicts with built-in functions.
95 #define strcpy xstrcpy
96 void xstrcpy (char *dest, char *src)
98 while (*src) *dest++ = *src++;
103 #define strcat xstrcat
104 void xstrcat (char *dest, char *src)
106 while (*dest) dest++;
107 while (*src) *dest++ = *src++;
111 /****************************************************************************/
112 /* utility functions */
114 /* print an error message and exit */
116 void fatal_error (char *message)
118 printf ("\n*** configurator failed: %s.\n\n"
119 "please fix your configuration and try again.\n"
120 "if you have to fix the configurator program or the makefiles, "
122 "your changes to the ODE mailing list (ode@q12.org).\n\n", message);
127 /* open a file, generate an error if it can't be done */
129 FILE * xfopen (char *filename, char *mode)
132 f = fopen (filename,mode);
133 if (!f) fatal_error ("can not open a file");
138 /* return 1 if the file exists or 0 if not */
140 int file_exists (char *filename)
143 f = fopen (filename,"rb");
149 /* write a string to a new file */
151 void write_to_file (char *filename, char *s)
153 FILE *f = xfopen (filename,"wt");
159 /* write a comment to a header file */
161 void write_header_comment (FILE *file, char *description)
163 fprintf (file,"/* %s */\n",description);
164 printf ("%s ...\n",description);
170 char *delete_cmd_line = 0;
171 void delete_file (char *filename)
174 strcpy (cmd,delete_cmd_line);
176 strcat (cmd,filename);
182 /* run a compile command */
184 char *compile_cmd_line = 0;
185 void compile (char *output, char *input)
188 strcpy (cmd,compile_cmd_line);
197 /* run a program we've just compiled */
199 char *run_prefix = "";
200 void run (char *filename)
203 strcpy (cmd,run_prefix);
204 strcat (cmd,filename);
209 /****************************************************************************/
212 void check_if_this_is_a_pentium (FILE *file)
214 write_header_comment (file,"is this a pentium on a gcc-based platform?");
215 write_to_file ("ctest.c",
217 " asm (\"mov $0,%%eax\\n cpuid\\n\" : : : \"%eax\");\n"
220 delete_file ("ctest.exe");
221 compile ("ctest.exe","ctest.c");
222 if (file_exists ("ctest.exe")) {
223 fprintf (file,"#define PENTIUM 1\n\n");
226 fprintf (file,"/* #define PENTIUM 1 -- not a pentium */\n\n");
229 delete_file ("ctest.c");
230 delete_file ("ctest.exe");
233 /****************************************************************************/
234 /* tests: standard headers */
236 void get_all_standard_headers (FILE *file)
240 char *header[7] = {"stdio.h", "stdlib.h", "math.h", "string.h",
241 "stdarg.h", "malloc.h", "alloca.h"};
243 for (i=0; i < sizeof(header)/sizeof(char*); i++) {
244 FILE *f = xfopen ("ctest.c","wt");
245 fprintf (f,"#include <%s>\nint main() { return 0; }\n",header[i]);
247 delete_file ("ctest.exe");
248 compile ("ctest.exe","ctest.c");
249 if (file_exists ("ctest.exe")) {
250 fprintf (file,"#include <%s>\n",header[i]);
254 delete_file ("ctest.c");
255 delete_file ("ctest.exe");
258 /****************************************************************************/
259 /* tests: typedefs and constants for ODE */
261 void get_ODE_integer_typedefs (FILE *file)
263 write_header_comment (file,"integer types (we assume int >= 32 bits)");
264 if (sizeof(char) != 1) fatal_error ("expecting sizeof(char) == 1");
265 if (sizeof(int) < 4) fatal_error ("expecting sizeof(int) >= 4");
266 fprintf (file,"typedef char int8;\ntypedef unsigned char uint8;\n");
267 if (sizeof(short) == 4) {
268 fprintf (file,"typedef short int32;\ntypedef unsigned short uint32;\n");
270 else if (sizeof(int) == 4) {
271 fprintf (file,"typedef int int32;\ntypedef unsigned int uint32;\n");
274 fatal_error ("can not find 4 byte integer type");
277 "/* an integer type that we can safely cast a pointer to and\n"
278 " * from without loss of bits.\n"
280 if (sizeof(short) == sizeof(void*)) {
281 fprintf (file,"typedef unsigned short intP;\n");
283 else if (sizeof(int) == sizeof(void*)) {
284 fprintf (file,"typedef unsigned int intP;\n");
286 else if (sizeof(long int) == sizeof(void*)) {
287 fprintf (file,"typedef unsigned long int intP;\n");
293 void get_ODE_float_stuff (FILE *file)
299 #define SHARED_LIB_SPEC_DECISION \
300 "#if defined SHARED_CONFIG_H_INCLUDED_FROM_DEFINING_FILE\n" \
301 " #define GLOBAL_SHAREDLIB_SPEC SHAREDLIBEXPORT\n" \
303 " #define GLOBAL_SHAREDLIB_SPEC SHAREDLIBIMPORT\n" \
306 #define UNDEF_SHAREDLIB_SPEC "\n#undef GLOBAL_SHAREDLIB_SPEC\n"
310 #define INFBYTES SHARED_LIB_SPEC_DECISION "union dInfBytes { unsigned char c[4]; float f; };\nextern GLOBAL_SHAREDLIB_SPEC union dInfBytes dInfinityValue;\n#define dInfinity (dInfinityValue.f)"
312 char *inc[6] = {"#include <math.h>",
319 "SHAREDLIBEXPORT double dInfinityValue = HUGE_VALF;",
320 "SHAREDLIBEXPORT double dInfinityValue = HUGE_VAL;",
321 "SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0x7f,0x80,0,0}};",
322 "SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0,0,0x80,0x7f}};",
323 "SHAREDLIBEXPORT double dInfinityValue = 1.0f/0.0f;",
324 "SHAREDLIBEXPORT double dInfinityValue = 1e20f;"};
326 SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
327 SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
328 INFBYTES UNDEF_SHAREDLIB_SPEC,
329 INFBYTES UNDEF_SHAREDLIB_SPEC,
330 SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
331 SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC};
333 #else /* not dSINGLE, must be dDOUBLE */
335 #define INFBYTES SHARED_LIB_SPEC_DECISION "union dInfBytes { unsigned char c[8]; double d; };\nextern GLOBAL_SHAREDLIB_SPEC union dInfBytes dInfinityValue;\n#define dInfinity (dInfinityValue.d)"
344 "SHAREDLIBEXPORT double dInfinityValue = HUGE_VAL;",
345 "SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0x7f,0xf0,0,0,0,0,0,0}};",
346 "SHAREDLIBEXPORT union dInfBytes dInfinityValue = {{0,0,0,0,0,0,0xf0,0x7f}};",
347 "SHAREDLIBEXPORT double dInfinityValue = 1.0/0.0;",
348 "SHAREDLIBEXPORT double dInfinityValue = 1e20;"};
350 SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
351 INFBYTES UNDEF_SHAREDLIB_SPEC,
352 INFBYTES UNDEF_SHAREDLIB_SPEC,
353 SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC,
354 SHARED_LIB_SPEC_DECISION "extern GLOBAL_SHAREDLIB_SPEC double dInfinityValue;\n#define dInfinity dInfinityValue" UNDEF_SHAREDLIB_SPEC};
357 write_header_comment (file,"select the base floating point type");
359 fprintf (file,"#define dSINGLE 1\n\n");
363 fprintf (file,"#define dDOUBLE 1\n\n");
369 write_header_comment (file,"the floating point infinity");
371 /* try the different infinity constants until one works */
372 for (i=0; i < sizeof(inf)/sizeof(char*); i++) {
373 f = xfopen ("ctest.c","wt");
375 "#include <stdio.h>\n"
376 "#define SHARED_CONFIG_H_INCLUDED_FROM_DEFINING_FILE 1\n"
382 " if (dInfinity > 1e10%s && -dInfinity < -1e10%s &&\n"
383 " -dInfinity < dInfinity) {\n"
384 " FILE *f = fopen (\"data\",\"wt\");\n"
385 " fprintf (f,\"foo\\n\");\n"
390 ,inc[i],inf[i],decl[i],suffix,suffix);
392 delete_file ("data");
393 compile ("ctest.exe","ctest.c");
395 if (file_exists ("data")) {
396 fprintf (file,"#define DINFINITY_DECL %s\n",decl[i]);
397 fprintf (file,"%s\n\n",inf[i]);
398 delete_file ("ctest.c");
399 delete_file ("ctest.exe");
400 delete_file ("data");
405 fatal_error ("can't determine dInfinity constant");
408 /****************************************************************************/
410 int main (int argc, char **argv)
414 if (argc < 4 || argc > 5)
415 fatal_error ("configurator expects 3 or 4 arguments");
416 compile_cmd_line = argv[2];
417 delete_cmd_line = argv[3];
418 if (argc >= 5) run_prefix = argv[4];
420 /* check some defines we should have been compiled with */
421 #if !defined(dSINGLE) && !defined(dDOUBLE)
422 fatal_error ("you must set PRECISION to either SINGLE or DOUBLE");
425 file = xfopen (argv[1],"wt");
426 fprintf (file,config_h_part1);
427 get_all_standard_headers (file);
428 fprintf (file,config_h_part2);
429 check_if_this_is_a_pentium (file);
430 get_ODE_integer_typedefs (file);
431 get_ODE_float_stuff (file);
432 fprintf (file,config_h_footer);
435 printf ("\n*** configurator succeeded ***\n\n");