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
|
// file : build2/name.cxx -*- C++ -*-
// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
// license : MIT; see accompanying LICENSE file
#include <build2/types> // Note: not <build2/names>
#include <string.h> // strchr()
#include <sstream>
#include <build2/diagnostics>
namespace build2
{
ostream&
to_stream (ostream& os, const name& n, bool quote, char pair)
{
auto write_string = [quote, pair, &os](const string& v)
{
char sc[] = {
'{', '}', '[', ']', '$', '(', ')', // Token endings.
' ', '\t', '\n', '#', // Spaces.
'\\', '"', // Escaping and quoting.
'%', // Project name separator.
pair, // Pair separator, if any.
'\0'};
if (quote && v.find ('\'') != string::npos)
{
// Quote the string with the double quotes rather than with the single
// one. Escape some of the special characters.
//
os << '"';
for (auto c: v)
{
if (strchr ("\\$(\"", c) != nullptr) // Special inside double quotes.
os << '\\';
os << c;
}
os << '"';
}
else if (quote && v.find_first_of (sc) != string::npos)
os << "'" << v << "'";
else
os << v;
};
auto write_dir = [quote, &os, &write_string](const dir_path& d)
{
if (quote)
{
std::ostringstream s;
stream_verb (s, stream_verb (os));
s << d;
write_string (s.str ());
}
else
os << d;
};
if (n.proj != nullptr)
{
write_string (*n.proj);
os << '%';
}
// If the value is empty, then we want to print the directory
// inside {}, e.g., dir{bar/}, not bar/dir{}. We also want to
// print {} for an empty name.
//
bool d (!n.dir.empty ());
bool v (!n.value.empty ());
bool t (!n.type.empty () || (!d && !v));
if (v)
write_dir (n.dir);
if (t)
{
write_string (n.type);
os << '{';
}
if (v)
write_string (n.value);
else
write_dir (n.dir);
if (t)
os << '}';
return os;
}
ostream&
to_stream (ostream& os, const names_view& ns, bool quote, char pair)
{
for (auto i (ns.begin ()), e (ns.end ()); i != e; )
{
const name& n (*i);
++i;
to_stream (os, n, quote, pair);
if (n.pair)
os << n.pair;
else if (i != e)
os << ' ';
}
return os;
}
}
|