1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
// file : butl/triplet.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#include <butl/triplet>
#include <stdexcept> // 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;
}
// Finally, 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 ());
}
}
}
|