Build system now standalone
[ttodo.git] / bsconf.c
blobbc13ca9d1e2b5301684895ec912dca827e73e64b
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 /*- Types and macros -------------------------------------------------*/
31 #define VectorSize(v) (sizeof(v) / sizeof(*v))
32 #define foreachN(i,v,n) for (i = 0; i != VectorSize(v) / n; ++ i)
33 #define foreach(i,v) foreachN(i,v,1)
35 /*#define const*/
36 /*typedef unsigned int uint;*/
37 typedef char* pchar_t;
38 typedef const char* cpchar_t;
39 typedef struct {
40 pchar_t data;
41 uint allocated;
42 uint used;
43 uint last;
44 uint page;
45 } SBuf, *pbuf_t;
46 #define NULL_BUF { NULL, 0, 0, 0, 0 }
48 typedef enum {
49 vv_prefix,
50 vv_exec_prefix,
51 vv_bindir,
52 vv_sbindir,
53 vv_libexecdir,
54 vv_datadir,
55 vv_sysconfdir,
56 vv_sharedstatedir,
57 vv_localstatedir,
58 vv_libdir,
59 vv_gcclibdir,
60 vv_includedir,
61 vv_oldincludedir,
62 vv_gccincludedir,
63 vv_custominclude,
64 vv_customlib,
65 vv_infodir,
66 vv_mandir,
67 vv_build,
68 vv_host,
69 vv_last
70 } EVV;
72 typedef struct {
73 int m_bDefaultOn;
74 cpchar_t m_Description;
75 } SComponentInfo;
77 typedef struct {
78 uint m_Bit;
79 cpchar_t m_Description;
80 cpchar_t m_Disabled;
81 cpchar_t m_Enabled;
82 } SCpuCaps;
84 typedef enum {
85 sys_Unknown,
86 sys_Linux,
87 sys_Mac,
88 sys_Bsd,
89 sys_Sun,
90 sys_Alpha
91 } ESysType;
93 typedef struct {
94 cpchar_t sysname;
95 ESysType type;
96 } SHostType;
98 /*- Global variables -------------------------------------------------*/
100 #include "bsconf.h"
101 #if !defined(BSCONF_VERSION) || BSCONF_VERSION < 0x03
102 #error Your bsconf.h file is too old; please update its format.
103 #endif
105 static cpchar_t g_ConfigV [vv_last] = {
106 "prefix",
107 "exec_prefix",
108 "bindir",
109 "sbindir",
110 "libexecdir",
111 "datadir",
112 "sysconfdir",
113 "sharedstatedir",
114 "localstatedir",
115 "libdir",
116 "gcclibdir",
117 "includedir",
118 "oldincludedir",
119 "gccincludedir",
120 "custominclude",
121 "customlib",
122 "infodir",
123 "mandir",
124 "build",
125 "host"
128 static SBuf g_Subs = NULL_BUF;
129 static SBuf g_ConfigVV [vv_last], g_ProgLocs [VectorSize (g_ProgVars) / 4];
130 static SBuf g_CustomLibDirs [16], g_CustomIncDirs [16];
131 static int g_nCustomLibDirs = 0, g_nCustomIncDirs = 0;
132 static struct utsname g_Uname;
133 static uint g_CpuCapBits = 0;
134 static ESysType g_SysType = sys_Unknown;
136 static const SCpuCaps g_CpuCaps [] = {
137 { 0, "FPU", "#undef CPU_HAS_FPU", "#define CPU_HAS_FPU 1" },
138 { 2, "DEBUG", "#undef CPU_HAS_EXT_DEBUG", "#define CPU_HAS_EXT_DEBUG 1" },
139 { 4, "TimeStamp", "#undef CPU_HAS_TIMESTAMPC", "#define CPU_HAS_TIMESTAMPC 1" },
140 { 5, "MSR", "#undef CPU_HAS_MSR", "#define CPU_HAS_MSR 1" },
141 { 8, "CMPXCHG8", "#undef CPU_HAS_CMPXCHG8", "#define CPU_HAS_CMPXCHG8 1" },
142 { 9, "APIC", "#undef CPU_HAS_APIC", "#define CPU_HAS_APIC 1" },
143 { 11, "SYSCALL", "#undef CPU_HAS_SYSCALL", "#define CPU_HAS_SYSCALL 1" },
144 { 12, "MTRR", "#undef CPU_HAS_MTRR", "#define CPU_HAS_MTRR 1" },
145 { 15, "CMOV", "#undef CPU_HAS_CMOV", "#define CPU_HAS_CMOV 1" },
146 { 16, "FCMOV", "#undef CPU_HAS_FCMOV", "#define CPU_HAS_FCMOV 1" },
147 { 22, "SSE", "#undef CPU_HAS_SSE ", "#define CPU_HAS_SSE 1" },
148 { 23, "MMX", "#undef CPU_HAS_MMX", "#define CPU_HAS_MMX 1" },
149 { 24, "FXSAVE", "#undef CPU_HAS_FXSAVE", "#define CPU_HAS_FXSAVE 1" },
150 { 25, "SSE", "#undef CPU_HAS_SSE ", "#define CPU_HAS_SSE 1" },
151 { 26, "SSE2", "#undef CPU_HAS_SSE2", "#define CPU_HAS_SSE2 1" },
152 { 30, "3dNow!+", "#undef CPU_HAS_EXT_3DNOW", "#define CPU_HAS_EXT_3DNOW 1" },
153 { 31, "3dNow!", "#undef CPU_HAS_3DNOW", "#define CPU_HAS_3DNOW 1" }
156 static const SHostType g_HostTypes[] = {
157 { "linux", sys_Linux },
158 { "sun", sys_Sun },
159 { "solaris", sys_Sun },
160 { "openbsd", sys_Bsd },
161 { "netbsd", sys_Bsd },
162 { "freebsd", sys_Bsd },
163 { "osx", sys_Mac },
164 { "darwin", sys_Mac },
165 { "alpha", sys_Alpha }
168 /*- Libc-like functions that might not exist -------------------------*/
170 static int StrLen (cpchar_t str)
172 int l;
173 for (l = 0; *str; ++ l, ++ str);
174 return (l);
177 static pchar_t copy_n (cpchar_t src, pchar_t dest, int n)
179 while (n--)
180 *dest++ = *src++;
181 return (dest);
184 static void fill_n (pchar_t str, int n, char v)
186 while (n--)
187 *str++ = v;
190 static void copy_backward (cpchar_t src, pchar_t dest, uint n)
192 dest += n; src += n;
193 while (n--)
194 *--dest = *--src;
197 static void Lowercase (pchar_t str)
199 for (; *str; ++ str)
200 if (*str >= 'A' && *str <= 'Z')
201 *str += 'a' - 'A';
204 static int compare (cpchar_t str1, cpchar_t str2)
206 while (*str1 && *str2 && *str1 == *str2)
207 ++ str1, ++ str2;
208 return (!*str2);
211 static void FatalError (cpchar_t errortext)
213 perror (errortext);
214 exit(-1);
217 /*- Malloc buffer object ---------------------------------------------*/
219 static pchar_t buf_addspace (pbuf_t p, uint n)
221 if ((p->used += n) > p->allocated) {
222 p->allocated = p->used;
223 if (!(p->data = (pchar_t) realloc (p->data, p->allocated)))
224 FatalError ("out of memory");
226 return (p->data + p->used - n);
229 static void buf_clear (pbuf_t p) { p->used = p->last; }
230 static void append (cpchar_t s, pbuf_t p) { copy_n (s, buf_addspace (p, StrLen(s)), StrLen(s)); }
231 static void copy (cpchar_t s, pbuf_t p) { buf_clear (p); append (s, p); }
233 static void buf_copy_n (cpchar_t s, pbuf_t p, uint n)
235 buf_clear (p);
236 copy_n (s, buf_addspace (p, n), n);
239 static void append2 (cpchar_t s1, cpchar_t s2, pbuf_t p)
241 uint l1 = StrLen(s1), l2 = StrLen(s2);
242 copy_n (s2, copy_n (s1, buf_addspace (p, l1+l2), l1), l2);
245 static void buf_cap (pbuf_t p)
247 if (p->used >= p->allocated || p->data [p->used]) {
248 *buf_addspace(p,1) = 0;
249 --p->used;
253 static pchar_t buf_resize_fragment (pbuf_t p, uint fo, uint os, uint ns)
255 int d = ns - os;
256 if (d <= 0) {
257 copy_n (p->data + fo - d, p->data + fo, p->used - (fo - d));
258 p->used += d;
259 } else {
260 buf_addspace (p, d);
261 copy_backward (p->data + fo, p->data + fo + d, p->used - (fo + d));
263 buf_cap (p);
264 return (p->data + fo);
267 static void pushstring (pbuf_t p) { buf_cap (p); p->last = p->used + 1; }
268 static pchar_t buf_str (pbuf_t p) { buf_cap (p); return (p->data + p->last); }
269 #define S(buf) buf_str(&buf)
271 static void buf_free (pbuf_t p)
273 if (p->data)
274 free (p->data);
275 p->data = NULL;
276 p->allocated = p->used = p->last = 0;
279 /*- File I/O with buffer objects -------------------------------------*/
281 static void ReadFile (cpchar_t filename, pbuf_t buf)
283 struct stat st;
284 FILE* fp = fopen (filename, "r");
285 if (!fp)
286 FatalError ("open");
287 if (fstat (fileno(fp), &st))
288 FatalError ("stat");
289 buf_clear (buf);
290 buf->used = fread (buf_addspace (buf, st.st_size + 1), 1, st.st_size, fp);
291 if (((int) buf->used) < 0)
292 FatalError ("read");
293 buf_cap (buf);
294 fclose (fp);
297 static void WriteFile (cpchar_t filename, pbuf_t buf)
299 uint bw;
300 FILE* fp = fopen (filename, "w");
301 if (!fp)
302 FatalError ("open");
303 bw = fwrite (buf->data, 1, buf->used, fp);
304 if (bw != buf->used)
305 FatalError ("write");
306 if (fclose (fp))
307 FatalError ("close");
310 /*- Substitution engine ----------------------------------------------*/
312 static void MakeSubstString (cpchar_t str, pbuf_t pbuf)
314 copy ("@", pbuf);
315 append2 (str, "@", pbuf);
318 static void Substitute (cpchar_t matchStr, cpchar_t replaceStr)
320 copy (matchStr, &g_Subs);
321 pushstring (&g_Subs);
322 copy (replaceStr, &g_Subs);
323 pushstring (&g_Subs);
326 static void ExecuteSubstitutionList (pbuf_t buf)
328 uint ml, rl;
329 cpchar_t m = g_Subs.data, r;
330 pchar_t cp, fbfirst = S(*buf);
332 while (m < g_Subs.data + g_Subs.used) {
333 ml = StrLen (m);
334 r = m + ml + 1;
335 rl = StrLen (r);
336 for (cp = fbfirst; cp < fbfirst + buf->used; ++ cp) {
337 if (!compare (cp, m))
338 continue;
339 cp = buf_resize_fragment (buf, cp - fbfirst, ml, rl);
340 fbfirst = S(*buf);
341 cp = copy_n (r, cp, rl);
343 m = r + rl + 1;
347 static void ApplySubstitutions (void)
349 uint f;
350 SBuf srcFile = NULL_BUF, fileBuf = NULL_BUF;
351 foreach (f, g_Files) {
352 copy (g_Files[f], &srcFile);
353 append (".in", &srcFile);
354 ReadFile (S(srcFile), &fileBuf);
355 ExecuteSubstitutionList (&fileBuf);
356 WriteFile (g_Files[f], &fileBuf);
358 buf_free (&fileBuf);
359 buf_free (&srcFile);
362 /*- Housekeeping -----------------------------------------------------*/
364 static void InitGlobals (void)
366 uint i;
367 SBuf nullBuf = NULL_BUF;
368 g_Subs = nullBuf;
369 foreach (i, g_ConfigVV)
370 g_ConfigVV[i] = nullBuf;
371 foreach (i, g_CustomLibDirs)
372 g_CustomLibDirs[i] = nullBuf;
373 foreach (i, g_CustomIncDirs)
374 g_CustomIncDirs[i] = nullBuf;
375 foreach (i, g_ProgLocs)
376 g_ProgLocs[i] = nullBuf;
379 static void FreeGlobals (void)
381 uint i;
382 buf_free (&g_Subs);
383 foreach (i, g_ConfigVV)
384 buf_free (&g_ConfigVV[i]);
385 foreach (i, g_CustomLibDirs)
386 buf_free (&g_CustomLibDirs[i]);
387 foreach (i, g_CustomIncDirs)
388 buf_free (&g_CustomIncDirs[i]);
389 foreach (i, g_ProgLocs)
390 buf_free (&g_ProgLocs[i]);
393 static void PrintHelp (void)
395 uint i;
396 printf (
397 "This program configures " PACKAGE_STRING " to adapt to many kinds of systems.\n"
398 "\n"
399 "Usage: configure [OPTION] ...\n"
400 "\n"
401 "Configuration:\n"
402 " --help\t\tdisplay this help and exit\n"
403 " --version\t\tdisplay version information and exit\n"
404 "\n"
405 "Installation directories:\n"
406 " --prefix=PREFIX\tarchitecture-independent files [/usr/local]\n"
407 " --exec-prefix=EPREFIX\tarchitecture-dependent files [PREFIX]\n"
408 " --bindir=DIR\t\tuser executables [EPREFIX/bin]\n"
409 " --sbindir=DIR\t\tsystem admin executables [EPREFIX/sbin]\n"
410 " --libexecdir=DIR\tprogram executables [EPREFIX/libexec]\n"
411 " --datadir=DIR\t\tread-only architecture-independent data [PREFIX/share]\n"
412 " --sysconfdir=DIR\tread-only single-machine data [PREFIX/etc]\n"
413 " --sharedstatedir=DIR\tmodifiable architecture-independent data [PREFIX/com]\n"
414 " --localstatedir=DIR\tmodifiable single-machine data [PREFIX/var]\n"
415 " --libdir=DIR\t\tobject code libraries [EPREFIX/lib]\n"
416 " --includedir=DIR\tC header files [PREFIX/include]\n"
417 " --oldincludedir=DIR\tC header files for non-gcc [/usr/include]\n"
418 " --gccincludedir=DIR\tGCC internal header files [PREFIX/include]\n"
419 " --custominclude=DIR\tNonstandard header file location (cumulative)\n"
420 " --customlib=DIR\tNonstandard library file location (cumulative)\n"
421 " --infodir=DIR\t\tinfo documentation [PREFIX/info]\n"
422 " --mandir=DIR\t\tman documentation [PREFIX/man]\n"
423 "\n"
424 "System types:\n"
425 " --build=BUILD\t\tconfigure for building on BUILD [guessed]\n"
426 " --host=HOST\t\tcross-compile to build programs to run on HOST [BUILD]\n"
427 "\n");
428 if (VectorSize(g_Components)) {
429 printf ("Options:\n");
430 foreach (i, g_ComponentInfos) {
431 if (!g_ComponentInfos[i].m_Description[0])
432 continue;
433 if (g_ComponentInfos[i].m_bDefaultOn)
434 printf (" --without-%-12s%s\n", g_Components[i * 3], g_ComponentInfos[i].m_Description);
435 else
436 printf (" --with-%-15s%s\n", g_Components[i * 3], g_ComponentInfos[i].m_Description);
438 printf ("\n");
440 printf (
441 "Some influential environment variables:\n"
442 " CC\t\tC compiler\t\tCFLAGS\n"
443 " CPP\t\tC preprocessor\t\tCPPFLAGS\n"
444 " CXX\t\tC++ compiler\t\tCXXFLAGS\n"
445 " LD\t\tLinker\t\t\tLDFLAGS\n"
446 "\n"
447 "Report bugs to " PACKAGE_BUGREPORT ".\n");
448 exit (0);
451 static void PrintVersion (void)
453 printf (PACKAGE_NAME " configure " PACKAGE_VERSION "\n"
454 "\nUsing bsconf package version 0.3\n"
455 "Copyright (c) 2003-2005, Mike Sharov <msharov@users.sourceforge.net>\n"
456 "This configure script and the bsconf package are free software.\n"
457 "Unlimited permission to copy, distribute, and modify is granted.\n");
458 exit (0);
461 /*- Configuration routines -------------------------------------------*/
463 static void GetConfigVarValues (int argc, cpchar_t const* argv)
465 int a, apos, cvl;
466 uint cv;
467 /* --var=VALUE */
468 for (a = 0; a < argc; ++ a) {
469 if (!compare (argv[a], "--"))
470 continue;
471 apos = 2;
472 if (compare (argv[a] + apos, "help"))
473 PrintHelp();
474 else if (compare (argv[a] + apos, "version"))
475 PrintVersion();
476 else if (compare (argv[a] + apos, "with")) {
477 apos += 4;
478 if (compare (argv[a] + apos, "out"))
479 apos += 3;
480 ++ apos;
481 foreach (cv, g_ComponentInfos)
482 if (compare (argv[a] + apos, g_Components[cv * 3]))
483 g_ComponentInfos[cv].m_bDefaultOn = (apos == 7);
484 } else {
485 foreach (cv, g_ConfigV)
486 if (compare (argv[a] + apos, g_ConfigV[cv]))
487 break;
488 if (cv == vv_last)
489 continue;
490 apos += StrLen (g_ConfigV[cv]) + 1;
491 cvl = StrLen (argv[a]) - apos + 1;
492 if (cvl > 1) {
493 buf_copy_n (argv[a] + apos, &g_ConfigVV[cv], cvl);
494 if (cv == vv_customlib)
495 buf_copy_n (argv[a] + apos, &g_CustomLibDirs [g_nCustomLibDirs++], cvl);
496 else if (cv == vv_custominclude)
497 buf_copy_n (argv[a] + apos, &g_CustomIncDirs [g_nCustomIncDirs++], cvl);
499 if (cv == vv_prefix && compare (S(g_ConfigVV[cv]), "/home")) {
500 copy (S(g_ConfigVV[cv]), &g_CustomLibDirs [g_nCustomLibDirs]);
501 append ("/lib", &g_CustomLibDirs [g_nCustomLibDirs++]);
502 copy (S(g_ConfigVV[cv]), &g_CustomIncDirs [g_nCustomIncDirs]);
503 append ("/include", &g_CustomIncDirs [g_nCustomIncDirs++]);
509 static void DefaultConfigVarValue (EVV v, EVV root, cpchar_t suffix)
511 if (!*S(g_ConfigVV[v])) {
512 copy (S(g_ConfigVV [root]), &g_ConfigVV [v]);
513 append (suffix, &g_ConfigVV [v]);
517 static void DetermineHost (void)
519 uint i;
520 fill_n ((pchar_t) &g_Uname, sizeof(struct utsname), 0);
521 uname (&g_Uname);
522 Lowercase (g_Uname.machine);
523 Lowercase (g_Uname.sysname);
524 copy (g_Uname.machine, &g_ConfigVV [vv_host]);
525 append ("-", &g_ConfigVV [vv_host]);
526 #ifdef __GNUC__
527 append ("gnu", &g_ConfigVV [vv_host]);
528 #else
529 append ("unknown", &g_ConfigVV [vv_host]);
530 #endif
531 append2 ("-", g_Uname.sysname, &g_ConfigVV [vv_host]);
532 foreach (i, g_HostTypes)
533 if (compare (g_Uname.sysname, g_HostTypes[i].sysname))
534 g_SysType = g_HostTypes[i].type;
535 if (compare (g_Uname.machine, "alpha"))
536 g_SysType = sys_Alpha;
539 static void FillInDefaultConfigVarValues (void)
541 typedef struct _SDefaultPathMap {
542 EVV var;
543 EVV base;
544 cpchar_t path;
545 } SDefaultPathMap;
546 static const SDefaultPathMap c_Defaults[] = {
547 { vv_bindir, vv_exec_prefix, "/bin" },
548 { vv_sbindir, vv_exec_prefix, "/sbin" },
549 { vv_libexecdir, vv_prefix, "/libexec" },
550 { vv_datadir, vv_prefix, "/share" },
551 { vv_sysconfdir, vv_prefix, "/etc" },
552 { vv_sharedstatedir, vv_prefix, "/com" },
553 { vv_localstatedir, vv_prefix, "/var" },
554 { vv_libdir, vv_exec_prefix, "/lib" },
555 { vv_gcclibdir, vv_exec_prefix, "/lib" },
556 { vv_includedir, vv_prefix, "/include" },
557 { vv_gccincludedir, vv_prefix, "/include" },
558 { vv_infodir, vv_prefix, "/info" },
559 { vv_mandir, vv_prefix, "/man" }
561 uint i;
563 if (!*S(g_ConfigVV [vv_prefix]))
564 copy ("/usr/local", &g_ConfigVV [vv_prefix]);
565 else if (S(g_ConfigVV[vv_prefix])[0] == '/' && !S(g_ConfigVV[vv_prefix])[1])
566 g_ConfigVV [vv_prefix].data[0] = 0;
567 if (!*S(g_ConfigVV [vv_exec_prefix]))
568 DefaultConfigVarValue (vv_exec_prefix, vv_prefix, "");
569 else if (S(g_ConfigVV[vv_exec_prefix])[0] == '/' && !S(g_ConfigVV[vv_exec_prefix])[1])
570 g_ConfigVV [vv_exec_prefix].data[0] = 0;
571 if (!*S(g_ConfigVV [vv_oldincludedir]))
572 copy ("/usr/include", &g_ConfigVV [vv_oldincludedir]);
574 foreach (i, c_Defaults)
575 DefaultConfigVarValue (c_Defaults[i].var, c_Defaults[i].base, c_Defaults[i].path);
577 if (!*S(g_ConfigVV [vv_prefix]))
578 copy ("/usr", &g_ConfigVV [vv_prefix]);
579 if (!*S(g_ConfigVV [vv_exec_prefix]))
580 copy ("/usr", &g_ConfigVV [vv_exec_prefix]);
582 if (!*S(g_ConfigVV [vv_host]))
583 DetermineHost();
584 if (!*S(g_ConfigVV [vv_build]))
585 copy (S(g_ConfigVV [vv_host]), &g_ConfigVV [vv_build]);
588 static cpchar_t CopyPathEntry (cpchar_t pi, pbuf_t dest)
590 uint pil = 0;
591 while (pi[pil] && pi[pil] != ':') ++ pil;
592 buf_copy_n (pi, dest, pil);
593 return (*(pi += pil) ? ++pi : NULL);
596 static int IsBadInstallDir (cpchar_t match)
598 static const char* c_BadDirs[] = {
599 "/etc", "/usr/sbin", "/c", "/C", "/usr/etc",
600 "/sbin", "/usr/ucb", "/usr/afsws/bin"
602 uint i;
603 foreach (i, c_BadDirs)
604 if (compare (match, c_BadDirs[i]))
605 return (1);
606 return (0);
609 static void FindPrograms (void)
611 uint i, count;
612 cpchar_t path, pi;
613 SBuf match = NULL_BUF;
615 path = getenv ("PATH");
616 if (!path)
617 path = "";
619 foreach (i, g_ProgLocs) {
620 copy (".", &match);
621 count = 0;
622 for (pi = path; pi; pi = CopyPathEntry (pi, &match)) {
623 /* Ignore "bad" versions of install, like autoconf does. */
624 if (compare (g_ProgVars[i * 4 + 1], "install") && IsBadInstallDir (S(match)))
625 continue;
626 append2 ("/", g_ProgVars[i * 4 + 1], &match);
627 if (access (S(match), X_OK) == 0) {
628 ++ count;
629 break;
632 if (count && compare (g_ProgVars[i * 4 + 1], "install"))
633 copy (S(match), &g_ProgLocs[i]);
634 else
635 copy (g_ProgVars[i * 4 + 2 + !count], &g_ProgLocs[i]);
637 buf_free (&match);
640 static void SubstitutePaths (void)
642 SBuf match = NULL_BUF;
643 int cv;
644 foreach (cv, g_ConfigV) {
645 MakeSubstString (g_ConfigV [cv], &match);
646 Substitute (S(match), S(g_ConfigVV [cv]));
648 buf_free (&match);
651 static void SubstituteCFlags (void)
653 SBuf buf = NULL_BUF;
654 int j;
656 for (j = 0; j < g_nCustomIncDirs; ++ j)
657 append2 (" -I", S(g_CustomIncDirs[j]), &buf);
658 Substitute ("@CUSTOMINCDIR@", S(buf));
660 buf_clear (&buf);
661 for (j = 0; j < g_nCustomLibDirs; ++ j)
662 append2 (" -L", S(g_CustomLibDirs[j]), &buf);
663 Substitute ("@CUSTOMLIBDIR@", S(buf));
665 buf_clear (&buf);
666 #if __GNUC__ >= 3
667 if (g_CpuCapBits & (1 << 23))
668 append (" -mmmx", &buf);
669 if (g_SysType == sys_Linux)
670 if (g_CpuCapBits & ((1 << 22) | (1 << 25)))
671 append (" -msse -mfpmath=sse", &buf);
672 if (g_CpuCapBits & (1 << 26))
673 append (" -msse2", &buf);
674 if (g_CpuCapBits & ((1 << 30) | (1 << 31)))
675 append (" -m3dnow", &buf);
676 #endif
677 Substitute ("@PROCESSOR_OPTS@", S(buf));
679 #if __GNUC__ >= 3
680 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
681 copy (" --param max-inline-insns-single=1024", &buf);
682 append (" \\\n\t\t--param large-function-growth=65535", &buf);
683 append (" \\\n\t\t--param inline-unit-growth=1024", &buf);
684 #else
685 copy ("-finline-limit=65535", &buf);
686 #endif
687 #if __GNUC__ >= 4
688 append (" \\\n\t\t-fvisibility-inlines-hidden", &buf);
689 #endif
690 #endif
691 Substitute ("@INLINE_OPTS@", S(buf));
693 #if __i386__
694 Substitute ("-fPIC", "");
695 #endif
696 buf_free (&buf);
699 static void SubstituteEnvironment (int bForce)
701 SBuf match = NULL_BUF;
702 uint i;
703 cpchar_t envval;
705 foreach (i, g_EnvVars) {
706 envval = getenv (g_EnvVars[i]);
707 if (!envval) {
708 if (!bForce)
709 continue;
710 envval = "";
712 MakeSubstString (g_EnvVars[i], &match);
713 Substitute (S(match), envval);
715 buf_free (&match);
718 static void SubstitutePrograms (void)
720 uint i;
721 SBuf match = NULL_BUF;
722 foreach (i, g_ProgLocs) {
723 MakeSubstString (g_ProgVars [i * 4], &match);
724 Substitute (S(match), S(g_ProgLocs [i]));
726 buf_free (&match);
729 #if defined(__GNUC__) && (__i386__ || __x86_64)
730 static uint cpuid_supported (void)
732 unsigned long forig, fnew;
733 /* Pop flags, toggle ID bit, push, pop. cpuid supported if changed. */
734 asm ("pushf\n\tpop\t%0\n\t"
735 "mov\t%0, %1\n\txor\t$0x200000, %0\n\t"
736 "push\t%0\n\tpopf\n\tpushf\n\tpop\t%0"
737 : "=r"(fnew), "=r"(forig));
738 return (fnew != forig);
741 static uint cpuid (void)
743 #define i_cpuid(a,r,c,d) asm("cpuid":"=a"(r),"=c"(c),"=d"(d):"0"(a):"%ebx")
744 const uint amdBits = 0xC9480000, extFeatures = 0x80000000, amdExtensions = 0x80000001;
745 uint r, c, d, caps;
746 if (!cpuid_supported()) return (0);
747 i_cpuid (0, r, c, d);
748 if (!r) return (0);
749 i_cpuid (1, r, c, d); /* Ask for feature list */
750 caps = (d & ~amdBits);
751 i_cpuid (extFeatures, r, c, d);
752 if (r != extFeatures) {
753 i_cpuid (amdExtensions, r, c, d);
754 caps |= d & amdBits;
756 return (caps);
758 #else
759 static uint cpuid (void) { return (0); }
760 #endif
762 static void SubstituteCpuCaps (void)
764 uint i;
765 g_CpuCapBits = cpuid();
766 foreach (i, g_CpuCaps)
767 if (g_CpuCapBits & (1 << g_CpuCaps[i].m_Bit))
768 Substitute (g_CpuCaps[i].m_Disabled, g_CpuCaps[i].m_Enabled);
771 static void SubstituteHostOptions (void)
773 static const short int boCheck = 0x0001;
774 static const char boNames[2][16] = { "BIG_ENDIAN", "LITTLE_ENDIAN" };
775 char buf [128];
776 #if __GNUC__ >= 3
777 if (g_SysType == sys_Sun)
778 #endif
779 Substitute ("-Wredundant-decls", "-Wno-redundant-decls");
781 if (g_SysType == sys_Bsd) {
782 Substitute (" @libgcc_eh@", "");
783 Substitute ("#define WITHOUT_LIBSTDCPP 1", "#undef WITHOUT_LIBSTDCPP");
784 Substitute ("NOLIBSTDCPP\t= -nodefaultlibs ", "#NOLIBSTDCPP\t= -nodefaultlibs");
785 Substitute ("-Wredundant-decls", "-Wno-redundant-decls");
786 Substitute ("-Winline", "-Wno-inline");
789 if ((g_SysType == sys_Linux) | (g_SysType == sys_Bsd))
790 Substitute ("@SHBLDFL@", "-shared -Wl,-soname=${LIBSOLNK}");
791 else if (g_SysType == sys_Mac)
792 Substitute ("@SHBLDFL@", "-Wl,-single_module -compatibility_version 1 -current_version 1 -install_name ${LIBSOLNK} -Wl,-Y,1455 -dynamiclib -mmacosx-version-min=10.4");
793 else if (g_SysType == sys_Sun)
794 Substitute ("@SHBLDFL@", "-G");
795 else {
796 Substitute ("BUILD_SHARED\t= 1 ", "#BUILD_SHARED\t= 1");
797 Substitute ("#BUILD_STATIC\t= 1", "BUILD_STATIC\t= 1 ");
800 if (g_SysType == sys_Mac) {
801 Substitute (" @libgcc_eh@", "");
802 Substitute ("@libgcc@", "@libsupc++@ @libgcc@");
803 Substitute ("@SYSWARNS@", "-Wno-long-double");
804 Substitute ("lib${LIBNAME}.so", "lib${LIBNAME}.dylib");
805 Substitute ("${LIBSO}.${MAJOR}.${MINOR}.${BUILD}", "lib${LIBNAME}.${MAJOR}.${MINOR}.${BUILD}.dylib");
806 Substitute ("${LIBSO}.${MAJOR}.${MINOR}", "lib${LIBNAME}.${MAJOR}.${MINOR}.dylib");
807 Substitute ("${LIBSO}.${MAJOR}", "lib${LIBNAME}.${MAJOR}.dylib");
808 } else
809 Substitute ("@SYSWARNS@", "");
811 if (g_SysType != sys_Sun)
812 Substitute ("#undef HAVE_THREE_CHAR_TYPES", "#define HAVE_THREE_CHAR_TYPES 1");
814 Substitute ("#undef RETSIGTYPE", "#define RETSIGTYPE void");
815 Substitute ("#undef const", "/* #define const */");
816 Substitute ("#undef inline", "/* #define inline __inline */");
817 Substitute ("#undef off_t", "/* typedef long off_t; */");
818 Substitute ("#undef size_t", "/* typedef long size_t; */");
820 snprintf (buf, VectorSize(buf), "#define SIZE_OF_CHAR %d", sizeof(char));
821 Substitute ("#undef SIZE_OF_CHAR", buf);
822 snprintf (buf, VectorSize(buf), "#define SIZE_OF_SHORT %d", sizeof(short));
823 Substitute ("#undef SIZE_OF_SHORT", buf);
824 snprintf (buf, VectorSize(buf), "#define SIZE_OF_INT %d", sizeof(int));
825 Substitute ("#undef SIZE_OF_INT", buf);
826 snprintf (buf, VectorSize(buf), "#define SIZE_OF_LONG %d", sizeof(long));
827 Substitute ("#undef SIZE_OF_LONG ", buf);
828 snprintf (buf, VectorSize(buf), "#define SIZE_OF_POINTER %d", sizeof(void*));
829 Substitute ("#undef SIZE_OF_POINTER ", buf);
830 snprintf (buf, VectorSize(buf), "#define SIZE_OF_SIZE_T %d", sizeof(size_t));
831 Substitute ("#undef SIZE_OF_SIZE_T ", buf);
832 if (g_SysType == sys_Alpha || g_SysType == sys_Mac)
833 Substitute ("#undef SIZE_OF_BOOL ", "#define SIZE_OF_BOOL SIZE_OF_LONG");
834 else
835 Substitute ("#undef SIZE_OF_BOOL ", "#define SIZE_OF_BOOL SIZE_OF_CHAR");
836 if ((sizeof(size_t) == sizeof(unsigned long) &&
837 sizeof(size_t) != sizeof(uint)) || g_SysType == sys_Mac)
838 Substitute ("#undef SIZE_T_IS_LONG", "#define SIZE_T_IS_LONG 1");
839 #if defined(__GNUC__) || (__WORDSIZE == 64) || defined(__ia64__)
840 if (g_SysType != sys_Bsd)
841 Substitute ("#undef HAVE_INT64_T", "#define HAVE_INT64_T 1");
842 #endif
843 #if defined(__GNUC__) || defined(__GLIBC_HAVE_LONG_LONG)
844 Substitute ("#undef HAVE_LONG_LONG", "#define HAVE_LONG_LONG 1");
845 snprintf (buf, VectorSize(buf), "#define SIZE_OF_LONG_LONG %d", sizeof(long long));
846 Substitute ("#undef SIZE_OF_LONG_LONG", buf);
847 #endif
848 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
849 Substitute ("#undef HAVE_VECTOR_EXTENSIONS", "#define HAVE_VECTOR_EXTENSIONS 1");
850 #else
851 Substitute ("-Wshadow ", "");
852 #endif
854 Substitute ("#undef LSTAT_FOLLOWS_SLASHED_SYMLINK", "#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1");
855 Substitute ("#undef HAVE_STAT_EMPTY_STRING_BUG", "/* #undef HAVE_STAT_EMPTY_STRING_BUG */");
857 if (g_SysType == sys_Linux)
858 Substitute ("#undef HAVE_RINTF", "#define HAVE_RINTF 1");
860 Substitute ("@BYTE_ORDER@", boNames [(uint)(*((const char*)&boCheck))]);
863 static void SubstituteCustomVars (void)
865 uint i;
866 SBuf match = NULL_BUF;
867 foreachN (i, g_CustomVars, 2) {
868 MakeSubstString (g_CustomVars [i * 2], &match);
869 Substitute (S(match), g_CustomVars [i * 2 + 1]);
871 buf_free (&match);
874 static void SubstituteHeaders (void)
876 uint i;
877 cpchar_t pi;
878 SBuf defaultPath = NULL_BUF, match = NULL_BUF;
880 copy (S(g_ConfigVV [vv_includedir]), &defaultPath);
881 append2 (":", S(g_ConfigVV [vv_oldincludedir]), &defaultPath);
882 append2 (":", S(g_ConfigVV [vv_gccincludedir]), &defaultPath);
883 for (i = 0; i != (uint) g_nCustomIncDirs; ++ i)
884 append2 (":", S(g_CustomIncDirs [i]), &defaultPath);
885 foreachN (i, g_Headers, 3) {
886 for (pi = S(defaultPath); pi; pi = CopyPathEntry (pi, &match)) {
887 append2 ("/", g_Headers [i * 3], &match);
888 if (access (S(match), R_OK) == 0)
889 Substitute (g_Headers [i * 3 + 1], g_Headers [i * 3 + 2]);
892 buf_free (&match);
893 buf_free (&defaultPath);
896 static void SubstituteLibs (void)
898 static const cpchar_t g_LibSuffixes[] = { ".a", ".so", ".la", ".dylib" };
899 uint i, k, ok;
900 cpchar_t pi;
901 SBuf defaultPath = NULL_BUF, match = NULL_BUF;
903 copy ("/lib:/usr/lib:/usr/local/lib", &defaultPath);
904 pi = getenv ("LD_LIBRARY_PATH");
905 if (pi)
906 append2 (":", pi, &defaultPath);
907 append2 (":", S(g_ConfigVV [vv_libdir]), &defaultPath);
908 append2 (":", S(g_ConfigVV [vv_gcclibdir]), &defaultPath);
909 for (i = 0; i != (uint) g_nCustomLibDirs; ++ i)
910 append2 (":", S(g_CustomLibDirs [i]), &defaultPath);
912 foreachN (i, g_Libs, 3) {
913 ok = 0;
914 for (pi = S(defaultPath); pi; pi = CopyPathEntry (pi, &match)) {
915 foreach (k, g_LibSuffixes) {
916 CopyPathEntry (pi, &match);
917 append2 ("/lib", g_Libs [i * 3], &match);
918 append (g_LibSuffixes [k], &match);
919 if (access (S(match), R_OK) == 0)
920 ok = 1;
923 copy ("@lib", &match);
924 append2 (g_Libs[i * 3], "@", &match);
925 Substitute (S(match), g_Libs [i * 3 + 1 + ok]);
927 buf_free (&match);
928 buf_free (&defaultPath);
931 static void SubstituteFunctions (void)
933 uint i;
934 foreachN (i, g_Functions, 3)
935 Substitute (g_Functions [i * 3 + 1], g_Functions [i * 3 + 2]);
936 if ((g_SysType == sys_Mac) | (g_SysType == sys_Bsd))
937 Substitute ("#define HAVE_STRSIGNAL 1", "#undef HAVE_STRSIGNAL");
938 if (g_SysType == sys_Bsd)
939 Substitute ("#define HAVE_VA_COPY 1", "#undef HAVE_VA_COPY");
942 static void SubstituteComponents (void)
944 uint i, isOn;
945 foreachN (i, g_Components, 3) {
946 isOn = g_ComponentInfos[i].m_bDefaultOn;
947 Substitute (g_Components [i * 3 + 1 + !isOn], g_Components [i * 3 + 1 + isOn]);
951 /*--------------------------------------------------------------------*/
953 int main (int argc, const char* const* argv)
955 InitGlobals();
956 GetConfigVarValues (--argc, ++argv);
957 FillInDefaultConfigVarValues();
959 FindPrograms();
960 SubstituteComponents();
961 SubstituteHostOptions();
962 SubstituteCpuCaps();
963 SubstituteCFlags();
964 SubstitutePaths();
965 SubstituteEnvironment (0);
966 SubstitutePrograms();
967 SubstituteHeaders();
968 SubstituteLibs();
969 SubstituteFunctions();
970 SubstituteCustomVars();
971 SubstituteEnvironment (1);
973 ApplySubstitutions();
974 FreeGlobals();
975 return (0);