-/* $Id$
-
-This file is part of builder
-Copyright © 2007-2009 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
+#include <limits>
+#ifndef WIN32
+#include <sys/utsname.h>
+#endif
+#include <msp/strings/format.h>
+#include <msp/strings/utils.h>
#include "architecture.h"
#include "builder.h"
using namespace std;
using namespace Msp;
-Architecture::Architecture(Builder &b, const string &n, bool a):
+namespace {
+
+const char *types[] =
+{
+ "pc",
+ "arm",
+ 0
+};
+
+const char *cpus[] =
+{
+ "i386", "pc",
+ "i486", "pc",
+ "pentium", "pc",
+ "pentiumpro", "pc",
+ "pentium2", "pc",
+ "pentium3", "pc",
+ "pentium4", "pc",
+ "core2", "pc",
+ "k6", "pc",
+ "athlon", "pc",
+ "athlonxp", "pc",
+ "athlon64", "pc",
+ "armv5", "arm",
+ 0
+};
+
+const char *systems[] =
+{
+ "linux",
+ "freebsd",
+ "windows",
+ 0
+};
+
+const char *aliases[] =
+{
+ "i586", "pentium",
+ "i686", "pentiumpro",
+ "x86_64", "athlon64",
+ "win32", "windows",
+ 0
+};
+
+}
+
+Architecture::Architecture(Builder &b, const string &spec):
builder(b),
- name(n),
- native(a)
-{ }
+ bits(0),
+ native(false)
+{
+ if(spec.empty())
+ {
+#ifdef WIN32
+ system = "windows";
+#else
+ utsname un;
+ if(uname(&un)==0)
+ {
+ system = tolower(un.sysname);
+ parse_specification(tolower(un.machine));
+ // We really only want to set type for the default arch
+ cpu.clear();
+ }
+#endif
+ bits = sizeof(void *)*numeric_limits<unsigned char>::digits;
+ native = true;
+ }
+ else
+ {
+ parse_specification(spec);
+ const Architecture &native_arch = builder.get_native_arch();
+ if(type.empty())
+ type = native_arch.type;
+ if(cpu.empty())
+ cpu = native_arch.cpu;
+ if(system.empty())
+ system = native_arch.system;
+ if(!bits)
+ {
+ if(type==native_arch.type)
+ bits = native_arch.bits;
+ else
+ bits = 32;
+ }
+
+ if(type!=native_arch.type || system!=native_arch.system)
+ cross_prefix = format("%s-%s", type, system);
+ else if(bits==native_arch.bits)
+ native = true;
+ }
+ name = type;
+ if(!cpu.empty())
+ name += format("-%s", cpu);
+ name += format("-%d-%s", bits, system);
+}
void Architecture::set_tool(const string &t, const string &p)
{
tools[t] = p;
}
+void Architecture::set_cross_prefix(const string &p)
+{
+ cross_prefix = p;
+}
+
std::string Architecture::get_tool(const string &t) const
{
StringMap::const_iterator i = tools.find(t);
if(i!=tools.end())
{
if(i->second[0]=='-')
- return prefix+i->second;
+ return cross_prefix+i->second;
else
return i->second;
}
- if(!native)
+ const Architecture &native_arch = builder.get_native_arch();
+ if(this!=&native_arch)
{
- const Architecture &native_arch = builder.get_native_arch();
- return prefix+"-"+native_arch.get_tool(t);
+ if(!cross_prefix.empty())
+ return cross_prefix+"-"+native_arch.get_tool(t);
+ else
+ return native_arch.get_tool(t);
}
else
- throw KeyError("Unknown tool");
+ throw invalid_argument("Unknown tool");
+}
+
+bool Architecture::match_name(const string &pattern) const
+{
+ vector<string> parts = split(pattern, "-");
+ for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+ {
+ string part = resolve_alias(*i);
+ if((part=="32" && bits==32) || (part=="64" && bits==64))
+ ;
+ else if(part!=type && part!=cpu && part!=system)
+ return false;
+ }
+ return true;
+}
+
+string Architecture::resolve_alias(const string &part) const
+{
+ for(unsigned j=0; aliases[j]; j+=2)
+ if(part==aliases[j])
+ return aliases[j+1];
+
+ return part;
+}
+
+void Architecture::parse_specification(const string &spec)
+{
+ vector<string> parts = split(spec, "-");
+ for(vector<string>::const_iterator i=parts.begin(); i!=parts.end(); ++i)
+ {
+ string part = resolve_alias(*i);
+
+ bool ok = false;
+
+ for(unsigned j=0; (!ok && types[j]); ++j)
+ if(part==types[j])
+ {
+ if(!type.empty() && part!=type)
+ throw invalid_argument("Conflicting type specification");
+ type = part;
+ ok = true;
+ }
+
+ for(unsigned j=0; (!ok && cpus[j]); j+=2)
+ if(part==cpus[j])
+ {
+ if(type.empty())
+ type = cpus[j+1];
+ else if(cpus[j+1]!=type)
+ throw invalid_argument("Conflicting CPU specification");
+ cpu = part;
+ ok = true;
+ }
+
+ for(unsigned j=0; (!ok && systems[j]); ++j)
+ if(part==systems[j])
+ {
+ system = part;
+ ok = true;
+ }
+
+ if(!ok && (part=="32" || part=="64"))
+ {
+ bits = lexical_cast<unsigned>(part);
+ ok = true;
+ }
+
+ if(!ok)
+ throw invalid_argument("Unrecognized part in arch specification: "+*i);
+ }
}
Architecture::Loader::Loader(Architecture &a):
arch(a)
{
- add("prefix", &Architecture::prefix);
+ add("prefix", &Architecture::cross_prefix);
add("tool", &Loader::tool);
}