From 39101a4383d38c1217c44b999a6e3bd199727c60 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 6 Jan 2017 17:28:08 +0200 Subject: Rework and rename target_triplet --- butl/buildfile | 2 +- butl/target-triplet | 155 ++++++++++++++++++++++++++++++++++++++ butl/target-triplet.cxx | 145 ++++++++++++++++++++++++++++++++++++ butl/triplet | 116 ----------------------------- butl/triplet.cxx | 135 --------------------------------- tests/buildfile | 2 +- tests/target-triplet/buildfile | 7 ++ tests/target-triplet/driver.cxx | 161 ++++++++++++++++++++++++++++++++++++++++ tests/triplet/buildfile | 7 -- tests/triplet/driver.cxx | 161 ---------------------------------------- 10 files changed, 470 insertions(+), 421 deletions(-) create mode 100644 butl/target-triplet create mode 100644 butl/target-triplet.cxx delete mode 100644 butl/triplet delete mode 100644 butl/triplet.cxx create mode 100644 tests/target-triplet/buildfile create mode 100644 tests/target-triplet/driver.cxx delete mode 100644 tests/triplet/buildfile delete mode 100644 tests/triplet/driver.cxx diff --git a/butl/buildfile b/butl/buildfile index 9168774..dd2e6bb 100644 --- a/butl/buildfile +++ b/butl/buildfile @@ -24,8 +24,8 @@ lib{butl}: \ {hxx cxx}{ sha256 } \ {hxx }{ small-vector } \ {hxx txx }{ string-table } \ +{hxx cxx}{ target-triplet } \ {hxx cxx}{ timestamp } \ -{hxx cxx}{ triplet } \ {hxx ixx cxx}{ utility } \ {hxx }{ vector-view } \ {hxx }{ version } diff --git a/butl/target-triplet b/butl/target-triplet new file mode 100644 index 0000000..d355d75 --- /dev/null +++ b/butl/target-triplet @@ -0,0 +1,155 @@ +// file : butl/target-triplet -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#ifndef BUTL_TARGET_TRIPLET +#define BUTL_TARGET_TRIPLET + +#include +#include + +#include + +namespace butl +{ + // This is the ubiquitous 'target triplet' that loosely has the CPU-VENDOR-OS + // form which, these days, quite often takes the CPU-VENDOR-OS-ABI form. Plus + // some fields can sometimes be omitted. This looseness makes it hard to base + // any kind of decisions on the triplet without canonicalizing it and then + // splitting it into components. The way we are going to split it is like + // this: + // + // CPU + // + // This one is reasonably straightforward. Note that we always expect at + // least two components with the first being the CPU. In other words, we + // don't try to guess what just 'mingw32' might mean like config.sub does. + // + // VENDOR + // + // This can be a machine vendor as in i686-apple-darwin8, a toolchain vendor + // as in i686-lfs-linux-gnu, or something else as in arm-softfloat-linux-gnu. + // Just as we think vendor is pretty irrelevant and can be ignored, comes + // MinGW-W64 and calls itself *-w64-mingw32. While it is tempting to + // attribute w64 to OS-ABI, the MinGW-W64 folks insist it is a (presumably + // toolchain) vendor. + // + // Another example where the vendor seems to be reused for something else + // entirely is the Intel's MIC architecture: x86_64-k1om-linux. + // + // To make things more regular we also convert the information-free vendor + // names 'pc', 'unknown' and 'none' to the empty name. + // + // OS/KERNEL-OS/OS-ABI + // + // This is where things get really messy and instead of trying to guess, we + // call the entire thing SYSTEM. Except, in certain cases, we factor out the + // trailing version, again, to make SYSTEM easier to compare to. For example, + // *-darwin14.5.0 becomes 'darwin' and '14.5.0'. + // + // Again, to make things more regular, if the first component in SYSTEM is + // none, then it is removed (so *-none-eabi becomes just 'eabi'). + // + // Values for two-component systems (e.g., linux-gnu) that don't specify + // VENDOR explicitly are inherently ambiguous: is 'linux' VENDOR or part of + // SYSTEM? The only way to handle this is to recognize their specific names + // as special cases and this is what we do for some of the more common + // ones. The alternative would be to first run such names through config.sub + // which adds explicit VENDOR and this could be a reasonable fallback + // strategy for (presumably less common) cases were we don't split things + // correctly. + // + // Note also that the version splitting is only done for certain commonly- + // used targets. + // + // Some examples of canonicalization and splitting: + // + // x86_64-apple-darwin14.5.0 x86_64 apple darwin 14.5.0 + // x86_64-unknown-freebsd10.2 x86_64 freebsd 10.2 + // i686-elf i686 elf + // arm-eabi arm eabi + // arm-none-eabi arm eabi + // arm-none-linux-gnueabi arm linux-gnueabi + // arm-softfloat-linux-gnu arm softfloat linux-gnu + // i686-pc-mingw32 i686 mingw32 + // i686-w64-mingw32 i686 w64 mingw32 + // i686-lfs-linux-gnu i686 lfs linux-gnu + // x86_64-unknown-linux-gnu x86_64 linux-gnu + // x86_64-linux-gnux32 x86_64 linux-gnux32 + // x86_64-microsoft-win32-msvc14.0 x86_64 microsoft win32-msvc 14.0 + // + // Similar to version splitting, for certain commonly-used targets we also + // derive the "target class" which can be used as a shorthand, more + // convenient way to identify a targets. If the target is not recognized, + // then the special 'other' value is used. Currently the following classes + // are recognized: + // + // linux *-*-linux-* + // macosx *-apple-darwin* + // bsd *-*-(freebsd|openbsd|netbsd)* + // windows *-*-win32-* | *-*-mingw32 + // + // References: + // + // 1. The libtool repository contains the PLATFORM file that lists many known + // triplets. + // + // 2. LLVM has the Triple class with similar goals. + // + struct LIBBUTL_EXPORT target_triplet + { + std::string cpu; + std::string vendor; + std::string system; + std::string version; + std::string class_; + + // Assemble and returning the canonical (i.e., the one we round-trip) + // target triplet string. + // + std::string + string () const; + + bool + empty () const {return cpu.empty ();} + + int + compare (const target_triplet& y) const + { + int r; + return + (r = cpu.compare (y.cpu)) != 0 ? r : + (r = vendor.compare (y.vendor)) != 0 ? r : + (r = system.compare (y.system)) != 0 ? r : + ( version.compare (y.version)); + } + + // Parse the triplet throw std::invalid_argument if the triplet is not + // recognizable. + // + explicit + target_triplet (const std::string&); + + target_triplet () = default; + }; + + inline bool + operator== (const target_triplet& x, const target_triplet& y) + { + return x.compare (y) == 0; + } + + inline bool + operator!= (const target_triplet& x, const target_triplet& y) + { + return !(x == y); + } + + inline std::ostream& + operator<< (std::ostream& o, const target_triplet& x) + { + return o << x.string (); + } +}; + +#endif // BUTL_TARGET_TRIPLET diff --git a/butl/target-triplet.cxx b/butl/target-triplet.cxx new file mode 100644 index 0000000..f7da724 --- /dev/null +++ b/butl/target-triplet.cxx @@ -0,0 +1,145 @@ +// file : butl/target-triplet.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include + +#include // invalid_argument + +using namespace std; + +namespace butl +{ + target_triplet:: + target_triplet (const std::string& s) + { + using std::string; + + auto bad = [](const char* m) {throw invalid_argument (m);}; + + // Find the first and the last components. The first is CPU and the last is + // (part of) SYSTEM, that we know for sure. + // + string::size_type f (s.find ('-')), l (s.rfind ('-')); + + if (f == 0 || f == string::npos) + bad ("missing cpu"); + + cpu.assign (s, 0, f); + + // If we have something in between, then the first component after CPU is + // VENDOR. Unless it is a first component of two-component system, as in + // i686-linux-gnu. + // + if (f != l) + { + // [f, p) is VENDOR. + // + string::size_type p (s.find ('-', ++f)), n (p - f); + + if (n == 0) + bad ("empty vendor"); + + // Do we have all four components? If so, then we don't need to do any + // special recognition of two-component systems. + // + if (l != p) + { + l = s.rfind ('-', --l); + + if (l != p) + bad ("too many components"); + + // Handle the none-* case here. + // + if (s.compare (l + 1, 5, "none-") == 0) + l += 5; + } + else + { + // See if this is one of the well-known non-vendors. + // + if (s.compare (f, n, "linux") == 0 || + s.compare (f, n, "kfreebsd") == 0) + { + l = f - 1; + n = 0; // No VENDOR. + } + } + + // Handle special VENDOR values. + // + if (n != 0) + { + if (s.compare (f, n, "pc") != 0 && + s.compare (f, n, "none") != 0 && + s.compare (f, n, "unknown") != 0) + vendor.assign (s, f, n); + } + } + + // (l, npos) is SYSTEM + // + system.assign (s, ++l, string::npos); + + if (system.empty ()) + bad ("missing os/kernel/abi"); + + if (system.front () == '-' || system.back () == '-') + bad ("invalid os/kernel/abi"); + + // Extract VERSION for some recognized systems. + // + string::size_type v (0); + if (system.compare (0, (v = 6), "darwin") == 0 || + system.compare (0, (v = 7), "freebsd") == 0 || + system.compare (0, (v = 7), "openbsd") == 0 || + system.compare (0, (v = 6), "netbsd") == 0 || + system.compare (0, (v = 7), "solaris") == 0 || + system.compare (0, (v = 3), "aix") == 0 || + system.compare (0, (v = 4), "hpux") == 0 || + system.compare (0, (v = 10), "win32-msvc") == 0) + { + version.assign (system, v, string::npos); + system.resize (system.size () - version.size ()); + } + + // Determine class for some recognized systems. + // + if (system.compare (0, 5, "linux") == 0) + class_ = "linux"; + else if (vendor == "apple" && system == "darwin") + class_ = "macosx"; + else if (system == "freebsd" || system == "openbsd" || system == "netbsd") + class_ = "bsd"; + else if (system.compare (0, 5, "win32") == 0 || system == "mingw32") + class_ = "windows"; + else + class_ = "other"; + } + + std::string target_triplet:: + string () const + { + std::string r (cpu); + + if (!vendor.empty ()) + { + if (!r.empty ()) r += '-'; + r += vendor; + } + + if (!system.empty ()) + { + if (!r.empty ()) r += '-'; + r += system; + } + + if (!version.empty ()) + { + r += version; + } + + return r; + } +} diff --git a/butl/triplet b/butl/triplet deleted file mode 100644 index 0d1b7f4..0000000 --- a/butl/triplet +++ /dev/null @@ -1,116 +0,0 @@ -// file : butl/triplet -*- C++ -*- -// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#ifndef BUTL_TRIPLET -#define BUTL_TRIPLET - -#include - -#include - -namespace butl -{ - // This is the ubiquitous 'target triplet' that loosely has the CPU-VENDOR-OS - // form which, these days, quite often takes the CPU-VENDOR-OS-ABI form. Plus - // some fields can sometimes be omitted. This looseness makes it hard to base - // any kind of decisions on the triplet without canonicalizing it and then - // splitting it into components. the way we are going to split it is like - // this: - // - // CPU - // - // This one is reasonably straightforward. Note that we always expect at - // least two components with the first being the CPU. In other words, we - // don't try to guess what just 'mingw32' might mean like config.sub does. - // - // VENDOR - // - // This can be a machine vendor as in i686-apple-darwin8, a toolchain vendor - // as in i686-lfs-linux-gnu, or something else as in arm-softfloat-linux-gnu. - // Just as we think vendor is pretty irrelevant and can be ignored, comes - // MinGW-W64 and calls itself *-w64-mingw32. While it is tempting to - // attribute w64 to OS-ABI, the MinGW-W64 folks insist it is a (presumably - // toolchain) vendor. - // - // Another example where the vendor seems to be reused for something else - // entirely is the Intel's MIC architecture: x86_64-k1om-linux. - // - // To make things more regular we also convert the information-free vendor - // names 'pc', 'unknown' and 'none' to the empty name. - // - // OS/KERNEL-OS/OS-ABI - // - // This is where things get really messy and instead of trying to guess, we - // call the entire thing SYSTEM. Except, in certain cases, we factor out the - // trailing version, again, to make SYSTEM easier to compare to. For example, - // *-darwin14.5.0 becomes 'darwin' and '14.5.0'. - // - // Again, to make things more regular, if the first component in SYSTEM is - // none, then it is removed (so *-none-eabi becomes just 'eabi'). - // - // Values for two-component systems (e.g., linux-gnu) that don't specify - // VENDOR explicitly are inherently ambiguous: is 'linux' VENDOR or part of - // SYSTEM? The only way to handle this is to recognize their specific names - // as special cases and this is what we do for some of the more common - // ones. The alternative would be to first run such names through config.sub - // which adds explicit VENDOR and this could be a reasonable fallback - // strategy for (presumably less common) cases were we don't split things - // correctly. - // - // Note also that the version splitting is only done for certain commonly- - // used targets. - // - // Some examples of canonicalization and splitting: - // - // x86_64-apple-darwin14.5.0 x86_64 apple darwin 14.5.0 - // x86_64-unknown-freebsd10.2 x86_64 freebsd 10.2 - // i686-elf i686 elf - // arm-eabi arm eabi - // arm-none-eabi arm eabi - // arm-none-linux-gnueabi arm linux-gnueabi - // arm-softfloat-linux-gnu arm softfloat linux-gnu - // i686-pc-mingw32 i686 mingw32 - // i686-w64-mingw32 i686 w64 mingw32 - // i686-lfs-linux-gnu i686 lfs linux-gnu - // x86_64-unknown-linux-gnu x86_64 linux-gnu - // x86_64-linux-gnux32 x86_64 linux-gnux32 - // x86_64-microsoft-win32-msvc14.0 x86_64 microsoft win32-msvc 14.0 - // - // Similar to version splitting, for certain commonly-used targets we also - // derive the "target class" which can be used as a shorthand, more - // convenient way to identify a targets. If the target is not recognized, - // then the special 'other' value is used. Currently the following classes - // are recognized: - // - // linux *-*-linux-* - // macosx *-apple-darwin* - // bsd *-*-(freebsd|openbsd|netbsd)* - // windows *-*-win32-* | *-*-mingw32 - // - // References: - // - // 1. The libtool repository contains the PLATFORM file that lists many known - // triplets. - // - // 2. LLVM has the Triple class with similar goals. - // - struct LIBBUTL_EXPORT triplet - { - std::string cpu; - std::string vendor; - std::string system; - std::string version; - std::string class_; - - // Parse the triplet optionally returning the canonicalized string. Throw - // std::invalid_argument if the triplet is not recognizable. - // - explicit - triplet (const std::string&, std::string* canon = nullptr); - triplet (const std::string& s, std::string& canon): triplet (s, &canon) {} - triplet () = default; - }; -}; - -#endif // BUTL_TRIPLET diff --git a/butl/triplet.cxx b/butl/triplet.cxx deleted file mode 100644 index 2177717..0000000 --- a/butl/triplet.cxx +++ /dev/null @@ -1,135 +0,0 @@ -// file : butl/triplet.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include - -#include // invalid_argument - -using namespace std; - -namespace butl -{ - triplet:: - triplet (const string& s, string* c) - { - auto bad = [](const char* m) {throw invalid_argument (m);}; - - // Find the first and the last components. The first is CPU and the last is - // (part of) SYSTEM, that we know for sure. - // - string::size_type f (s.find ('-')), l (s.rfind ('-')); - - if (f == 0 || f == string::npos) - bad ("missing cpu"); - - cpu.assign (s, 0, f); - - if (c != nullptr) - *c = cpu; - - // If we have something in between, then the first component after CPU is - // VENDOR. Unless it is a first component of two-component system, as in - // i686-linux-gnu. - // - if (f != l) - { - // [f, p) is VENDOR. - // - string::size_type p (s.find ('-', ++f)), n (p - f); - - if (n == 0) - bad ("empty vendor"); - - // Do we have all four components? If so, then we don't need to do any - // special recognition of two-component systems. - // - if (l != p) - { - l = s.rfind ('-', --l); - - if (l != p) - bad ("too many components"); - - // Handle the none-* case here. - // - if (s.compare (l + 1, 5, "none-") == 0) - l += 5; - } - else - { - // See if this is one of the well-known non-vendors. - // - if (s.compare (f, n, "linux") == 0 || - s.compare (f, n, "kfreebsd") == 0) - { - l = f - 1; - n = 0; // No VENDOR. - } - } - - // Handle special VENDOR values. - // - if (n != 0) - { - if (s.compare (f, n, "pc") != 0 && - s.compare (f, n, "none") != 0 && - s.compare (f, n, "unknown") != 0) - { - vendor.assign (s, f, n); - - if (c != nullptr) - { - *c += '-'; - *c += vendor; - } - } - } - } - - // (l, npos) is SYSTEM - // - system.assign (s, ++l, string::npos); - - if (system.empty ()) - bad ("missing os/kernel/abi"); - - if (system.front () == '-' || system.back () == '-') - bad ("invalid os/kernel/abi"); - - if (c != nullptr) - { - *c += '-'; - *c += system; - } - - // Extract VERSION for some recognized systems. - // - string::size_type v (0); - if (system.compare (0, (v = 6), "darwin") == 0 || - system.compare (0, (v = 7), "freebsd") == 0 || - system.compare (0, (v = 7), "openbsd") == 0 || - system.compare (0, (v = 6), "netbsd") == 0 || - system.compare (0, (v = 7), "solaris") == 0 || - system.compare (0, (v = 3), "aix") == 0 || - system.compare (0, (v = 4), "hpux") == 0 || - system.compare (0, (v = 10), "win32-msvc") == 0) - { - version.assign (system, v, string::npos); - system.resize (system.size () - version.size ()); - } - - // Determine class for some recognized systems. - // - if (system.compare (0, 5, "linux") == 0) - class_ = "linux"; - else if (vendor == "apple" && system == "darwin") - class_ = "macosx"; - else if (system == "freebsd" || system == "openbsd" || system == "netbsd") - class_ = "bsd"; - else if (system.compare (0, 5, "win32") == 0 || system == "mingw32") - class_ = "windows"; - else - class_ = "other"; - } -} diff --git a/tests/buildfile b/tests/buildfile index 7259717..8608ed9 100644 --- a/tests/buildfile +++ b/tests/buildfile @@ -4,7 +4,7 @@ d = base64/ cpfile/ dir-iterator/ fdstream/ link/ manifest-parser/ \ manifest-serializer/ manifest-roundtrip/ pager/ path/ prefix-map/ \ - process/ sha256/ small-vector/ strcase/ timestamp/ triplet/ + process/ sha256/ small-vector/ strcase/ timestamp/ target-triplet/ ./: $d include $d diff --git a/tests/target-triplet/buildfile b/tests/target-triplet/buildfile new file mode 100644 index 0000000..ca8365d --- /dev/null +++ b/tests/target-triplet/buildfile @@ -0,0 +1,7 @@ +# file : tests/target-triplet/buildfile +# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} + +include ../../butl/ diff --git a/tests/target-triplet/driver.cxx b/tests/target-triplet/driver.cxx new file mode 100644 index 0000000..fe055db --- /dev/null +++ b/tests/target-triplet/driver.cxx @@ -0,0 +1,161 @@ +// file : tests/target-triplet/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include +#include +#include // invalid_argument + +#include + +using namespace std; +using namespace butl; + +static bool +fail (const char*); + +static bool +test (const char*, + const char* canon, + const char* cpu, + const char* vendor, + const char* system, + const char* version, + const char* class_ = "other"); + +int +main () +{ + assert (fail ("")); + assert (fail ("mingw32")); + assert (fail ("-")); + assert (fail ("arm-")); + assert (fail ("-mingw32")); + assert (fail ("a-b-c-d-e")); + assert (fail ("arm-pc--")); + assert (fail ("arm-pc-linux-")); + assert (fail ("arm-pc--gnu")); + + assert (test ("i686-elf", + "i686-elf", + "i686", "", "elf", "")); + + assert (test ("arm-eabi", + "arm-eabi", + "arm", "", "eabi", "")); + + assert (test ("arm-none-eabi", + "arm-eabi", + "arm", "", "eabi", "")); + + assert (test ("arm-none-linux-gnueabi", + "arm-linux-gnueabi", + "arm", "", "linux-gnueabi", "", "linux")); + + assert (test ("arm-softfloat-linux-gnu", + "arm-softfloat-linux-gnu", + "arm", "softfloat", "linux-gnu", "", "linux")); + + assert (test ("i686-pc-mingw32", + "i686-mingw32", + "i686", "", "mingw32", "", "windows")); + + assert (test ("i686-w64-mingw32", + "i686-w64-mingw32", + "i686", "w64", "mingw32", "", "windows")); + + assert (test ("i686-lfs-linux-gnu", + "i686-lfs-linux-gnu", + "i686", "lfs", "linux-gnu", "", "linux")); + + assert (test ("x86_64-unknown-linux-gnu", + "x86_64-linux-gnu", + "x86_64", "", "linux-gnu", "", "linux")); + + assert (test ("x86_64-linux-gnux32", + "x86_64-linux-gnux32", + "x86_64", "", "linux-gnux32", "", "linux")); + + // Removal of none-. + // + assert (test ("arm-none", + "arm-none", + "arm", "", "none", "")); + + assert (test ("arm-unknown-none-eabi", + "arm-eabi", + "arm", "", "eabi", "")); + + // Version extraction. + // + assert (test ("x86_64-apple-darwin14.5.0", + "x86_64-apple-darwin14.5.0", + "x86_64", "apple", "darwin", "14.5.0", "macosx")); + + assert (test ("x86_64-unknown-freebsd10.2", + "x86_64-freebsd10.2", + "x86_64", "", "freebsd", "10.2", "bsd")); + + assert (test ("x86_64-pc-openbsd5.6", + "x86_64-openbsd5.6", + "x86_64", "", "openbsd", "5.6", "bsd")); + + assert (test ("sparc-sun-solaris2.9", + "sparc-sun-solaris2.9", + "sparc", "sun", "solaris", "2.9")); + + assert (test ("x86_64-microsoft-win32-msvc14.0", + "x86_64-microsoft-win32-msvc14.0", + "x86_64", "microsoft", "win32-msvc", "14.0", "windows")); +} + +static bool +test (const char* s, + const char* canon, + const char* cpu, + const char* vendor, + const char* system, + const char* version, + const char* class_) +{ + target_triplet t (s); + string c (t.string ()); + + auto cmp = [] (const string& a, const char* e, const char* n) -> bool + { + if (a != e) + { + cerr << n << " actual: " << a << endl + << n << " expect: " << e << endl; + + return false; + } + + return true; + }; + + return + cmp (c, canon, "canonical") && + cmp (t.cpu, cpu, "cpu") && + cmp (t.vendor, vendor, "vendor") && + cmp (t.system, system, "system") && + cmp (t.version, version, "version") && + cmp (t.class_, class_, "class"); +} + +static bool +fail (const char* s) +{ + try + { + target_triplet t (s); + cerr << "nofail: " << s << endl; + return false; + } + catch (invalid_argument& e) + { + //cerr << e.what () << endl; + } + + return true; +} diff --git a/tests/triplet/buildfile b/tests/triplet/buildfile deleted file mode 100644 index 7724f4c..0000000 --- a/tests/triplet/buildfile +++ /dev/null @@ -1,7 +0,0 @@ -# file : tests/triplet/buildfile -# copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -# license : MIT; see accompanying LICENSE file - -exe{driver}: cxx{driver} ../../butl/lib{butl} - -include ../../butl/ diff --git a/tests/triplet/driver.cxx b/tests/triplet/driver.cxx deleted file mode 100644 index 96d76cd..0000000 --- a/tests/triplet/driver.cxx +++ /dev/null @@ -1,161 +0,0 @@ -// file : tests/triplet/driver.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include -#include -#include // invalid_argument - -#include - -using namespace std; -using namespace butl; - -static bool -fail (const char*); - -static bool -test (const char*, - const char* canon, - const char* cpu, - const char* vendor, - const char* system, - const char* version, - const char* class_ = "other"); - -int -main () -{ - assert (fail ("")); - assert (fail ("mingw32")); - assert (fail ("-")); - assert (fail ("arm-")); - assert (fail ("-mingw32")); - assert (fail ("a-b-c-d-e")); - assert (fail ("arm-pc--")); - assert (fail ("arm-pc-linux-")); - assert (fail ("arm-pc--gnu")); - - assert (test ("i686-elf", - "i686-elf", - "i686", "", "elf", "")); - - assert (test ("arm-eabi", - "arm-eabi", - "arm", "", "eabi", "")); - - assert (test ("arm-none-eabi", - "arm-eabi", - "arm", "", "eabi", "")); - - assert (test ("arm-none-linux-gnueabi", - "arm-linux-gnueabi", - "arm", "", "linux-gnueabi", "", "linux")); - - assert (test ("arm-softfloat-linux-gnu", - "arm-softfloat-linux-gnu", - "arm", "softfloat", "linux-gnu", "", "linux")); - - assert (test ("i686-pc-mingw32", - "i686-mingw32", - "i686", "", "mingw32", "", "windows")); - - assert (test ("i686-w64-mingw32", - "i686-w64-mingw32", - "i686", "w64", "mingw32", "", "windows")); - - assert (test ("i686-lfs-linux-gnu", - "i686-lfs-linux-gnu", - "i686", "lfs", "linux-gnu", "", "linux")); - - assert (test ("x86_64-unknown-linux-gnu", - "x86_64-linux-gnu", - "x86_64", "", "linux-gnu", "", "linux")); - - assert (test ("x86_64-linux-gnux32", - "x86_64-linux-gnux32", - "x86_64", "", "linux-gnux32", "", "linux")); - - // Removal of none-. - // - assert (test ("arm-none", - "arm-none", - "arm", "", "none", "")); - - assert (test ("arm-unknown-none-eabi", - "arm-eabi", - "arm", "", "eabi", "")); - - // Version extraction. - // - assert (test ("x86_64-apple-darwin14.5.0", - "x86_64-apple-darwin14.5.0", - "x86_64", "apple", "darwin", "14.5.0", "macosx")); - - assert (test ("x86_64-unknown-freebsd10.2", - "x86_64-freebsd10.2", - "x86_64", "", "freebsd", "10.2", "bsd")); - - assert (test ("x86_64-pc-openbsd5.6", - "x86_64-openbsd5.6", - "x86_64", "", "openbsd", "5.6", "bsd")); - - assert (test ("sparc-sun-solaris2.9", - "sparc-sun-solaris2.9", - "sparc", "sun", "solaris", "2.9")); - - assert (test ("x86_64-microsoft-win32-msvc14.0", - "x86_64-microsoft-win32-msvc14.0", - "x86_64", "microsoft", "win32-msvc", "14.0", "windows")); -} - -static bool -test (const char* s, - const char* canon, - const char* cpu, - const char* vendor, - const char* system, - const char* version, - const char* class_) -{ - string c; - triplet t (s, c); - - auto cmp = [] (const string& a, const char* e, const char* n) -> bool - { - if (a != e) - { - cerr << n << " actual: " << a << endl - << n << " expect: " << e << endl; - - return false; - } - - return true; - }; - - return - cmp (c, canon, "canonical") && - cmp (t.cpu, cpu, "cpu") && - cmp (t.vendor, vendor, "vendor") && - cmp (t.system, system, "system") && - cmp (t.version, version, "version") && - cmp (t.class_, class_, "class"); -} - -static bool -fail (const char* s) -{ - try - { - triplet t (s); - cerr << "nofail: " << s << endl; - return false; - } - catch (invalid_argument& e) - { - //cerr << e.what () << endl; - } - - return true; -} -- cgit v1.1