Fixed the terminal not fully functional error
[utio.git] / bsconf.c
blobab3db827353d66ff60102cf3e031e4226cb9a088
1 /* This file is part of bsconf - a configure replacement.
3 * Copyright (C) 2005 by Mike Sharov <msharov@users.sourceforge.net>
4 * This file is free software, distributed under the MIT License.
6 * bsconf was written to replace autoconf-made configure scripts, which
7 * through their prohibitively large size have fallen out of favor with
8 * many developers. The configure script performs many time-consuming
9 * tests, the results of which are usually unused because no progammer
10 * likes to pollute his code with ifdefs. This program performs the
11 * program and header lookup and substitutes @CONSTANTS@ in specified
12 * files. bsconf.h is used to define which files, programs, and headers
13 * to look for. config.h is generated, but the headers are only checked
14 * for existence and the functions are assumed to exist (nobody is going
15 * to ifdef around every memchr). Most compilers these days have all the
16 * headers you want, and if yours does not, there is always gcc. There
17 * is simply no excuse for using a braindead compiler when better ones
18 * are freely available.
21 #include <stdio.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/utsname.h>
27 #include <sys/stat.h>
29 /*- The configuration header and its types ---------------------------*/
31 #define VectorSize(v) (sizeof(v) / sizeof(*v))
33 /*#define const*/
34 /*typedef unsigned int uint;*/
35 typedef char* pchar_t;
36 typedef const char* cpchar_t;
38 typedef struct {
39 int m_bDefaultOn;
40 cpchar_t m_Description;
41 } SComponentInfo;
43 #include "bsconf.h"
44 #if !defined(BSCONF_VERSION) || BSCONF_VERSION < 0x03
45 #error Your bsconf.h file is too old; please update its format.
46 #endif
48 /*- Internal types and macros ----------------------------------------*/
50 #define foreachN(i,v,n) for (i = 0; i != VectorSize(v) / n; ++ i)
51 #define foreach(i,v) foreachN(i,v,1)
53 typedef struct {
54 pchar_t data;
55 uint allocated;
56 uint used;
57 uint last;
58 uint page;
59 } SBuf, *pbuf_t;
60 #define NULL_BUF { NULL, 0, 0, 0, 0 }
62 typedef enum {
63 vv_prefix,
64 vv_exec_prefix,
65 vv_bindir,
66 vv_sbindir,
67 vv_libexecdir,
68 vv_datadir,
69 vv_sysconfdir,
70 vv_sharedstatedir,
71 vv_localstatedir,
72 vv_libdir,
73 vv_gcclibdir,
74 vv_includedir,
75 vv_oldincludedir,
76 vv_gccincludedir,
77 vv_custominclude,
78 vv_customlib,
79 vv_infodir,
80 vv_mandir,
81 vv_build,
82 vv_host,
83 vv_last
84 } EVV;
86 static char g_ConfigV [vv_last][16] = {
87 "prefix",
88 "exec_prefix",
89 "bindir",
90 "sbindir",
91 "libexecdir",
92 "datadir",
93 "sysconfdir",
94 "sharedstatedir",
95 "localstatedir",
96 "libdir",
97 "gcclibdir",
98 "includedir",
99 "oldincludedir",
100 "gccincludedir",
101 "custominclude",
102 "customlib",
103 "infodir",
104 "mandir",
105 "build",
106 "host"
109 static SBuf g_Subs = NULL_BUF;
110 static SBuf g_ConfigVV [vv_last], g_ProgLocs [VectorSize (g_ProgVars) / 4];
111 static SBuf g_CustomLibDirs [16], g_CustomIncDirs [16];
112 static int g_nCustomLibDirs = 0, g_nCustomIncDirs = 0;
113 static struct utsname g_Uname;
114 static uint g_CpuCapBits = 0;
116 typedef enum {
117 sys_Unknown,
118 sys_Linux,
119 sys_Mac,
120 sys_Bsd,
121 sys_Sun,
122 sys_Alpha
123 } ESysType;
125 static ESysType g_SysType = sys_Unknown;
127 /*- Libc-like functions that might not exist -------------------------*/
129 static int StrLen (cpchar_t str)
131 int l;
132 for (l = 0; *str; ++ l, ++ str);
133 return (l);
136 static pchar_t copy_n (cpchar_t src, pchar_t dest, int n)
138 while (n--)
139 *dest++ = *src++;
140 return (dest);
143 static void fill_n (pchar_t str, int n, char v)
145 while (n--)
146 *str++ = v;
149 static void copy_backward (cpchar_t src, pchar_t dest, uint n)
151 dest += n; src += n;
152 while (n--)
153 *--dest = *--src;
156 static void Lowercase (pchar_t str)
158 for (; *str; ++ str)
159 if (*str >= 'A' && *str <= 'Z')
160 *str += 'a' - 'A';
163 static int compare (cpchar_t str1, cpchar_t str2)
165 while (*str1 && *str2 && *str1 == *str2)
166 ++ str1, ++ str2;
167 return (!*str2);
170 static void FatalError (cpchar_t errortext)
172 perror (errortext);
173 exit(-1);
176 /*- Malloc buffer object ---------------------------------------------*/
178 static pchar_t buf_addspace (pbuf_t p, uint n)
180 if ((p->used += n) > p->allocated) {
181 p->allocated = p->used;
182 if (!(p->data = (pchar_t) realloc (p->data, p->allocated)))
183 FatalError ("out of memory");
185 return (p->data + p->used - n);
188 static void buf_clear (pbuf_t p) { p->used = p->last; }
189 static void append (cpchar_t s, pbuf_t p) { copy_n (s, buf_addspace (p, StrLen(s)), StrLen(s)); }
190 static void copy (cpchar_t s, pbuf_t p) { buf_clear (p); append (s, p); }
192 static void buf_copy_n (cpchar_t s, pbuf_t p, uint n)
194 buf_clear (p);
195 copy_n (s, buf_addspace (p, n), n);
198 static void append2 (cpchar_t s1, cpchar_t s2, pbuf_t p)
200 uint l1 = StrLen(s1), l2 = StrLen(s2);
201 copy_n (s2, copy_n (s1, buf_addspace (p, l1+l2), l1), l2);
204 static void buf_cap (pbuf_t p)
206 if (p->used >= p->allocated || p->data [p->used]) {
207 *buf_addspace(p,1) = 0;
208 --p->used;
212 static pchar_t buf_resize_fragment (pbuf_t p, uint fo, uint os, uint ns)
214 int d = ns - os;
215 if (d <= 0) {
216 copy_n (p->data + fo - d, p->data + fo, p->used - (fo - d));
217 p->used += d;
218 } else {
219 buf_addspace (p, d);
220 copy_backward (p->data + fo, p->data + fo + d, p->used - (fo + d));
222 buf_cap (p);
223 return (p->data + fo);
226 static void pushstring (pbuf_t p) { buf_cap (p); p->last = p->used + 1; }
227 static pchar_t buf_str (pbuf_t p) { buf_cap (p); return (p->data + p->last); }
228 #define S(buf) buf_str(&buf)
230 static void buf_free (pbuf_t p)
232 if (p->data)
233 free (p->data);
234 p->data = NULL;
235 p->allocated = p->used = p->last = 0;
238 /*- File I/O with buffer objects -------------------------------------*/
240 static void ReadFile (cpchar_t filename, pbuf_t buf)
242 struct stat st;
243 FILE* fp = fopen (filename, "r");
244 if (!fp)
245 FatalError ("open");
246 if (fstat (fileno(fp), &st))
247 FatalError ("stat");
248 buf_clear (buf);
249 buf->used = fread (buf_addspace (buf, st.st_size + 1), 1, st.st_size, fp);
250 if (((int) buf->used) < 0)
251 FatalError ("read");
252 buf_cap (buf);
253 fclose (fp);
256 static void WriteFile (cpchar_t filename, pbuf_t buf)
258 uint bw;
259 FILE* fp = fopen (filename, "w");
260 if (!fp)
261 FatalError ("open");
262 bw = fwrite (buf->data, 1, buf->used, fp);
263 if (bw != buf->used)
264 FatalError ("write");
265 if (fclose (fp))
266 FatalError ("close");
269 /*- Substitution engine ----------------------------------------------*/
271 static void MakeSubstString (cpchar_t str, pbuf_t pbuf)
273 copy ("@", pbuf);
274 append2 (str, "@", pbuf);
277 static void Substitute (cpchar_t matchStr, cpchar_t replaceStr)
279 copy (matchStr, &g_Subs);
280 pushstring (&g_Subs);
281 copy (replaceStr, &g_Subs);
282 pushstring (&g_Subs);
285 static void ExecuteSubstitutionList (pbuf_t buf)
287 uint ml, rl;
288 cpchar_t m = g_Subs.data, r;
289 pchar_t cp, fbfirst = S(*buf);
291 while (m < g_Subs.data + g_Subs.used) {
292 ml = StrLen (m);
293 r = m + ml + 1;
294 rl = StrLen (r);
295 for (cp = fbfirst; cp < fbfirst + buf->used; ++ cp) {
296 if (!compare (cp, m))
297 continue;
298 cp = buf_resize_fragment (buf, cp - fbfirst, ml, rl);
299 fbfirst = S(*buf);
300 cp = copy_n (r, cp, rl);
302 m = r + rl + 1;
306 static void ApplySubstitutions (void)
308 uint f;
309 SBuf srcFile = NULL_BUF, fileBuf = NULL_BUF;
310 foreach (f, g_Files) {
311 copy (g_Files[f], &srcFile);
312 append (".in", &srcFile);
313 ReadFile (S(srcFile), &fileBuf);
314 ExecuteSubstitutionList (&fileBuf);
315 WriteFile (g_Files[f], &fileBuf);
317 buf_free (&fileBuf);
318 buf_free (&srcFile);
321 /*- Housekeeping -----------------------------------------------------*/
323 static void InitGlobals (void)
325 uint i;
326 SBuf nullBuf = NULL_BUF;
327 g_Subs = nullBuf;
328 foreach (i, g_ConfigVV)
329 g_ConfigVV[i] = nullBuf;
330 foreach (i, g_CustomLibDirs)
331 g_CustomLibDirs[i] = nullBuf;
332 foreach (i, g_CustomIncDirs)
333 g_CustomIncDirs[i] = nullBuf;
334 foreach (i, g_ProgLocs)
335 g_ProgLocs[i] = nullBuf;
338 static void FreeGlobals (void)
340 uint i;
341 buf_free (&g_Subs);
342 foreach (i, g_ConfigVV)
343 buf_free (&g_ConfigVV[i]);
344 foreach (i, g_CustomLibDirs)
345 buf_free (&g_CustomLibDirs[i]);
346 foreach (i, g_CustomIncDirs)
347 buf_free (&g_CustomIncDirs[i]);
348 foreach (i, g_ProgLocs)
349 buf_free (&g_ProgLocs[i]);
352 static void PrintHelp (void)
354 uint i;
355 printf (
356 "This program configures " PACKAGE_STRING " to adapt to many kinds of systems.\n"
357 "\n"
358 "Usage: configure [OPTION] ...\n"
359 "\n"
360 "Configuration:\n"
361 " --help\t\tdisplay this help and exit\n"
362 " --version\t\tdisplay version information and exit\n"
363 "\n"
364 "Installation directories:\n"
365 " --prefix=PREFIX\tarchitecture-independent files [/usr/local]\n"
366 " --exec-prefix=EPREFIX\tarchitecture-dependent files [PREFIX]\n"
367 " --bindir=DIR\t\tuser executables [EPREFIX/bin]\n"
368 " --sbindir=DIR\t\tsystem admin executables [EPREFIX/sbin]\n"
369 " --libexecdir=DIR\tprogram executables [EPREFIX/libexec]\n"
370 " --datadir=DIR\t\tread-only architecture-independent data [PREFIX/share]\n"
371 " --sysconfdir=DIR\tread-only single-machine data [PREFIX/etc]\n"
372 " --sharedstatedir=DIR\tmodifiable architecture-independent data [PREFIX/com]\n"
373 " --localstatedir=DIR\tmodifiable single-machine data [PREFIX/var]\n"
374 " --libdir=DIR\t\tobject code libraries [EPREFIX/lib]\n"
375 " --includedir=DIR\tC header files [PREFIX/include]\n"
376 " --oldincludedir=DIR\tC header files for non-gcc [/usr/include]\n"
377 " --gccincludedir=DIR\tGCC internal header files [PREFIX/include]\n"
378 " --custominclude=DIR\tNonstandard header file location (cumulative)\n"
379 " --customlib=DIR\tNonstandard library file location (cumulative)\n"
380 " --infodir=DIR\t\tinfo documentation [PREFIX/info]\n"
381 " --mandir=DIR\t\tman documentation [PREFIX/man]\n"
382 "\n"
383 "System types:\n"
384 " --build=BUILD\t\tconfigure for building on BUILD [guessed]\n"
385 " --host=HOST\t\tcross-compile to build programs to run on HOST [BUILD]\n"
387 if (VectorSize(g_Components)) {
388 printf ("\nOptions:\n");
389 foreach (i, g_ComponentInfos) {
390 if (!g_ComponentInfos[i].m_Description[0])
391 continue;
392 if (g_ComponentInfos[i].m_bDefaultOn)
393 printf (" --without-%-12s%s\n", g_Components[i * 3], g_ComponentInfos[i].m_Description);
394 else
395 printf (" --with-%-15s%s\n", g_Components[i * 3], g_ComponentInfos[i].m_Description);
398 printf (
399 "\nSome influential environment variables:\n"
400 " CC\t\tC compiler\t\tCFLAGS\n"
401 " CPP\t\tC preprocessor\t\tCPPFLAGS\n"
402 " CXX\t\tC++ compiler\t\tCXXFLAGS\n"
403 " LD\t\tLinker\t\t\tLDFLAGS\n"
404 "\n"
405 "Report bugs to " PACKAGE_BUGREPORT ".\n");
406 exit (0);
409 static void PrintVersion (void)
411 printf (PACKAGE_NAME " configure " PACKAGE_VERSION "\n"
412 "\nUsing bsconf package version 0.3\n"
413 "Copyright (c) 2003-2005, Mike Sharov <msharov@users.sourceforge.net>\n"
414 "This configure script and the bsconf package are free software.\n"
415 "Unlimited permission to copy, distribute, and modify is granted.\n");
416 exit (0);
419 /*- Configuration routines -------------------------------------------*/
421 static void GetConfigVarValues (int argc, cpchar_t const* argv)
423 int a, apos, cvl;
424 uint cv;
425 /* --var=VALUE */
426 for (a = 0; a < argc; ++ a) {
427 if (!compare (argv[a], "--"))
428 continue;
429 apos = 2;
430 if (compare (argv[a] + apos, "help"))
431 PrintHelp();
432 else if (compare (argv[a] + apos, "version"))
433 PrintVersion();
434 else if (compare (argv[a] + apos, "with")) {
435 apos += 4;
436 if (compare (argv[a] + apos, "out"))
437 apos += 3;
438 ++ apos;
439 foreach (cv, g_ComponentInfos)
440 if (compare (argv[a] + apos, g_Components[cv * 3]))
441 g_ComponentInfos[cv].m_bDefaultOn = (apos == 7);
442 } else {
443 foreach (cv, g_ConfigV)
444 if (compare (argv[a] + apos, g_ConfigV[cv]))
445 break;
446 if (cv == vv_last)
447 continue;
448 apos += StrLen (g_ConfigV[cv]) + 1;
449 cvl = StrLen (argv[a]) - apos + 1;
450 if (cvl > 1) {
451 buf_copy_n (argv[a] + apos, &g_ConfigVV[cv], cvl);
452 if (cv == vv_customlib)
453 buf_copy_n (argv[a] + apos, &g_CustomLibDirs [g_nCustomLibDirs++], cvl);
454 else if (cv == vv_custominclude)
455 buf_copy_n (argv[a] + apos, &g_CustomIncDirs [g_nCustomIncDirs++], cvl);
457 if (cv == vv_prefix && compare (S(g_ConfigVV[cv]), "/home")) {
458 copy (S(g_ConfigVV[cv]), &g_CustomLibDirs [g_nCustomLibDirs]);
459 append ("/lib", &g_CustomLibDirs [g_nCustomLibDirs++]);
460 copy (S(g_ConfigVV[cv]), &g_CustomIncDirs [g_nCustomIncDirs]);
461 append ("/include", &g_CustomIncDirs [g_nCustomIncDirs++]);
467 static void DefaultConfigVarValue (EVV v, EVV root, cpchar_t suffix)
469 if (!*S(g_ConfigVV[v])) {
470 copy (S(g_ConfigVV [root]), &g_ConfigVV [v]);
471 append (suffix, &g_ConfigVV [v]);
475 static void DetermineHost (void)
477 typedef struct {
478 char sysname[8];
479 char type;
480 } SHostType;
481 static const SHostType g_HostTypes[] = {
482 { "linux", sys_Linux },
483 { "sun", sys_Sun },
484 { "solaris", sys_Sun },
485 { "openbsd", sys_Bsd },
486 { "netbsd", sys_Bsd },
487 { "freebsd", sys_Bsd },
488 { "osx", sys_Mac },
489 { "darwin", sys_Mac },
490 { "alpha", sys_Alpha }
492 uint i;
493 fill_n ((pchar_t) &g_Uname, sizeof(struct utsname), 0);
494 uname (&g_Uname);
495 Lowercase (g_Uname.machine);
496 Lowercase (g_Uname.sysname);
497 copy (g_Uname.machine, &g_ConfigVV [vv_host]);
498 append ("-", &g_ConfigVV [vv_host]);
499 #ifdef __GNUC__
500 append ("gnu", &g_ConfigVV [vv_host]);
501 #else
502 append ("unknown", &g_ConfigVV [vv_host]);
503 #endif
504 append2 ("-", g_Uname.sysname, &g_ConfigVV [vv_host]);
505 foreach (i, g_HostTypes)
506 if (compare (g_Uname.sysname, g_HostTypes[i].sysname))
507 g_SysType = g_HostTypes[i].type;
508 if (compare (g_Uname.machine, "alpha"))
509 g_SysType = sys_Alpha;
512 static void FillInDefaultConfigVarValues (void)
514 typedef struct _SDefaultPathMap {
515 unsigned char var;
516 unsigned char base;
517 char path[10];
518 } SDefaultPathMap;
519 static const SDefaultPathMap c_Defaults[] = {
520 { vv_bindir, vv_exec_prefix, "/bin" },
521 { vv_sbindir, vv_exec_prefix, "/sbin" },
522 { vv_libexecdir, vv_prefix, "/libexec" },
523 { vv_datadir, vv_prefix, "/share" },
524 { vv_sysconfdir, vv_prefix, "/etc" },
525 { vv_sharedstatedir, vv_prefix, "/com" },
526 { vv_localstatedir, vv_prefix, "/var" },
527 { vv_libdir, vv_exec_prefix, "/lib" },
528 { vv_gcclibdir, vv_exec_prefix, "/lib" },
529 { vv_includedir, vv_prefix, "/include" },
530 { vv_gccincludedir, vv_prefix, "/include" },
531 { vv_infodir, vv_prefix, "/info" },
532 { vv_mandir, vv_prefix, "/man" }
534 uint i;
536 if (!*S(g_ConfigVV [vv_prefix]))
537 copy ("/usr/local", &g_ConfigVV [vv_prefix]);
538 else if (S(g_ConfigVV[vv_prefix])[0] == '/' && !S(g_ConfigVV[vv_prefix])[1])
539 g_ConfigVV [vv_prefix].data[0] = 0;
540 if (!*S(g_ConfigVV [vv_exec_prefix]))
541 DefaultConfigVarValue (vv_exec_prefix, vv_prefix, "");
542 else if (S(g_ConfigVV[vv_exec_prefix])[0] == '/' && !S(g_ConfigVV[vv_exec_prefix])[1])
543 g_ConfigVV [vv_exec_prefix].data[0] = 0;
544 if (!*S(g_ConfigVV [vv_oldincludedir]))
545 copy ("/usr/include", &g_ConfigVV [vv_oldincludedir]);
547 foreach (i, c_Defaults)
548 DefaultConfigVarValue (c_Defaults[i].var, c_Defaults[i].base, c_Defaults[i].path);
550 if (!*S(g_ConfigVV [vv_prefix]))
551 copy ("/usr", &g_ConfigVV [vv_prefix]);
552 if (!*S(g_ConfigVV [vv_exec_prefix]))
553 copy ("/usr", &g_ConfigVV [vv_exec_prefix]);
555 if (!*S(g_ConfigVV [vv_host]))
556 DetermineHost();
557 if (!*S(g_ConfigVV [vv_build]))
558 copy (S(g_ConfigVV [vv_host]), &g_ConfigVV [vv_build]);
561 static cpchar_t CopyPathEntry (cpchar_t pi, pbuf_t dest)
563 uint pil = 0;
564 while (pi[pil] && pi[pil] != ':') ++ pil;
565 buf_copy_n (pi, dest, pil);
566 return (*(pi += pil) ? ++pi : NULL);
569 static int IsBadInstallDir (cpchar_t match)
571 static const char c_BadDirs[][10] = { "/etc", "/c", "/C", "/usr/etc", "/sbin", "/usr/sbin", "/usr/ucb" };
572 uint i;
573 foreach (i, c_BadDirs)
574 if (compare (match, c_BadDirs[i]))
575 return (1);
576 return (0);
579 static void FindPrograms (void)
581 uint i, count;
582 cpchar_t path, pi;
583 SBuf match = NULL_BUF;
585 path = getenv ("PATH");
586 if (!path)
587 path = "";
589 foreach (i, g_ProgLocs) {
590 copy (".", &match);
591 count = 0;
592 for (pi = path; pi; pi = CopyPathEntry (pi, &match)) {
593 /* Ignore "bad" versions of install, like autoconf does. */
594 if (compare (g_ProgVars[i * 4 + 1], "install") && IsBadInstallDir (S(match)))
595 continue;
596 append2 ("/", g_ProgVars[i * 4 + 1], &match);
597 if (access (S(match), X_OK) == 0) {
598 ++ count;
599 break;
602 if (count && compare (g_ProgVars[i * 4 + 1], "install"))
603 copy (S(match), &g_ProgLocs[i]);
604 else
605 copy (g_ProgVars[i * 4 + 2 + !count], &g_ProgLocs[i]);
607 buf_free (&match);
610 static void SubstitutePaths (void)
612 SBuf match = NULL_BUF;
613 int cv;
614 foreach (cv, g_ConfigV) {
615 MakeSubstString (g_ConfigV [cv], &match);
616 Substitute (S(match), S(g_ConfigVV [cv]));
618 buf_free (&match);
621 static void SubstituteCFlags (void)
623 SBuf buf = NULL_BUF;
624 int j;
626 for (j = 0; j < g_nCustomIncDirs; ++ j)
627 append2 (" -I", S(g_CustomIncDirs[j]), &buf);
628 Substitute ("@CUSTOMINCDIR@", S(buf));
630 buf_clear (&buf);
631 for (j = 0; j < g_nCustomLibDirs; ++ j)
632 append2 (" -L", S(g_CustomLibDirs[j]), &buf);
633 Substitute ("@CUSTOMLIBDIR@", S(buf));
635 buf_clear (&buf);
636 #if __GNUC__ >= 3
637 if (g_CpuCapBits & (1 << 23))
638 append (" -mmmx", &buf);
639 if (g_SysType == sys_Linux)
640 if (g_CpuCapBits & ((1 << 22) | (1 << 25)))
641 append (" -msse -mfpmath=sse", &buf);
642 if (g_CpuCapBits & (1 << 26))
643 append (" -msse2", &buf);
644 if (g_CpuCapBits & ((1 << 30) | (1 << 31)))
645 append (" -m3dnow", &buf);
646 #endif
647 Substitute ("@PROCESSOR_OPTS@", S(buf));
649 #if __GNUC__ >= 3
650 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
651 copy (" --param max-inline-insns-single=1024", &buf);
652 append (" \\\n\t\t--param large-function-growth=65535", &buf);
653 append (" \\\n\t\t--param inline-unit-growth=1024", &buf);
654 #else
655 copy ("-finline-limit=65535", &buf);
656 #endif
657 #if __GNUC__ >= 4
658 append (" \\\n\t\t-fvisibility-inlines-hidden", &buf);
659 #endif
660 #endif
661 Substitute ("@INLINE_OPTS@", S(buf));
663 #if __i386__
664 Substitute ("-fPIC", "");
665 #endif
666 buf_free (&buf);
669 static void SubstituteEnvironment (int bForce)
671 SBuf match = NULL_BUF;
672 uint i;
673 cpchar_t envval;
675 foreach (i, g_EnvVars) {
676 envval = getenv (g_EnvVars[i]);
677 if (!envval) {
678 if (!bForce)
679 continue;
680 envval = "";
682 MakeSubstString (g_EnvVars[i], &match);
683 Substitute (S(match), envval);
685 buf_free (&match);
688 static void SubstitutePrograms (void)
690 uint i;
691 SBuf match = NULL_BUF;
692 foreach (i, g_ProgLocs) {
693 MakeSubstString (g_ProgVars [i * 4], &match);
694 Substitute (S(match), S(g_ProgLocs [i]));
696 buf_free (&match);
699 #if defined(__GNUC__) && (__i386__ || __x86_64) && !defined(__PIC__)
700 static uint cpuid_supported (void)
702 unsigned long forig, fnew;
703 /* Pop flags, toggle ID bit, push, pop. cpuid supported if changed. */
704 asm ("pushf\n\tpop\t%0\n\t"
705 "mov\t%0, %1\n\txor\t$0x200000, %0\n\t"
706 "push\t%0\n\tpopf\n\tpushf\n\tpop\t%0"
707 : "=r"(fnew), "=r"(forig));
708 return (fnew != forig);
711 static uint cpuid (void)
713 #define i_cpuid(a,r,c,d) asm("cpuid":"=a"(r),"=c"(c),"=d"(d):"0"(a):"ebx")
714 const uint amdBits = 0xC9480000, extFeatures = 0x80000000, amdExtensions = 0x80000001;
715 uint r, c, d, caps;
716 if (!cpuid_supported()) return (0);
717 i_cpuid (0, r, c, d);
718 if (!r) return (0);
719 i_cpuid (1, r, c, d); /* Ask for feature list */
720 caps = (d & ~amdBits);
721 i_cpuid (extFeatures, r, c, d);
722 if (r != extFeatures) {
723 i_cpuid (amdExtensions, r, c, d);
724 caps |= d & amdBits;
726 return (caps);
728 #else
729 static uint cpuid (void) { return (0); }
730 #endif
732 static void SubstituteCpuCaps (void)
734 typedef struct {
735 char m_Bit;
736 char m_Disabled [26];
737 char m_Enabled [29];
738 } SCpuCaps;
739 static const SCpuCaps s_CpuCaps [] = {
740 { 0, "#undef CPU_HAS_FPU", "#define CPU_HAS_FPU 1" },
741 { 2, "#undef CPU_HAS_EXT_DEBUG", "#define CPU_HAS_EXT_DEBUG 1" },
742 { 4, "#undef CPU_HAS_TIMESTAMPC", "#define CPU_HAS_TIMESTAMPC 1" },
743 { 5, "#undef CPU_HAS_MSR", "#define CPU_HAS_MSR 1" },
744 { 8, "#undef CPU_HAS_CMPXCHG8", "#define CPU_HAS_CMPXCHG8 1" },
745 { 9, "#undef CPU_HAS_APIC", "#define CPU_HAS_APIC 1" },
746 { 11, "#undef CPU_HAS_SYSCALL", "#define CPU_HAS_SYSCALL 1" },
747 { 12, "#undef CPU_HAS_MTRR", "#define CPU_HAS_MTRR 1" },
748 { 15, "#undef CPU_HAS_CMOV", "#define CPU_HAS_CMOV 1" },
749 { 16, "#undef CPU_HAS_FCMOV", "#define CPU_HAS_FCMOV 1" },
750 { 22, "#undef CPU_HAS_SSE ", "#define CPU_HAS_SSE 1" },
751 { 23, "#undef CPU_HAS_MMX", "#define CPU_HAS_MMX 1" },
752 { 24, "#undef CPU_HAS_FXSAVE", "#define CPU_HAS_FXSAVE 1" },
753 { 25, "#undef CPU_HAS_SSE ", "#define CPU_HAS_SSE 1" },
754 { 26, "#undef CPU_HAS_SSE2", "#define CPU_HAS_SSE2 1" },
755 { 30, "#undef CPU_HAS_EXT_3DNOW", "#define CPU_HAS_EXT_3DNOW 1" },
756 { 31, "#undef CPU_HAS_3DNOW", "#define CPU_HAS_3DNOW 1" }
758 uint i;
759 g_CpuCapBits = cpuid();
760 foreach (i, s_CpuCaps)
761 if (g_CpuCapBits & (1 << s_CpuCaps[i].m_Bit))
762 Substitute (s_CpuCaps[i].m_Disabled, s_CpuCaps[i].m_Enabled);
765 static void SubstituteHostOptions (void)
767 static const short int boCheck = 0x0001;
768 static const char boNames[2][16] = { "BIG_ENDIAN", "LITTLE_ENDIAN" };
769 char buf [128];
770 #if __GNUC__ >= 3
771 if (g_SysType == sys_Sun)
772 #endif
773 Substitute ("-Wredundant-decls", "-Wno-redundant-decls");
775 if (g_SysType == sys_Bsd) {
776 Substitute (" @libgcc_eh@", "");
777 Substitute ("#define WITHOUT_LIBSTDCPP 1", "#undef WITHOUT_LIBSTDCPP");
778 Substitute ("NOLIBSTDCPP\t= -nodefaultlibs ", "#NOLIBSTDCPP\t= -nodefaultlibs");
779 Substitute ("-Wredundant-decls", "-Wno-redundant-decls");
780 Substitute ("-Winline", "-Wno-inline");
783 if ((g_SysType == sys_Linux) | (g_SysType == sys_Bsd))
784 Substitute ("@SHBLDFL@", "-shared -Wl,-soname=${LIBSOLNK}");
785 else if (g_SysType == sys_Mac)
786 Substitute ("@SHBLDFL@", "-Wl,-single_module -compatibility_version 1 -current_version 1 -install_name ${LIBSOLNK} -Wl,-Y,1455 -dynamiclib -mmacosx-version-min=10.4");
787 else if (g_SysType == sys_Sun)
788 Substitute ("@SHBLDFL@", "-G");
789 else {
790 Substitute ("BUILD_SHARED\t= 1 ", "#BUILD_SHARED\t= 1");
791 Substitute ("#BUILD_STATIC\t= 1", "BUILD_STATIC\t= 1 ");
794 if (g_SysType == sys_Mac) {
795 Substitute (" @libgcc_eh@", "");
796 Substitute ("@libgcc@", "@libsupc++@ @libgcc@");
797 Substitute ("@SYSWARNS@", "-Wno-long-double");
798 Substitute ("lib${LIBNAME}.so", "lib${LIBNAME}.dylib");
799 Substitute ("${LIBSO}.${MAJOR}.${MINOR}.${BUILD}", "lib${LIBNAME}.${MAJOR}.${MINOR}.${BUILD}.dylib");
800 Substitute ("${LIBSO}.${MAJOR}.${MINOR}", "lib${LIBNAME}.${MAJOR}.${MINOR}.dylib");
801 Substitute ("${LIBSO}.${MAJOR}", "lib${LIBNAME}.${MAJOR}.dylib");
802 } else
803 Substitute ("@SYSWARNS@", "");
805 if (g_SysType != sys_Sun)
806 Substitute ("#undef HAVE_THREE_CHAR_TYPES", "#define HAVE_THREE_CHAR_TYPES 1");
808 Substitute ("#undef RETSIGTYPE", "#define RETSIGTYPE void");
809 Substitute ("#undef const", "/* #define const */");
810 Substitute ("#undef inline", "/* #define inline __inline */");
811 Substitute ("#undef off_t", "/* typedef long off_t; */");
812 Substitute ("#undef size_t", "/* typedef long size_t; */");
814 snprintf (buf, VectorSize(buf), "#define SIZE_OF_CHAR %zd", sizeof(char));
815 Substitute ("#undef SIZE_OF_CHAR", buf);
816 snprintf (buf, VectorSize(buf), "#define SIZE_OF_SHORT %zd", sizeof(short));
817 Substitute ("#undef SIZE_OF_SHORT", buf);
818 snprintf (buf, VectorSize(buf), "#define SIZE_OF_INT %zd", sizeof(int));
819 Substitute ("#undef SIZE_OF_INT", buf);
820 snprintf (buf, VectorSize(buf), "#define SIZE_OF_LONG %zd", sizeof(long));
821 Substitute ("#undef SIZE_OF_LONG ", buf);
822 snprintf (buf, VectorSize(buf), "#define SIZE_OF_POINTER %zd", sizeof(void*));
823 Substitute ("#undef SIZE_OF_POINTER ", buf);
824 snprintf (buf, VectorSize(buf), "#define SIZE_OF_SIZE_T %zd", sizeof(size_t));
825 Substitute ("#undef SIZE_OF_SIZE_T ", buf);
826 if (g_SysType == sys_Alpha || g_SysType == sys_Mac)
827 Substitute ("#undef SIZE_OF_BOOL ", "#define SIZE_OF_BOOL SIZE_OF_LONG");
828 else
829 Substitute ("#undef SIZE_OF_BOOL ", "#define SIZE_OF_BOOL SIZE_OF_CHAR");
830 if ((sizeof(size_t) == sizeof(unsigned long) &&
831 sizeof(size_t) != sizeof(uint)) || g_SysType == sys_Mac)
832 Substitute ("#undef SIZE_T_IS_LONG", "#define SIZE_T_IS_LONG 1");
833 #if defined(__GNUC__) || (__WORDSIZE == 64) || defined(__ia64__)
834 if (g_SysType != sys_Bsd)
835 Substitute ("#undef HAVE_INT64_T", "#define HAVE_INT64_T 1");
836 #endif
837 #if defined(__GNUC__) || defined(__GLIBC_HAVE_LONG_LONG)
838 Substitute ("#undef HAVE_LONG_LONG", "#define HAVE_LONG_LONG 1");
839 snprintf (buf, VectorSize(buf), "#define SIZE_OF_LONG_LONG %zd", sizeof(long long));
840 Substitute ("#undef SIZE_OF_LONG_LONG", buf);
841 #endif
842 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
843 Substitute ("#undef HAVE_VECTOR_EXTENSIONS", "#define HAVE_VECTOR_EXTENSIONS 1");
844 #else
845 Substitute ("-Wshadow ", "");
846 #endif
848 Substitute ("#undef LSTAT_FOLLOWS_SLASHED_SYMLINK", "#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1");
849 Substitute ("#undef HAVE_STAT_EMPTY_STRING_BUG", "/* #undef HAVE_STAT_EMPTY_STRING_BUG */");
851 if (g_SysType == sys_Linux)
852 Substitute ("#undef HAVE_RINTF", "#define HAVE_RINTF 1");
854 Substitute ("@BYTE_ORDER@", boNames [(uint)(*((const char*)&boCheck))]);
857 static void SubstituteCustomVars (void)
859 uint i;
860 SBuf match = NULL_BUF;
861 foreachN (i, g_CustomVars, 2) {
862 MakeSubstString (g_CustomVars [i * 2], &match);
863 Substitute (S(match), g_CustomVars [i * 2 + 1]);
865 buf_free (&match);
868 static void SubstituteHeaders (void)
870 uint i;
871 cpchar_t pi;
872 SBuf defaultPath = NULL_BUF, match = NULL_BUF;
874 copy (S(g_ConfigVV [vv_includedir]), &defaultPath);
875 append2 (":", S(g_ConfigVV [vv_oldincludedir]), &defaultPath);
876 append2 (":", S(g_ConfigVV [vv_gccincludedir]), &defaultPath);
877 for (i = 0; i != (uint) g_nCustomIncDirs; ++ i)
878 append2 (":", S(g_CustomIncDirs [i]), &defaultPath);
879 foreachN (i, g_Headers, 3) {
880 for (pi = S(defaultPath); pi; pi = CopyPathEntry (pi, &match)) {
881 append2 ("/", g_Headers [i * 3], &match);
882 if (access (S(match), R_OK) == 0)
883 Substitute (g_Headers [i * 3 + 1], g_Headers [i * 3 + 2]);
886 buf_free (&match);
887 buf_free (&defaultPath);
890 static void SubstituteLibs (void)
892 static const char g_LibSuffixes[][8] = { ".a", ".so", ".la", ".dylib" };
893 uint i, k, ok;
894 cpchar_t pi;
895 SBuf defaultPath = NULL_BUF, match = NULL_BUF;
897 copy ("/lib:/usr/lib:/usr/local/lib", &defaultPath);
898 pi = getenv ("LD_LIBRARY_PATH");
899 if (pi)
900 append2 (":", pi, &defaultPath);
901 append2 (":", S(g_ConfigVV [vv_libdir]), &defaultPath);
902 append2 (":", S(g_ConfigVV [vv_gcclibdir]), &defaultPath);
903 for (i = 0; i != (uint) g_nCustomLibDirs; ++ i)
904 append2 (":", S(g_CustomLibDirs [i]), &defaultPath);
906 foreachN (i, g_Libs, 3) {
907 ok = 0;
908 for (pi = S(defaultPath); pi; pi = CopyPathEntry (pi, &match)) {
909 foreach (k, g_LibSuffixes) {
910 CopyPathEntry (pi, &match);
911 append2 ("/lib", g_Libs [i * 3], &match);
912 append (g_LibSuffixes [k], &match);
913 if (access (S(match), R_OK) == 0)
914 ok = 1;
917 copy ("@lib", &match);
918 append2 (g_Libs[i * 3], "@", &match);
919 Substitute (S(match), g_Libs [i * 3 + 1 + ok]);
921 buf_free (&match);
922 buf_free (&defaultPath);
925 static void SubstituteFunctions (void)
927 uint i;
928 foreachN (i, g_Functions, 3)
929 Substitute (g_Functions [i * 3 + 1], g_Functions [i * 3 + 2]);
930 if ((g_SysType == sys_Mac) | (g_SysType == sys_Bsd))
931 Substitute ("#define HAVE_STRSIGNAL 1", "#undef HAVE_STRSIGNAL");
932 if (g_SysType == sys_Bsd)
933 Substitute ("#define HAVE_VA_COPY 1", "#undef HAVE_VA_COPY");
936 static void SubstituteComponents (void)
938 uint i, isOn;
939 foreachN (i, g_Components, 3) {
940 isOn = g_ComponentInfos[i].m_bDefaultOn;
941 Substitute (g_Components [i * 3 + 1 + !isOn], g_Components [i * 3 + 1 + isOn]);
945 /*--------------------------------------------------------------------*/
947 int main (int argc, const char* const* argv)
949 InitGlobals();
950 GetConfigVarValues (--argc, ++argv);
951 FillInDefaultConfigVarValues();
953 FindPrograms();
954 SubstituteComponents();
955 SubstituteHostOptions();
956 SubstituteCpuCaps();
957 SubstituteCFlags();
958 SubstitutePaths();
959 SubstituteEnvironment (0);
960 SubstitutePrograms();
961 SubstituteHeaders();
962 SubstituteLibs();
963 SubstituteFunctions();
964 SubstituteCustomVars();
965 SubstituteEnvironment (1);
967 ApplySubstitutions();
968 FreeGlobals();
969 return (0);