2 // Automated Testing Framework (atf)
4 // Copyright (c) 2007 The NetBSD Foundation, Inc.
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
10 // 1. Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // 2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "config_file.hpp"
40 namespace impl
= tools::config_file
;
41 namespace detail
= tools::config_file::detail
;
45 typedef std::map
< std::string
, std::string
> vars_map
;
47 namespace atf_config
{
49 static const tools::parser::token_type eof_type
= 0;
50 static const tools::parser::token_type nl_type
= 1;
51 static const tools::parser::token_type text_type
= 2;
52 static const tools::parser::token_type dblquote_type
= 3;
53 static const tools::parser::token_type equal_type
= 4;
54 static const tools::parser::token_type hash_type
= 5;
56 class tokenizer
: public tools::parser::tokenizer
< std::istream
> {
58 tokenizer(std::istream
& is
, size_t curline
) :
59 tools::parser::tokenizer
< std::istream
>
60 (is
, true, eof_type
, nl_type
, text_type
, curline
)
62 add_delim('=', equal_type
);
63 add_delim('#', hash_type
);
64 add_quote('"', dblquote_type
);
68 } // namespace atf_config
70 class config_reader
: public detail::atf_config_reader
{
74 got_var(const std::string
& var
, const std::string
& name
)
80 config_reader(std::istream
& is
) :
93 template< class K
, class V
>
96 merge_maps(std::map
< K
, V
>& dest
, const std::map
< K
, V
>& src
)
98 for (typename
std::map
< K
, V
>::const_iterator iter
= src
.begin();
99 iter
!= src
.end(); iter
++)
100 dest
[(*iter
).first
] = (*iter
).second
;
105 merge_config_file(const tools::fs::path
& config_path
,
108 std::ifstream
is(config_path
.c_str());
110 config_reader
reader(is
);
112 merge_maps(config
, reader
.get_vars());
117 std::vector
< tools::fs::path
>
118 get_config_dirs(void)
120 std::vector
< tools::fs::path
> dirs
;
121 dirs
.push_back(tools::fs::path(tools::config::get("atf_confdir")));
122 if (tools::env::has("HOME"))
123 dirs
.push_back(tools::fs::path(tools::env::get("HOME")) / ".atf");
127 } // anonymous namespace
129 detail::atf_config_reader::atf_config_reader(std::istream
& is
) :
134 detail::atf_config_reader::~atf_config_reader(void)
139 detail::atf_config_reader::got_var(
140 const std::string
& var
__attribute__((__unused__
)),
141 const std::string
& val
__attribute__((__unused__
)))
146 detail::atf_config_reader::got_eof(void)
151 detail::atf_config_reader::read(void)
153 using tools::parser::parse_error
;
154 using namespace atf_config
;
156 std::pair
< size_t, tools::parser::headers_map
> hml
=
157 tools::parser::read_headers(m_is
, 1);
158 tools::parser::validate_content_type(hml
.second
,
159 "application/X-atf-config", 1);
161 tokenizer
tkz(m_is
, hml
.first
);
162 tools::parser::parser
< tokenizer
> p(tkz
);
166 tools::parser::token t
= p
.expect(eof_type
, hash_type
, text_type
,
168 "eof, #, new line or text");
169 if (t
.type() == eof_type
)
172 if (t
.type() == hash_type
) {
173 (void)p
.rest_of_line();
174 t
= p
.expect(nl_type
, "new line");
175 } else if (t
.type() == text_type
) {
176 std::string name
= t
.text();
178 t
= p
.expect(equal_type
, "equal sign");
180 t
= p
.expect(text_type
, "word or quoted string");
181 ATF_PARSER_CALLBACK(p
, got_var(name
, t
.text()));
183 t
= p
.expect(nl_type
, hash_type
, "new line or comment");
184 if (t
.type() == hash_type
) {
185 (void)p
.rest_of_line();
186 t
= p
.expect(nl_type
, "new line");
188 } else if (t
.type() == nl_type
) {
191 } catch (const parse_error
& pe
) {
197 ATF_PARSER_CALLBACK(p
, got_eof());
201 impl::merge_configs(const vars_map
& lower
,
202 const vars_map
& upper
)
204 vars_map merged
= lower
;
205 merge_maps(merged
, upper
);
210 impl::read_config_files(const std::string
& test_suite_name
)
214 const std::vector
< tools::fs::path
> dirs
= get_config_dirs();
215 for (std::vector
< tools::fs::path
>::const_iterator iter
= dirs
.begin();
216 iter
!= dirs
.end(); iter
++) {
217 merge_config_file((*iter
) / "common.conf", config
);
218 merge_config_file((*iter
) / (test_suite_name
+ ".conf"), config
);