config_file.cpp revision 1.1 1 1.1 jmmv //
2 1.1 jmmv // Automated Testing Framework (atf)
3 1.1 jmmv //
4 1.1 jmmv // Copyright (c) 2007 The NetBSD Foundation, Inc.
5 1.1 jmmv // All rights reserved.
6 1.1 jmmv //
7 1.1 jmmv // Redistribution and use in source and binary forms, with or without
8 1.1 jmmv // modification, are permitted provided that the following conditions
9 1.1 jmmv // are met:
10 1.1 jmmv // 1. Redistributions of source code must retain the above copyright
11 1.1 jmmv // notice, this list of conditions and the following disclaimer.
12 1.1 jmmv // 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmmv // notice, this list of conditions and the following disclaimer in the
14 1.1 jmmv // documentation and/or other materials provided with the distribution.
15 1.1 jmmv //
16 1.1 jmmv // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 1.1 jmmv // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 1.1 jmmv // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 1.1 jmmv // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.1 jmmv // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 1.1 jmmv // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 jmmv // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 1.1 jmmv // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 1.1 jmmv // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 1.1 jmmv // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 1.1 jmmv // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 1.1 jmmv // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 jmmv //
29 1.1 jmmv
30 1.1 jmmv #include <cstdlib>
31 1.1 jmmv #include <fstream>
32 1.1 jmmv #include <vector>
33 1.1 jmmv
34 1.1 jmmv #include "config.hpp"
35 1.1 jmmv #include "config_file.hpp"
36 1.1 jmmv #include "defs.hpp"
37 1.1 jmmv #include "env.hpp"
38 1.1 jmmv #include "fs.hpp"
39 1.1 jmmv #include "parser.hpp"
40 1.1 jmmv
41 1.1 jmmv namespace impl = tools::config_file;
42 1.1 jmmv namespace detail = tools::config_file::detail;
43 1.1 jmmv
44 1.1 jmmv namespace {
45 1.1 jmmv
46 1.1 jmmv typedef std::map< std::string, std::string > vars_map;
47 1.1 jmmv
48 1.1 jmmv namespace atf_config {
49 1.1 jmmv
50 1.1 jmmv static const tools::parser::token_type eof_type = 0;
51 1.1 jmmv static const tools::parser::token_type nl_type = 1;
52 1.1 jmmv static const tools::parser::token_type text_type = 2;
53 1.1 jmmv static const tools::parser::token_type dblquote_type = 3;
54 1.1 jmmv static const tools::parser::token_type equal_type = 4;
55 1.1 jmmv static const tools::parser::token_type hash_type = 5;
56 1.1 jmmv
57 1.1 jmmv class tokenizer : public tools::parser::tokenizer< std::istream > {
58 1.1 jmmv public:
59 1.1 jmmv tokenizer(std::istream& is, size_t curline) :
60 1.1 jmmv tools::parser::tokenizer< std::istream >
61 1.1 jmmv (is, true, eof_type, nl_type, text_type, curline)
62 1.1 jmmv {
63 1.1 jmmv add_delim('=', equal_type);
64 1.1 jmmv add_delim('#', hash_type);
65 1.1 jmmv add_quote('"', dblquote_type);
66 1.1 jmmv }
67 1.1 jmmv };
68 1.1 jmmv
69 1.1 jmmv } // namespace atf_config
70 1.1 jmmv
71 1.1 jmmv class config_reader : public detail::atf_config_reader {
72 1.1 jmmv vars_map m_vars;
73 1.1 jmmv
74 1.1 jmmv void
75 1.1 jmmv got_var(const std::string& var, const std::string& name)
76 1.1 jmmv {
77 1.1 jmmv m_vars[var] = name;
78 1.1 jmmv }
79 1.1 jmmv
80 1.1 jmmv public:
81 1.1 jmmv config_reader(std::istream& is) :
82 1.1 jmmv atf_config_reader(is)
83 1.1 jmmv {
84 1.1 jmmv }
85 1.1 jmmv
86 1.1 jmmv const vars_map&
87 1.1 jmmv get_vars(void)
88 1.1 jmmv const
89 1.1 jmmv {
90 1.1 jmmv return m_vars;
91 1.1 jmmv }
92 1.1 jmmv };
93 1.1 jmmv
94 1.1 jmmv template< class K, class V >
95 1.1 jmmv static
96 1.1 jmmv void
97 1.1 jmmv merge_maps(std::map< K, V >& dest, const std::map< K, V >& src)
98 1.1 jmmv {
99 1.1 jmmv for (typename std::map< K, V >::const_iterator iter = src.begin();
100 1.1 jmmv iter != src.end(); iter++)
101 1.1 jmmv dest[(*iter).first] = (*iter).second;
102 1.1 jmmv }
103 1.1 jmmv
104 1.1 jmmv static
105 1.1 jmmv void
106 1.1 jmmv merge_config_file(const tools::fs::path& config_path,
107 1.1 jmmv vars_map& config)
108 1.1 jmmv {
109 1.1 jmmv std::ifstream is(config_path.c_str());
110 1.1 jmmv if (is) {
111 1.1 jmmv config_reader reader(is);
112 1.1 jmmv reader.read();
113 1.1 jmmv merge_maps(config, reader.get_vars());
114 1.1 jmmv }
115 1.1 jmmv }
116 1.1 jmmv
117 1.1 jmmv static
118 1.1 jmmv std::vector< tools::fs::path >
119 1.1 jmmv get_config_dirs(void)
120 1.1 jmmv {
121 1.1 jmmv std::vector< tools::fs::path > dirs;
122 1.1 jmmv dirs.push_back(tools::fs::path(tools::config::get("atf_confdir")));
123 1.1 jmmv if (tools::env::has("HOME"))
124 1.1 jmmv dirs.push_back(tools::fs::path(tools::env::get("HOME")) / ".atf");
125 1.1 jmmv return dirs;
126 1.1 jmmv }
127 1.1 jmmv
128 1.1 jmmv } // anonymous namespace
129 1.1 jmmv
130 1.1 jmmv detail::atf_config_reader::atf_config_reader(std::istream& is) :
131 1.1 jmmv m_is(is)
132 1.1 jmmv {
133 1.1 jmmv }
134 1.1 jmmv
135 1.1 jmmv detail::atf_config_reader::~atf_config_reader(void)
136 1.1 jmmv {
137 1.1 jmmv }
138 1.1 jmmv
139 1.1 jmmv void
140 1.1 jmmv detail::atf_config_reader::got_var(
141 1.1 jmmv const std::string& var ATF_DEFS_ATTRIBUTE_UNUSED,
142 1.1 jmmv const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED)
143 1.1 jmmv {
144 1.1 jmmv }
145 1.1 jmmv
146 1.1 jmmv void
147 1.1 jmmv detail::atf_config_reader::got_eof(void)
148 1.1 jmmv {
149 1.1 jmmv }
150 1.1 jmmv
151 1.1 jmmv void
152 1.1 jmmv detail::atf_config_reader::read(void)
153 1.1 jmmv {
154 1.1 jmmv using tools::parser::parse_error;
155 1.1 jmmv using namespace atf_config;
156 1.1 jmmv
157 1.1 jmmv std::pair< size_t, tools::parser::headers_map > hml =
158 1.1 jmmv tools::parser::read_headers(m_is, 1);
159 1.1 jmmv tools::parser::validate_content_type(hml.second,
160 1.1 jmmv "application/X-atf-config", 1);
161 1.1 jmmv
162 1.1 jmmv tokenizer tkz(m_is, hml.first);
163 1.1 jmmv tools::parser::parser< tokenizer > p(tkz);
164 1.1 jmmv
165 1.1 jmmv for (;;) {
166 1.1 jmmv try {
167 1.1 jmmv tools::parser::token t = p.expect(eof_type, hash_type, text_type,
168 1.1 jmmv nl_type,
169 1.1 jmmv "eof, #, new line or text");
170 1.1 jmmv if (t.type() == eof_type)
171 1.1 jmmv break;
172 1.1 jmmv
173 1.1 jmmv if (t.type() == hash_type) {
174 1.1 jmmv (void)p.rest_of_line();
175 1.1 jmmv t = p.expect(nl_type, "new line");
176 1.1 jmmv } else if (t.type() == text_type) {
177 1.1 jmmv std::string name = t.text();
178 1.1 jmmv
179 1.1 jmmv t = p.expect(equal_type, "equal sign");
180 1.1 jmmv
181 1.1 jmmv t = p.expect(text_type, "word or quoted string");
182 1.1 jmmv ATF_PARSER_CALLBACK(p, got_var(name, t.text()));
183 1.1 jmmv
184 1.1 jmmv t = p.expect(nl_type, hash_type, "new line or comment");
185 1.1 jmmv if (t.type() == hash_type) {
186 1.1 jmmv (void)p.rest_of_line();
187 1.1 jmmv t = p.expect(nl_type, "new line");
188 1.1 jmmv }
189 1.1 jmmv } else if (t.type() == nl_type) {
190 1.1 jmmv } else
191 1.1 jmmv std::abort();
192 1.1 jmmv } catch (const parse_error& pe) {
193 1.1 jmmv p.add_error(pe);
194 1.1 jmmv p.reset(nl_type);
195 1.1 jmmv }
196 1.1 jmmv }
197 1.1 jmmv
198 1.1 jmmv ATF_PARSER_CALLBACK(p, got_eof());
199 1.1 jmmv }
200 1.1 jmmv
201 1.1 jmmv vars_map
202 1.1 jmmv impl::merge_configs(const vars_map& lower,
203 1.1 jmmv const vars_map& upper)
204 1.1 jmmv {
205 1.1 jmmv vars_map merged = lower;
206 1.1 jmmv merge_maps(merged, upper);
207 1.1 jmmv return merged;
208 1.1 jmmv }
209 1.1 jmmv
210 1.1 jmmv vars_map
211 1.1 jmmv impl::read_config_files(const std::string& test_suite_name)
212 1.1 jmmv {
213 1.1 jmmv vars_map config;
214 1.1 jmmv
215 1.1 jmmv const std::vector< tools::fs::path > dirs = get_config_dirs();
216 1.1 jmmv for (std::vector< tools::fs::path >::const_iterator iter = dirs.begin();
217 1.1 jmmv iter != dirs.end(); iter++) {
218 1.1 jmmv merge_config_file((*iter) / "common.conf", config);
219 1.1 jmmv merge_config_file((*iter) / (test_suite_name + ".conf"), config);
220 1.1 jmmv }
221 1.1 jmmv
222 1.1 jmmv return config;
223 1.1 jmmv }
224