configure/src/configure.c

286 lines
5.6 KiB
C

/* configure.c */
#include <System.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include "makefile.h"
#include "configure.h"
/* configure */
/* variables */
const String * sHostArch[HA_LAST+1] =
{
"i386", "i486", "i586", "i686",
"sparc",
"unknown"
};
const String * sHostOS[HO_LAST+1] =
{
"Linux",
"FreeBSD", "NetBSD", "OpenBSD",
"unknown"
};
const String * sHostKernel[HK_LAST+1] =
{
"2.0", "2.2", "2.4", "2.6",
"2.0",
"unknown"
};
const String * sTargetType[TT_LAST] = { "binary", "library", "object" };
const String * sObjectType[OT_LAST] = { "c", "S" };
String * _source_extension(String * source)
{
int len;
for(len = string_length(source)-1; len >= 0; len--)
if(source[len] == '.')
return &source[len+1];
return NULL;
}
/* functions */
int configure_error(char const * message, int ret)
{
fprintf(stderr, "%s", "configure: ");
perror(message);
return ret;
}
int enum_string(int last, const String * strings[], String * str)
{
int i;
for(i = 0; i < last; i++)
if(string_compare(strings[i], str) == 0)
return i;
return last;
}
int enum_string_short(int last, const String * strings[], String * str)
{
int i;
for(i = 0; i < last; i++)
if(string_compare_length(strings[i], str,
string_length(strings[i])) == 0)
return i;
return last;
}
/* Configure */
static void _configure_detect(Configure * configure);
static int _configure_load(Prefs * prefs, char const * directory,
configArray * ca);
static int _configure_do(Configure * configure, configArray * ca);
static int _configure(Prefs * prefs, char const * directory)
{
Configure cfgr;
configArray * ca;
int ret;
int i;
Config * p;
if((ca = configarray_new()) == NULL)
return configure_error("libSystem", 2);
cfgr.prefs = *prefs;
_configure_detect(&cfgr);
ret = _configure_load(prefs, directory, ca);
if(ret == 0)
{
if(*prefs & PREFS_n)
ret = _configure_do(&cfgr, ca);
else
{
cfgr.prefs = PREFS_n;
if(_configure_do(&cfgr, ca) == 0)
{
cfgr.prefs = *prefs;
ret = _configure_do(&cfgr, ca);
}
}
}
for(i = array_count(ca); i > 0; i--)
{
array_get_copy(ca, i - 1, &p);
config_delete(p);
}
array_delete(ca);
return ret;
}
/* private */
static void _configure_detect(Configure * configure)
{
struct utsname un;
if(uname(&un) != 0)
{
configure_error("system detection failed", 0);
configure->arch = HA_UNKNOWN;
configure->os = HO_UNKNOWN;
configure->kernel = HK_UNKNOWN;
return;
}
configure->arch = enum_string(HA_LAST, sHostArch, un.machine);
configure->os = enum_string(HO_LAST, sHostOS, un.sysname);
configure->kernel = enum_string_short(HK_LAST, sHostKernel,
un.release);
if(configure->prefs & PREFS_v)
printf("Detected system %s version %s on %s\n",
sHostOS[configure->os],
sHostKernel[configure->kernel],
sHostArch[configure->arch]);
}
static int _load_subdirs(Prefs * prefs, char const * directory,
configArray * ca, String * subdirs);
static int _configure_load(Prefs * prefs, String const * directory,
configArray * ca)
{
int ret = 0;
Config * config;
String * path;
String * subdirs = NULL;
if((path = string_new(directory)) == NULL)
return configure_error(directory, 1);
if(string_append(&path, "/") != 0
|| string_append(&path, PROJECT_CONF) != 0
|| (config = config_new()) == NULL)
{
string_delete(path);
return configure_error(directory, 1);
}
config_set(config, "", "directory", directory);
if(*prefs & PREFS_v)
printf("%s%s%s", "Loading project file ", path, "\n");
if(config_load(config, path) != 0)
ret = configure_error(path, 1);
else
{
array_append(ca, &config);
subdirs = config_get(config, "", "subdirs");
}
string_delete(path);
if(subdirs == NULL)
return ret;
return _load_subdirs(prefs, directory, ca, subdirs);
}
static int _load_subdirs_subdir(Prefs * prefs, char const * directory,
configArray * ca, char const * subdir);
static int _load_subdirs(Prefs * prefs, char const * directory,
configArray * ca, String * subdirs)
{
int ret = 0;
int i;
char c;
String * subdir;
subdir = subdirs;
for(i = 0; ret == 0; i++)
{
if(subdir[i] != ',' && subdir[i] != '\0')
continue;
c = subdir[i];
subdir[i] = '\0';
ret = _load_subdirs_subdir(prefs, directory, ca, subdir);
if(c == '\0')
break;
subdir[i] = c;
subdir+=i+1;
i = 0;
}
return ret;
}
static int _load_subdirs_subdir(Prefs * prefs, char const * directory,
configArray * ca, char const * subdir)
/* FIXME error checking */
{
int ret;
String * p;
p = string_new(directory);
string_append(&p, "/");
string_append(&p, subdir);
ret = _configure_load(prefs, p, ca);
string_delete(p);
return ret;
}
static int _configure_do(Configure * configure, configArray * ca)
{
int i;
int cnt = array_count(ca);
Config * ci;
String * di;
int j;
Config * cj;
String * dj;
for(i = 0; i < cnt; i++)
{
array_get_copy(ca, i, &ci);
di = config_get(ci, "", "directory");
for(j = i; j < cnt; j++)
{
array_get_copy(ca, j, &cj);
dj = config_get(cj, "", "directory");
if(string_find(dj, di) == NULL)
break;
}
if(makefile(configure, ci, di, ca, i, j) != 0)
break;
}
return i == cnt ? 0 : 1;
}
/* usage */
static int _usage(void)
{
fprintf(stderr, "%s", "Usage: configure [-nv][directory]\n\
-n do not actually write Makefiles\n\
-v verbose mode\n");
return 1;
}
/* main */
int main(int argc, char * argv[])
{
Prefs prefs = 0;
int o;
while((o = getopt(argc, argv, "nv")) != -1)
switch(o)
{
case 'n':
prefs |= PREFS_n;
break;
case 'v':
prefs |= PREFS_v;
break;
case '?':
return _usage();
}
if(argc - optind > 1)
return _usage();
return _configure(&prefs, argc - optind == 1 ? argv[argc - 1] : ".");
}