blob: 855b093a6418746ecfed6e2ca86d50af9985ccef (
plain)
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
123
124
|
// file : libbbot/build-config.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#include <libbbot/build-config.hxx>
#include <string>
#include <cstddef> // size_t
#include <utility> // move()
#include <stdexcept> // invalid_argument
#include <libbutl/path.hxx>
#include <libbutl/fdstream.hxx>
#include <libbutl/tab-parser.hxx>
#include <libbbot/manifest.hxx> // task_manifest::check_config()
using namespace std;
using namespace butl;
namespace bbot
{
LIBBBOT_EXPORT build_configs
parse_buildtab (istream& is, const string& name)
{
build_configs r;
tab_parser parser (is, name);
tab_fields tl;
while (!(tl = parser.next ()).empty ())
{
size_t n (tl.size ()); // Fields count.
size_t i (0); // The field currently being processed.
// Throw tab_parsing for the field currently being processed. If i == n
// then we refer to the end-of-line column (presumably reporting a missed
// field).
//
auto bad_line = [&name, &tl, &i, n] (const string& d)
{
// Offset beyond the end-of-line is meaningless.
//
assert (i <= n);
throw tab_parsing (name,
tl.line,
i == n
? tl.end_column
: tl[i].column,
d);
};
build_config config;
config.machine_pattern = move (tl[i++].value);
// Configuration name field is a required one.
//
if (i == n)
bad_line ("no configuration name found");
config.name = move (tl[i].value);
// Make sure the name is unique.
//
for (const auto& c: r)
{
if (c.name == config.name)
bad_line ("duplicate configuration name");
}
if (++i == n)
bad_line ("no target found");
try
{
config.target = target_triplet (tl[i].value);
}
catch (const invalid_argument& e)
{
bad_line (e.what ());
}
try
{
for (++i; i < n; ++i)
{
string& v (tl[i].value);
if (v[0] == '~') // Regular expression.
{
string re (v, 1);
task_manifest::check_regex (re);
config.warning_regexes.emplace_back (move (re));
}
else // Configuration variable.
{
task_manifest::check_config (v);
config.vars.emplace_back (move (v));
}
}
}
catch (const invalid_argument& e)
{
bad_line (e.what ());
}
// Save the configuration.
//
r.emplace_back (move (config));
}
return r;
}
build_configs
parse_buildtab (const path& p)
{
ifdstream ifs (p);
build_configs r (parse_buildtab (ifs, p.string ()));
ifs.close (); // Throws on failure.
return r;
}
}
|