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
|
// file : tests/build-class-expr/driver.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
#include <ios>
#include <string>
#include <iostream>
#include <libbutl/utility.mxx> // eof(), operator<<(ostream, exception)
#include <libbutl/optional.mxx>
#include <libbpkg/manifest.hxx>
#undef NDEBUG
#include <cassert>
// Usages:
//
// argv[0] -p
// argv[0] [<class>[:<base>]]*
//
// Parse stdin lines as build configuration class expressions and print them
// or evaluate.
//
// In the first form print expressions to stdout, one per line.
//
// In the second form sequentially match the configuration classes passed as
// arguments against the expressions, updating the match result. If the first
// expression has an underlying class set specified, then transform the
// combined expression, making the underlying class set a starting set for the
// original expression and a restricting set, simultaneously.
//
// On error print the exception description to stderr and exit with the two
// status. Otherwise, if the combined expression doesn't match then exit with
// the one status. Otherwise, exit with zero status.
//
int
main (int argc, char* argv[])
{
using namespace std;
using namespace butl;
using namespace bpkg;
using butl::optional;
bool print (argc != 1 && argv[1] == string ("-p"));
assert (!print || argc == 2);
cin.exceptions (ios::badbit);
strings cs;
build_class_inheritance_map im;
if (print)
cout.exceptions (ios::failbit | ios::badbit);
else
{
for (int i (1); i != argc; ++i)
{
string c (argv[i]);
string base;
size_t p (c.find (':'));
if (p != string::npos)
{
base = string (c, p + 1);
c.resize (p);
}
im[c] = move (base);
cs.emplace_back (move (c));
}
}
try
{
string s;
bool r (false);
optional<strings> underlying_cls;
while (!eof (getline (cin, s)))
{
build_class_expr expr (s, "" /* comment */);
if (print)
cout << expr << endl;
else
{
if (!underlying_cls)
{
underlying_cls = move (expr.underlying_classes);
if (!underlying_cls->empty ())
{
build_class_expr expr (*underlying_cls, '+', "" /* comment */);
expr.match (cs, im, r);
}
}
expr.match (cs, im, r);
}
}
if (underlying_cls && !underlying_cls->empty ())
{
build_class_expr expr (*underlying_cls, '&', "" /* comment */);
expr.match (cs, im, r);
}
return print || r ? 0 : 1;
}
catch (const exception& e)
{
cerr << e << endl;
return 2;
}
}
|