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
|
#pragma once
/**
* @file
* @brief Common printing functions for the Nix language
*
* While most types come with their own methods for printing, they share some
* functions that are placed here.
*/
#include <iostream>
#include "fmt.hh"
#include "print-options.hh"
#include "print-elided.hh"
namespace nix {
struct Expr;
class EvalState;
struct Value;
/** Print `true` or `false`. */
std::ostream & printLiteralBool(std::ostream & o, bool b);
/**
* Print a string as an attribute name in the Nix expression language syntax.
*
* Prints a quoted string if necessary.
*/
std::ostream & printAttributeName(std::ostream & o, std::string_view s);
/**
* Returns `true' is a string is a reserved keyword which requires quotation
* when printing attribute set field names.
*/
bool isReservedKeyword(const std::string_view str);
/**
* Print a string as an identifier in the Nix expression language syntax.
*
* FIXME: "identifier" is ambiguous. Identifiers do not have a single
* textual representation. They can be used in variable references,
* let bindings, left-hand sides or attribute names in a select
* expression, or something else entirely, like JSON. Use one of the
* `print*` functions instead.
*/
std::ostream & printIdentifier(std::ostream & o, std::string_view s);
void printValue(EvalState & state, std::ostream & str, Value & v, PrintOptions options = PrintOptions {});
/**
* A partially-applied form of `printValue` which can be formatted using `<<`
* without allocating an intermediate string.
* This class should not outlive the eval state or it will UAF.
* FIXME: This should take `nix::ref`s, to avoid that, but our eval methods all have
* EvalState &, not ref<EvalState>, and constructing a new shared_ptr to data that
* already has a shared_ptr is a much bigger footgun. In the current architecture of
* libexpr, using a ValuePrinter after an EvalState has been destroyed would be
* pretty hard.
*/
class ValuePrinter {
friend std::ostream & operator << (std::ostream & output, const ValuePrinter & printer);
private:
EvalState & state;
Value & value;
PrintOptions options;
public:
ValuePrinter(EvalState & state, Value & value, PrintOptions options = PrintOptions {})
: state(state), value(value), options(options) { }
};
std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer);
/**
* `ValuePrinter` does its own ANSI formatting, so we don't color it
* magenta.
*/
template<>
fmt_internal::HintFmt & fmt_internal::HintFmt::operator%(const ValuePrinter & value);
/**
* A partially-applied form of Expr::show(), which can be formatted using `<<`
* without allocating an intermediate string.
* This class should not outlive the eval state or it will UAF.
* FIXME: This should take `nix::ref`s, to avoid that, but our eval methods all have
* EvalState &, not ref<EvalState>, and constructing a new shared_ptr to data that
* already has a shared_ptr is a much bigger footgun. In the current architecture of
* libexpr, using an ExprPrinter after an EvalState has been destroyed would be
* pretty hard.
*/
class ExprPrinter
{
/** The eval state used to get symbols. */
EvalState const & state;
/** The expression to print. */
Expr const & expr;
public:
ExprPrinter(EvalState const & state, Expr const & expr) : state(state), expr(expr) { }
friend std::ostream & operator << (std::ostream & output, ExprPrinter const & printer);
};
}
|