]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // doxml2qbk (developed in the context of Boost.Geometry documentation) |
2 | // | |
3 | // Copyright (c) 2010-2013 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | // Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland. | |
5 | // Use, modification and distribution is subject to the Boost Software License, | |
6 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | // | |
9 | // | |
10 | // Barend Gehrels, Aug 1, 2010 | |
11 | // In continuation of the QuickBook documentation of Boost.Geometry | |
12 | // | |
13 | // Converts XML files created by Doxygen to Quickbook | |
14 | // Notes: | |
15 | // - basically generic, but implemented with Boost.Geometry in mind | |
16 | // - makes use of some specific XML elements, which can be created by Doxygen | |
17 | // using /xmlonly | |
18 | // currently this is the element <qbk.example> which will make a reference | |
19 | // to an example. | |
20 | // - currently still in draft | |
21 | ||
22 | #include <iostream> | |
23 | #include <fstream> | |
24 | #include <sstream> | |
25 | #include <vector> | |
26 | #include <map> | |
27 | ||
28 | #include <boost/foreach.hpp> | |
29 | #include <boost/algorithm/string.hpp> | |
30 | #include <boost/algorithm/string/split.hpp> | |
31 | ||
32 | ||
33 | #include <boost/program_options.hpp> | |
34 | ||
35 | #include <rapidxml.hpp> | |
36 | ||
37 | #include <configuration.hpp> | |
38 | #include <file_to_string.hpp> | |
39 | #include <doxygen_elements.hpp> | |
40 | #include <doxygen_xml_parser.hpp> | |
41 | #include <parameter_predicates.hpp> | |
42 | #include <quickbook_output.hpp> | |
43 | #include <rapidxml_util.hpp> | |
44 | ||
45 | static const std::string version = "1.1.1"; | |
46 | ||
47 | inline std::string program_description(bool decorated) | |
48 | { | |
49 | std::string result; | |
50 | if (decorated) | |
51 | { | |
52 | result = "=== "; | |
53 | } | |
54 | result += "doxygen_xml2qbk "; | |
55 | result += version; | |
56 | if (decorated) | |
57 | { | |
58 | result += " ==="; | |
59 | } | |
60 | return result; | |
61 | } | |
62 | ||
63 | ||
64 | int main(int argc, char** argv) | |
65 | { | |
66 | std::string filename; | |
67 | try | |
68 | { | |
69 | configuration config; | |
70 | std::string copyright_filename; | |
71 | std::string output_style; | |
72 | ||
73 | // Read/get configuration | |
74 | { | |
75 | namespace po = boost::program_options; | |
76 | po::options_description description; | |
77 | ||
78 | std::string convenience_headers; | |
79 | ||
80 | description.add_options() | |
81 | ("help", "Help message") | |
82 | ("version", "Version description") | |
83 | ("xml", po::value<std::string>(&filename), | |
84 | "Name of XML file written by Doxygen") | |
85 | ("start_include", po::value<std::string>(&config.start_include), | |
86 | "Start include") | |
87 | ("convenience_header_path", po::value<std::string>(&config.convenience_header_path), | |
88 | "Convenience header path") | |
89 | ("convenience_headers", po::value<std::string>(&convenience_headers), | |
90 | "Convenience header(s) (comma-separated)") | |
91 | ("skip_namespace", po::value<std::string>(&config.skip_namespace), | |
92 | "Namespace to skip (e.g. boost::mylib::)") | |
93 | ("copyright", po::value<std::string>(©right_filename), | |
94 | "Name of QBK file including (commented) copyright and license") | |
95 | ||
96 | ("output_style", po::value<std::string>(&output_style), | |
97 | "Docbook output style. Available values: 'alt'") | |
98 | ("output_member_variables", po::value<bool>(&config.output_member_variables), | |
99 | "Output member variables inside the class") | |
100 | ; | |
101 | ||
102 | po::variables_map varmap; | |
103 | ||
104 | if (argc == 2 && ! boost::starts_with(argv[1], "--")) | |
105 | { | |
106 | // (especially for debugging) options might go into an INI file | |
107 | std::ifstream config_file (argv[1], std::ifstream::in); | |
108 | po::store(po::parse_config_file(config_file, description), varmap); | |
109 | } | |
110 | else | |
111 | { | |
112 | po::store(po::parse_command_line(argc, argv, description), varmap); | |
113 | } | |
114 | ||
115 | po::notify(varmap); | |
116 | ||
117 | if (varmap.count("version")) | |
118 | { | |
119 | std::cout << version << std::endl; | |
120 | return 0; | |
121 | } | |
122 | else if (varmap.count("help")) | |
123 | { | |
124 | std::cout | |
125 | << program_description(true) << std::endl | |
126 | << "Available options:" << std::endl | |
127 | << description << std::endl; | |
128 | return 0; | |
129 | } | |
130 | else if (filename.empty()) | |
131 | { | |
132 | std::cout | |
133 | << program_description(true) << std::endl | |
134 | << "Allowed options:" << std::endl | |
135 | << description << std::endl; | |
136 | return 1; | |
137 | } | |
138 | ||
139 | // Split CSV with headerfile names into configuration | |
140 | if (! convenience_headers.empty()) | |
141 | { | |
142 | boost::split(config.convenience_headers, convenience_headers, boost::is_any_of(",")); | |
143 | } | |
144 | } | |
145 | ||
146 | // Set output style | |
147 | if ("alt" == output_style) | |
148 | { | |
149 | config.output_style = configuration::alt; | |
150 | } | |
151 | ||
152 | // Read files into strings | |
153 | std::string xml_string = file_to_string(filename); | |
154 | std::string license = copyright_filename.empty() | |
155 | ? "" | |
156 | : file_to_string(copyright_filename); | |
157 | ||
158 | // Parse the XML outputted by Doxygen | |
159 | xml_doc xml(xml_string.c_str()); | |
160 | ||
161 | documentation doc; | |
162 | parse(xml.first_node(), config, doc); | |
163 | ||
164 | // Check for duplicate function names | |
165 | for (std::size_t i = 0; i < doc.functions.size(); i++) | |
166 | { | |
167 | function& f1 = doc.functions[i]; | |
168 | for (std::size_t j = i + 1; j < doc.functions.size(); j++) | |
169 | { | |
170 | function& f2 = doc.functions[j]; | |
171 | ||
172 | if (f1.name == f2.name) | |
173 | { | |
174 | // It is not a unique function, so e.g. an overload, | |
175 | // so a description must distinguish them. | |
176 | // Difference is either the number of parameters, or a const / non-const version | |
177 | // Use the "\qbk{distinguish,with strategy}" in the source code to distinguish | |
178 | f1.unique = false; | |
179 | f2.unique = false; | |
180 | } | |
181 | } | |
182 | } | |
183 | ||
184 | ||
185 | // Write copyright/license (keep inspect silent) | |
186 | if (! license.empty()) | |
187 | { | |
188 | std::cout << license << std::endl; | |
189 | } | |
190 | ||
191 | // Write warning comment | |
192 | std::cout | |
193 | << "[/ Generated by " << program_description(false) << ", don't change, will be overwritten automatically]" << std::endl | |
194 | << "[/ Generated from " << filename << "]" << std::endl; | |
195 | ||
196 | if ( configuration::def == config.output_style ) | |
197 | { | |
198 | // Write the rest: functions, defines, classes or structs | |
199 | BOOST_FOREACH(function const& f, doc.functions) | |
200 | { | |
201 | quickbook_output(f, config, std::cout); | |
202 | } | |
203 | BOOST_FOREACH(function const& f, doc.defines) | |
204 | { | |
205 | quickbook_output(f, config, std::cout); | |
206 | } | |
207 | BOOST_FOREACH(enumeration const& e, doc.enumerations) | |
208 | { | |
209 | quickbook_output(e, config, std::cout); | |
210 | } | |
211 | ||
212 | if (! doc.cos.name.empty()) | |
213 | { | |
214 | std::sort(doc.cos.functions.begin(), doc.cos.functions.end(), sort_on_line<function>()); | |
215 | quickbook_output(doc.cos, config, std::cout); | |
216 | } | |
217 | } | |
218 | else if ( configuration::alt == config.output_style ) | |
219 | { | |
220 | if (! doc.cos.name.empty()) | |
221 | { | |
222 | std::sort(doc.cos.functions.begin(), doc.cos.functions.end(), sort_on_line<function>()); | |
223 | quickbook_output_alt(doc.cos, config, std::cout); | |
224 | } | |
225 | ||
226 | if (! doc.group_id.empty()) | |
227 | { | |
228 | quickbook_output_alt(doc, config, std::cout); | |
229 | } | |
230 | } | |
231 | } | |
232 | catch(std::exception const& e) | |
233 | { | |
234 | std::cerr << "Exception in doxygen_xml2qbk: " << std::endl | |
235 | << " Message: " << e.what() << std::endl | |
236 | << " File: " << filename << std::endl | |
237 | << " Type: " << typeid(e).name() << std::endl | |
238 | << std::endl; | |
239 | return 1; | |
240 | } | |
241 | catch(...) | |
242 | { | |
243 | std::cerr << "Unknown exception in doxygen_xml2qbk" | |
244 | << std::endl; | |
245 | return 1; | |
246 | } | |
247 | return 0; | |
248 | } | |
249 |