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.
33 #include "atf-c/defs.h"
35 #include "atf-c++/config.hpp"
37 #include "atf-c++/detail/env.hpp"
38 #include "atf-c++/detail/fs.hpp"
39 #include "atf-c++/detail/sanity.hpp"
40 #include "atf-c++/detail/parser.hpp"
44 namespace impl
= atf::atf_run
;
45 namespace detail
= atf::atf_run::detail
;
49 namespace atf_config
{
51 static const atf::parser::token_type eof_type
= 0;
52 static const atf::parser::token_type nl_type
= 1;
53 static const atf::parser::token_type text_type
= 2;
54 static const atf::parser::token_type dblquote_type
= 3;
55 static const atf::parser::token_type equal_type
= 4;
56 static const atf::parser::token_type hash_type
= 5;
58 class tokenizer
: public atf::parser::tokenizer
< std::istream
> {
60 tokenizer(std::istream
& is
, size_t curline
) :
61 atf::parser::tokenizer
< std::istream
>
62 (is
, true, eof_type
, nl_type
, text_type
, curline
)
64 add_delim('=', equal_type
);
65 add_delim('#', hash_type
);
66 add_quote('"', dblquote_type
);
70 } // namespace atf_config
72 class config_reader
: public detail::atf_config_reader
{
73 atf::tests::vars_map m_vars
;
76 got_var(const std::string
& var
, const std::string
& name
)
82 config_reader(std::istream
& is
) :
87 const atf::tests::vars_map
&
95 template< class K
, class V
>
98 merge_maps(std::map
< K
, V
>& dest
, const std::map
< K
, V
>& src
)
100 for (typename
std::map
< K
, V
>::const_iterator iter
= src
.begin();
101 iter
!= src
.end(); iter
++)
102 dest
[(*iter
).first
] = (*iter
).second
;
107 merge_config_file(const atf::fs::path
& config_path
,
108 atf::tests::vars_map
& config
)
110 std::ifstream
is(config_path
.c_str());
112 config_reader
reader(is
);
114 merge_maps(config
, reader
.get_vars());
119 std::vector
< atf::fs::path
>
120 get_config_dirs(void)
122 std::vector
< atf::fs::path
> dirs
;
123 dirs
.push_back(atf::fs::path(atf::config::get("atf_confdir")));
124 if (atf::env::has("HOME"))
125 dirs
.push_back(atf::fs::path(atf::env::get("HOME")) / ".atf");
129 } // anonymous namespace
131 detail::atf_config_reader::atf_config_reader(std::istream
& is
) :
136 detail::atf_config_reader::~atf_config_reader(void)
141 detail::atf_config_reader::got_var(
142 const std::string
& var ATF_DEFS_ATTRIBUTE_UNUSED
,
143 const std::string
& val ATF_DEFS_ATTRIBUTE_UNUSED
)
148 detail::atf_config_reader::got_eof(void)
153 detail::atf_config_reader::read(void)
155 using atf::parser::parse_error
;
156 using namespace atf_config
;
158 std::pair
< size_t, atf::parser::headers_map
> hml
=
159 atf::parser::read_headers(m_is
, 1);
160 atf::parser::validate_content_type(hml
.second
,
161 "application/X-atf-config", 1);
163 tokenizer
tkz(m_is
, hml
.first
);
164 atf::parser::parser
< tokenizer
> p(tkz
);
168 atf::parser::token t
= p
.expect(eof_type
, hash_type
, text_type
,
170 "eof, #, new line or text");
171 if (t
.type() == eof_type
)
174 if (t
.type() == hash_type
) {
175 (void)p
.rest_of_line();
176 t
= p
.expect(nl_type
, "new line");
177 } else if (t
.type() == text_type
) {
178 std::string name
= t
.text();
180 t
= p
.expect(equal_type
, "equal sign");
182 t
= p
.expect(text_type
, "word or quoted string");
183 ATF_PARSER_CALLBACK(p
, got_var(name
, t
.text()));
185 t
= p
.expect(nl_type
, hash_type
, "new line or comment");
186 if (t
.type() == hash_type
) {
187 (void)p
.rest_of_line();
188 t
= p
.expect(nl_type
, "new line");
190 } else if (t
.type() == nl_type
) {
193 } catch (const parse_error
& pe
) {
199 ATF_PARSER_CALLBACK(p
, got_eof());
203 impl::merge_configs(const atf::tests::vars_map
& lower
,
204 const atf::tests::vars_map
& upper
)
206 atf::tests::vars_map merged
= lower
;
207 merge_maps(merged
, upper
);
212 impl::read_config_files(const std::string
& test_suite_name
)
214 atf::tests::vars_map config
;
216 const std::vector
< atf::fs::path
> dirs
= get_config_dirs();
217 for (std::vector
< atf::fs::path
>::const_iterator iter
= dirs
.begin();
218 iter
!= dirs
.end(); iter
++) {
219 merge_config_file((*iter
) / "common.conf", config
);
220 merge_config_file((*iter
) / (test_suite_name
+ ".conf"), config
);