1 // doxml2qbk (developed in the context of Boost.Geometry documentation)
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)
10 // Barend Gehrels, Aug 1, 2010
11 // In continuation of the QuickBook documentation of Boost.Geometry
13 // Converts XML files created by Doxygen to Quickbook
15 // - basically generic, but implemented with Boost.Geometry in mind
16 // - makes use of some specific XML elements, which can be created by Doxygen
18 // currently this is the element <qbk.example> which will make a reference
20 // - currently still in draft
28 #include <boost/foreach.hpp>
29 #include <boost/algorithm/string.hpp>
30 #include <boost/algorithm/string/split.hpp>
33 #include <boost/program_options.hpp>
35 #include <rapidxml.hpp>
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>
45 static const std::string version
= "1.1.1";
47 inline std::string
program_description(bool decorated
)
54 result
+= "doxygen_xml2qbk ";
64 int main(int argc
, char** argv
)
70 std::string copyright_filename
;
71 std::string output_style
;
73 // Read/get configuration
75 namespace po
= boost::program_options
;
76 po::options_description description
;
78 std::string convenience_headers
;
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
),
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")
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")
102 po::variables_map varmap
;
104 if (argc
== 2 && ! boost::starts_with(argv
[1], "--"))
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
);
112 po::store(po::parse_command_line(argc
, argv
, description
), varmap
);
117 if (varmap
.count("version"))
119 std::cout
<< version
<< std::endl
;
122 else if (varmap
.count("help"))
125 << program_description(true) << std::endl
126 << "Available options:" << std::endl
127 << description
<< std::endl
;
130 else if (filename
.empty())
133 << program_description(true) << std::endl
134 << "Allowed options:" << std::endl
135 << description
<< std::endl
;
139 // Split CSV with headerfile names into configuration
140 if (! convenience_headers
.empty())
142 boost::split(config
.convenience_headers
, convenience_headers
, boost::is_any_of(","));
147 if ("alt" == output_style
)
149 config
.output_style
= configuration::alt
;
152 // Read files into strings
153 std::string xml_string
= file_to_string(filename
);
154 std::string license
= copyright_filename
.empty()
156 : file_to_string(copyright_filename
);
158 // Parse the XML outputted by Doxygen
159 xml_doc
xml(xml_string
.c_str());
162 parse(xml
.first_node(), config
, doc
);
164 // Check for duplicate function names
165 for (std::size_t i
= 0; i
< doc
.functions
.size(); i
++)
167 function
& f1
= doc
.functions
[i
];
168 for (std::size_t j
= i
+ 1; j
< doc
.functions
.size(); j
++)
170 function
& f2
= doc
.functions
[j
];
172 if (f1
.name
== f2
.name
)
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
185 // Write copyright/license (keep inspect silent)
186 if (! license
.empty())
188 std::cout
<< license
<< std::endl
;
191 // Write warning comment
193 << "[/ Generated by " << program_description(false) << ", don't change, will be overwritten automatically]" << std::endl
194 << "[/ Generated from " << filename
<< "]" << std::endl
;
196 if ( configuration::def
== config
.output_style
)
198 // Write the rest: functions, defines, classes or structs
199 BOOST_FOREACH(function
const& f
, doc
.functions
)
201 quickbook_output(f
, config
, std::cout
);
203 BOOST_FOREACH(function
const& f
, doc
.defines
)
205 quickbook_output(f
, config
, std::cout
);
207 BOOST_FOREACH(enumeration
const& e
, doc
.enumerations
)
209 quickbook_output(e
, config
, std::cout
);
212 if (! doc
.cos
.name
.empty())
214 std::sort(doc
.cos
.functions
.begin(), doc
.cos
.functions
.end(), sort_on_line
<function
>());
215 quickbook_output(doc
.cos
, config
, std::cout
);
218 else if ( configuration::alt
== config
.output_style
)
220 if (! doc
.cos
.name
.empty())
222 std::sort(doc
.cos
.functions
.begin(), doc
.cos
.functions
.end(), sort_on_line
<function
>());
223 quickbook_output_alt(doc
.cos
, config
, std::cout
);
226 if (! doc
.group_id
.empty())
228 quickbook_output_alt(doc
, config
, std::cout
);
232 catch(std::exception
const& e
)
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
243 std::cerr
<< "Unknown exception in doxygen_xml2qbk"