8129716881de17ccd8ab6244d7355de0d33fdb6e
[blender-staging.git] / extern / ode / dist / configurator.c
1 /*************************************************************************
2  *                                                                       *
3  * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
4  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
5  *                                                                       *
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     *
12  *       file LICENSE.TXT.                                               *
13  *   (2) The BSD-style license that is included with this library in     *
14  *       the file LICENSE-BSD.TXT.                                       *
15  *                                                                       *
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.                     *
20  *                                                                       *
21  *************************************************************************/
22
23 /*
24
25 this program discovers some system configuration stuff, prior to compiling
26 ODE. the usage is:
27
28   configurator <config.h-file-to-generate> <compiler-command-line>
29         <delete-command-line> <THIS_DIR-variable>
30
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:
34   * printf
35   * fopen (assumes 0 returned on failure)
36   * fclose
37   * fprintf
38   * system
39   * exit
40 except where stated, we do not assume anything about the return codes from
41 these functions.
42
43 why didn't i just use GNU autoconf? :
44   * autoconf needs a bourne shell and a bunch of other tools that windows
45     users may not have.
46   * i like reinventing the wheel.
47
48 */
49
50 #include <stdio.h>
51
52 /****************************************************************************/
53 /* project constants */
54
55 #define SETUP_SHLIB_DEFS \
56   "#ifndef SHAREDLIBIMPORT\n" \
57   "#define SHAREDLIBIMPORT\n" \
58   "#endif\n" \
59   "#ifndef SHAREDLIBEXPORT\n" \
60   "#define SHAREDLIBEXPORT\n" \
61   "#endif\n"
62
63 /* the config.h header */
64 char *config_h_part1 =
65 "/* per-machine configuration. this file is automatically generated. */\n"
66 "\n"
67 "#ifndef _ODE_CONFIG_H_\n"
68 "#define _ODE_CONFIG_H_\n"
69 "\n"
70 "/* shared lib definitions */\n"
71 SETUP_SHLIB_DEFS
72 "\n"
73 "/* standard system headers */\n";
74
75
76 char *config_h_part2 =
77 "\n"
78 "#ifdef __cplusplus\n"
79 "extern \"C\" {\n"
80 "#endif\n"
81 "\n";
82
83 /* the config.h footer */
84 char *config_h_footer =
85 "#ifdef __cplusplus\n"
86 "}\n"
87 "#endif\n"
88 "#endif\n";
89
90 /****************************************************************************/
91 /* implementations of some string functions. these are prefixed with 'x'
92  * to prevent any conflicts with built-in functions.
93  */
94
95 #define strcpy xstrcpy
96 void xstrcpy (char *dest, char *src)
97 {
98   while (*src) *dest++ = *src++;
99   *dest = 0;
100 }
101
102
103 #define strcat xstrcat
104 void xstrcat (char *dest, char *src)
105 {
106   while (*dest) dest++;
107   while (*src) *dest++ = *src++;
108   *dest = 0;
109 }
110
111 /****************************************************************************/
112 /* utility functions */
113
114 /* print an error message and exit */
115
116 void fatal_error (char *message)
117 {
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, "
121           "please email\n"
122           "your changes to the ODE mailing list (ode@q12.org).\n\n", message);
123   exit (0);
124 }
125
126
127 /* open a file, generate an error if it can't be done */
128
129 FILE * xfopen (char *filename, char *mode)
130 {
131   FILE *f;
132   f = fopen (filename,mode);
133   if (!f) fatal_error ("can not open a file");
134   return f;
135 }
136
137
138 /* return 1 if the file exists or 0 if not */
139
140 int file_exists (char *filename)
141 {
142   FILE *f;
143   f = fopen (filename,"rb");
144   if (f) fclose (f);
145   return (f != 0);
146 }
147
148
149 /* write a string to a new file */
150
151 void write_to_file (char *filename, char *s)
152 {
153   FILE *f = xfopen (filename,"wt");
154   fprintf (f,"%s",s);
155   fclose (f);
156 }
157
158
159 /* write a comment to a header file */
160
161 void write_header_comment (FILE *file, char *description)
162 {
163   fprintf (file,"/* %s */\n",description);
164   printf ("%s ...\n",description);
165 }
166
167
168 /* delete a file */
169
170 char *delete_cmd_line = 0;
171 void delete_file (char *filename)
172 {
173   char cmd[1000];
174   strcpy (cmd,delete_cmd_line);
175   strcat (cmd," ");
176   strcat (cmd,filename);
177   printf ("%s\n",cmd);
178   system (cmd);
179 }
180
181
182 /* run a compile command */
183
184 char *compile_cmd_line = 0;
185 void compile (char *output, char *input)
186 {
187   char cmd[1000];
188   strcpy (cmd,compile_cmd_line);
189   strcat (cmd,output);
190   strcat (cmd," ");
191   strcat (cmd,input);
192   printf ("%s\n",cmd);
193   system (cmd);
194 }
195
196
197 /* run a program we've just compiled */
198
199 char *run_prefix = "";
200 void run (char *filename)
201 {
202   char cmd[1000];
203   strcpy (cmd,run_prefix);
204   strcat (cmd,filename);
205   printf ("%s\n",cmd);
206   system (cmd);
207 }
208
209 /****************************************************************************/
210 /* system tests */
211
212 void check_if_this_is_a_pentium (FILE *file)
213 {
214   write_header_comment (file,"is this a pentium on a gcc-based platform?");
215   write_to_file ("ctest.c",
216                  "int main() {\n"
217                  "  asm (\"mov $0,%%eax\\n cpuid\\n\" : : : \"%eax\");\n"
218                  "  return 0;\n"
219                  "}\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");
224   }
225   else {
226     fprintf (file,"/* #define PENTIUM 1 -- not a pentium */\n\n");
227   }
228
229   delete_file ("ctest.c");
230   delete_file ("ctest.exe");
231 }
232
233 /****************************************************************************/
234 /* tests: standard headers */
235
236 void get_all_standard_headers (FILE *file)
237 {
238   int i;
239   FILE *f;
240   char *header[7] = {"stdio.h", "stdlib.h", "math.h", "string.h",
241                      "stdarg.h", "malloc.h", "alloca.h"};
242
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]);
246     fclose (f);
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]);
251     }
252   }
253
254   delete_file ("ctest.c");
255   delete_file ("ctest.exe");
256 }
257
258 /****************************************************************************/
259 /* tests: typedefs and constants for ODE */
260
261 void get_ODE_integer_typedefs (FILE *file)
262 {
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");
269   }
270   else if (sizeof(int) == 4) {
271     fprintf (file,"typedef int int32;\ntypedef unsigned int uint32;\n");
272   }
273   else {
274     fatal_error ("can not find 4 byte integer type");
275   }
276   fprintf (file,"\n"
277            "/* an integer type that we can safely cast a pointer to and\n"
278            " * from without loss of bits.\n"
279            " */\n");
280   if (sizeof(short) == sizeof(void*)) {
281     fprintf (file,"typedef unsigned short intP;\n");
282   }
283   else if (sizeof(int) == sizeof(void*)) {
284     fprintf (file,"typedef unsigned int intP;\n");
285   }
286   else if (sizeof(long int) == sizeof(void*)) {
287     fprintf (file,"typedef unsigned long int intP;\n");
288   }
289   fprintf (file,"\n");
290 }
291
292
293 void get_ODE_float_stuff (FILE *file)
294 {
295   char *suffix,*type;
296   int i;
297   FILE *f;
298
299 #define SHARED_LIB_SPEC_DECISION \
300     "#if defined SHARED_CONFIG_H_INCLUDED_FROM_DEFINING_FILE\n" \
301     "  #define GLOBAL_SHAREDLIB_SPEC SHAREDLIBEXPORT\n" \
302     "#else \n" \
303     "  #define GLOBAL_SHAREDLIB_SPEC SHAREDLIBIMPORT\n" \
304     "#endif\n"
305
306 #define UNDEF_SHAREDLIB_SPEC "\n#undef GLOBAL_SHAREDLIB_SPEC\n"
307
308 #ifdef dSINGLE
309
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)"
311
312   char *inc[6]  = {"#include <math.h>",
313                    "#include <math.h>",
314                    "",
315                    "",
316                    "",
317                    ""};
318   char *decl[6] = {
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;"};
325   char *inf[6]  = {
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};
332
333 #else /* not dSINGLE, must be dDOUBLE */
334
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)"
336
337   char *inc[5]  = {
338     "#include <math.h>",
339     "",
340     "",
341     "",
342     ""};
343   char *decl[5] = {
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;"};
349   char *inf[5]  = {
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};
355 #endif
356
357   write_header_comment (file,"select the base floating point type");
358 #ifdef dSINGLE
359   fprintf (file,"#define dSINGLE 1\n\n");
360   type = "float";
361   suffix = "f";
362 #else
363   fprintf (file,"#define dDOUBLE 1\n\n");
364   type = "double";
365   suffix = "";
366 #endif
367
368   /* infinity */
369   write_header_comment (file,"the floating point infinity");
370
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");
374     fprintf (f,
375              "#include <stdio.h>\n"
376              "#define SHARED_CONFIG_H_INCLUDED_FROM_DEFINING_FILE 1\n"
377              SETUP_SHLIB_DEFS
378              "%s\n"
379              "%s\n"
380              "%s\n"
381              "int main() {\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"
386              "    fclose (f);\n"
387              "  }\n"
388              "  return 0;\n"
389              "}\n"
390              ,inc[i],inf[i],decl[i],suffix,suffix);
391     fclose (f);
392     delete_file ("data");
393     compile ("ctest.exe","ctest.c");
394     run ("ctest.exe");
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");
401       return;
402     }
403   }
404
405   fatal_error ("can't determine dInfinity constant");
406 }
407
408 /****************************************************************************/
409
410 int main (int argc, char **argv)
411 {
412   FILE *file;
413
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];
419
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");
423 #endif
424
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);
433   fclose (file);
434
435   printf ("\n*** configurator succeeded ***\n\n");
436   return 0;
437 }