aboutsummaryrefslogtreecommitdiff
path: root/xsde/cxx/hybrid/generator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xsde/cxx/hybrid/generator.cxx')
-rw-r--r--xsde/cxx/hybrid/generator.cxx2476
1 files changed, 2476 insertions, 0 deletions
diff --git a/xsde/cxx/hybrid/generator.cxx b/xsde/cxx/hybrid/generator.cxx
new file mode 100644
index 0000000..b6215f9
--- /dev/null
+++ b/xsde/cxx/hybrid/generator.cxx
@@ -0,0 +1,2476 @@
+// file : xsde/cxx/hybrid/generator.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2005-2009 Code Synthesis Tools CC
+// license : GNU GPL v2 + exceptions; see accompanying LICENSE file
+
+#include <cxx/hybrid/elements.hxx>
+#include <cxx/hybrid/generator.hxx>
+
+#include <cxx/hybrid/validator.hxx>
+
+#include <cxx/hybrid/tree-size-processor.hxx>
+#include <cxx/hybrid/tree-name-processor.hxx>
+
+
+#include <cxx/hybrid/tree-forward.hxx>
+#include <cxx/hybrid/tree-header.hxx>
+#include <cxx/hybrid/tree-inline.hxx>
+#include <cxx/hybrid/tree-source.hxx>
+#include <cxx/hybrid/tree-type-map.hxx>
+
+#include <cxx/hybrid/parser-name-processor.hxx>
+#include <cxx/hybrid/parser-header.hxx>
+#include <cxx/hybrid/parser-source.hxx>
+#include <cxx/hybrid/parser-aggregate-header.hxx>
+#include <cxx/hybrid/parser-aggregate-source.hxx>
+
+#include <cxx/hybrid/serializer-name-processor.hxx>
+#include <cxx/hybrid/serializer-header.hxx>
+#include <cxx/hybrid/serializer-source.hxx>
+#include <cxx/hybrid/serializer-aggregate-header.hxx>
+#include <cxx/hybrid/serializer-aggregate-source.hxx>
+
+#include <xsd-frontend/semantic-graph.hxx>
+
+#include <backend-elements/regex.hxx>
+#include <backend-elements/indentation/cxx.hxx>
+#include <backend-elements/indentation/sloc.hxx>
+#include <backend-elements/indentation/clip.hxx>
+
+#include <cult/containers/set.hxx>
+#include <cult/containers/vector.hxx>
+
+#include <boost/filesystem/fstream.hpp>
+
+#include <iostream>
+
+#include <usage.hxx>
+
+#include "../../../libxsde/xsde/cxx/version.hxx"
+
+using std::endl;
+using std::wcerr;
+
+using namespace XSDFrontend::SemanticGraph;
+
+//
+//
+typedef
+boost::filesystem::wifstream
+WideInputFileStream;
+
+typedef
+boost::filesystem::wofstream
+WideOutputFileStream;
+
+typedef
+boost::filesystem::ifstream
+NarrowInputFileStream;
+
+namespace CXX
+{
+ namespace
+ {
+ Char const copyright_gpl[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD/e, an XML Schema\n"
+ "// to C++ data binding compiler for embedded systems.\n"
+ "//\n"
+ "// This program is free software; you can redistribute it and/or modify\n"
+ "// it under the terms of the GNU General Public License version 2 as\n"
+ "// published by the Free Software Foundation.\n"
+ "//\n"
+ "// This program is distributed in the hope that it will be useful,\n"
+ "// but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "// GNU General Public License for more details.\n"
+ "//\n"
+ "// You should have received a copy of the GNU General Public License\n"
+ "// along with this program; if not, write to the Free Software\n"
+ "// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
+ "//\n"
+ "//\n\n";
+
+ Char const copyright_proprietary[] =
+ "// Copyright (C) 2005-2009 Code Synthesis Tools CC\n"
+ "//\n"
+ "// This program was generated by CodeSynthesis XSD/e, an XML Schema to\n"
+ "// C++ data binding compiler for embedded systems, in the Proprietary\n"
+ "// License mode. You should have received a proprietary license from\n"
+ "// Code Synthesis Tools CC prior to generating this code. See the\n"
+ "// license text for conditions.\n"
+ "//\n\n";
+ }
+
+ namespace Hybrid
+ {
+ namespace CLI
+ {
+ extern Key no_stl = "no-stl";
+ extern Key no_iostream = "no-iostream";
+ extern Key no_exceptions = "no-exceptions";
+ extern Key no_long_long = "no-long-long";
+ extern Key generate_parser = "generate-parser";
+ extern Key generate_serializer = "generate-serializer";
+ extern Key generate_aggregate = "generate-aggregate";
+ extern Key suppress_validation = "suppress-validation";
+ extern Key suppress_parser_val = "suppress-parser-val";
+ extern Key suppress_serializer_val = "suppress-serializer-val";
+ extern Key generate_inline = "generate-inline";
+ extern Key generate_forward = "generate-forward";
+ extern Key generate_xml_schema = "generate-xml-schema";
+ extern Key extern_xml_schema = "extern-xml-schema";
+ extern Key suppress_reset = "suppress-reset";
+ extern Key reuse_style_mixin = "reuse-style-mixin";
+ extern Key custom_data = "custom-data";
+ extern Key custom_parser = "custom-parser";
+ extern Key custom_serializer = "custom-serializer";
+ extern Key root_element_first = "root-element-first";
+ extern Key root_element_last = "root-element-last";
+ extern Key root_element_all = "root-element-all";
+ extern Key root_element_none = "root-element-none";
+ extern Key root_element = "root-element";
+ extern Key root_type = "root-type";
+ extern Key output_dir = "output-dir";
+ extern Key pskel_type_suffix = "pskel-type-suffix";
+ extern Key sskel_type_suffix = "sskel-type-suffix";
+ extern Key pskel_file_suffix = "pskel-file-suffix";
+ extern Key sskel_file_suffix = "sskel-file-suffix";
+ extern Key pimpl_type_suffix = "pimpl-type-suffix";
+ extern Key simpl_type_suffix = "simpl-type-suffix";
+ extern Key pimpl_file_suffix = "pimpl-file-suffix";
+ extern Key simpl_file_suffix = "simpl-file-suffix";
+ extern Key paggr_type_suffix = "paggr-type-suffix";
+ extern Key saggr_type_suffix = "saggr-type-suffix";
+ extern Key namespace_map = "namespace-map";
+ extern Key namespace_regex = "namespace-regex";
+ extern Key namespace_regex_trace = "namespace-regex-trace";
+ extern Key reserved_name = "reserved-name";
+ extern Key include_with_brackets = "include-with-brackets";
+ extern Key include_prefix = "include-prefix";
+ extern Key include_regex = "include-regex";
+ extern Key include_regex_trace = "include-regex-trace";
+ extern Key guard_prefix = "guard-prefix";
+ extern Key hxx_suffix = "hxx-suffix";
+ extern Key ixx_suffix = "ixx-suffix";
+ extern Key cxx_suffix = "cxx-suffix";
+ extern Key fwd_suffix = "fwd-suffix";
+ extern Key hxx_regex = "hxx-regex";
+ extern Key ixx_regex = "ixx-regex";
+ extern Key cxx_regex = "cxx-regex";
+ extern Key fwd_regex = "fwd-regex";
+ extern Key hxx_prologue = "hxx-prologue";
+ extern Key ixx_prologue = "ixx-prologue";
+ extern Key cxx_prologue = "cxx-prologue";
+ extern Key fwd_prologue = "fwd-prologue";
+ extern Key prologue = "prologue";
+ extern Key hxx_epilogue = "hxx-epilogue";
+ extern Key ixx_epilogue = "ixx-epilogue";
+ extern Key cxx_epilogue = "cxx-epilogue";
+ extern Key fwd_epilogue = "fwd-epilogue";
+ extern Key epilogue = "epilogue";
+ extern Key hxx_prologue_file = "hxx-prologue-file";
+ extern Key ixx_prologue_file = "ixx-prologue-file";
+ extern Key cxx_prologue_file = "cxx-prologue-file";
+ extern Key fwd_prologue_file = "fwd-prologue-file";
+ extern Key prologue_file = "prologue-file";
+ extern Key hxx_epilogue_file = "hxx-epilogue-file";
+ extern Key ixx_epilogue_file = "ixx-epilogue-file";
+ extern Key cxx_epilogue_file = "cxx-epilogue-file";
+ extern Key fwd_epilogue_file = "fwd-epilogue-file";
+ extern Key epilogue_file = "epilogue-file";
+ extern Key show_anonymous = "show-anonymous";
+ extern Key show_sloc = "show-sloc";
+ extern Key proprietary_license = "proprietary-license";
+ }
+ }
+
+ Void Hybrid::Generator::
+ usage ()
+ {
+ std::wostream& e (wcerr);
+ ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e);
+
+ e << "--no-stl" << endl
+ << " Generate code that does not use STL."
+ << endl;
+
+ e << "--no-iostream" << endl
+ << " Generate code that does not use the iostream\n"
+ << " library."
+ << endl;
+
+ e << "--no-exceptions" << endl
+ << " Generate code that does not use C++ exceptions."
+ << endl;
+
+ e << "--no-long-long" << endl
+ << " Generate code that does not use the long long\n"
+ << " and unsigned long long types."
+ << endl;
+
+ e << "--generate-parser" << endl
+ << " Generate XML parsing code."
+ << endl;
+
+ e << "--generate-serializer" << endl
+ << " Generate XML serialization code."
+ << endl;
+
+ e << "--generate-aggregate" << endl
+ << " Generate parser/serializer aggregates for root\n"
+ << " elements and/or types."
+ << endl;
+
+ e << "--suppress-validation" << endl
+ << " Suppress the generation of validation code in\n"
+ << " parser and serializer."
+ << endl;
+
+ e << "--suppress-parser-val" << endl
+ << " Suppress the generation of validation code in\n"
+ << " parser."
+ << endl;
+
+ e << "--suppress-serializer-val" << endl
+ << " Suppress the generation of validation code in\n"
+ << " serializer."
+ << endl;
+
+ e << "--generate-inline" << endl
+ << " Generate certain functions inline."
+ << endl;
+
+ e << "--generate-forward" << endl
+ << " Generate forward declaration file."
+ << endl;
+
+ e << "--generate-xml-schema" << endl
+ << " Generate C++ header files as if the schema being\n"
+ << " compiled defines the XML Schema namespace."
+ << endl;
+
+ e << "--extern-xml-schema <file>" << endl
+ << " Generate code as if the XML Schema namespace was\n"
+ << " defined in <file> and xsd:included in the schema\n"
+ << " being compiled."
+ << endl;
+
+ e << "--suppress-reset" << endl
+ << " Suppress the generation of parser and serializer\n"
+ << " reset code."
+ << endl;
+
+ e << "--reuse-style-mixin" << endl
+ << " Generate code that supports the mixin base\n"
+ << " parser/serializer implementation reuse style."
+ << endl;
+
+ e << "--custom-data <type>" << endl
+ << " Add custom data to the C++ class generated for\n"
+ << " XML Schema type <type>."
+ << endl;
+
+ e << "--custom-parser <map>" << endl
+ << " Use a custom parser implementation instead of the\n"
+ << " generated version. The <map> argument is in the\n"
+ << " form type[=base[/include]], where <type> is an XML\n"
+ << " Schema type name, optional <base> is a C++ name\n"
+ << " that should be given to the generated version,\n"
+ << " and optional <include> is the header file that\n"
+ << " defines the custom implementation."
+ << endl;
+
+ e << "--custom-serializer <map>" << endl
+ << " Use a custom serializer implementation instead of\n"
+ << " the generated version. The <map> argument is in\n"
+ << " the form type[=base[/include]], where <type> is\n"
+ << " an XML Schema type name, optional <base> is a C++\n"
+ << " name that should be given to the generated\n"
+ << " version, and optional <include> is the header\n"
+ << " file that defines the custom implementation."
+ << endl;
+
+ e << "--root-element-first" << endl
+ << " Treat only the first global element as a document\n"
+ << " root."
+ << endl;
+
+ e << "--root-element-last" << endl
+ << " Treat only the last global element as a document\n"
+ << " root."
+ << endl;
+
+ e << "--root-element-all" << endl
+ << " Treat all global elements as document roots."
+ << endl;
+
+ e << "--root-element-none" << endl
+ << " Don't treat any global elements as document roots."
+ << endl;
+
+ e << "--root-element <element>" << endl
+ << " Treat only <element> as a document root. Repeat\n"
+ << " this option to specify more than one root element."
+ << endl;
+
+ e << "--root-type <type>" << endl
+ << " Generate parser/serializer aggregate for <type>.\n"
+ << " Repeat this option to specify more than one type."
+ << endl;
+
+ e << "--output-dir <dir>" << endl
+ << " Write generated files to <dir> instead of the\n"
+ << " current directory."
+ << endl;
+
+ e << "--pskel-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_pskel' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " skeletons."
+ << endl;
+
+ e << "--sskel-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_sskel' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " skeletons."
+ << endl;
+
+ e << "--pskel-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-pskel' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--sskel-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-sskel' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " skeleton files."
+ << endl;
+
+ e << "--pimpl-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_pimpl' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " implementations."
+ << endl;
+
+ e << "--simpl-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_simpl' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " implementations."
+ << endl;
+
+ e << "--pimpl-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-pimpl' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " implementation files."
+ << endl;
+
+ e << "--simpl-file-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '-simpl' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " implementation files."
+ << endl;
+
+ e << "--paggr-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_paggs' suffix\n"
+ << " to construct the names of generated parser\n"
+ << " aggregates."
+ << endl;
+
+ e << "--saggr-type-suffix <sfx>" << endl
+ << " Use <sfx> instead of the default '_saggr' suffix\n"
+ << " to construct the names of generated serializer\n"
+ << " aggregates."
+ << endl;
+
+ e << "--namespace-map <xns>=<cns>" << endl
+ << " Map XML Schema namespace <xns> to C++ namespace\n"
+ << " <cns>. Repeat this option to specify mapping for\n"
+ << " more than one XML Schema namespace."
+ << endl;
+
+ e << "--namespace-regex <regex>" << endl
+ << " Add <regex> to the list of regular expressions\n"
+ << " used to translate XML Schema namespace names to\n"
+ << " C++ namespace names."
+ << endl;
+
+ e << "--namespace-regex-trace" << endl
+ << " Trace the process of applying regular expressions\n"
+ << " specified with the --namespace-regex option."
+ << endl;
+
+ e << "--reserved-name <name>" << endl
+ << " Add <name> to the list of names that should not\n"
+ << " be used as identifiers. The name can optionally\n"
+ << " be followed by '=' and the replacement name that\n"
+ << " should be used instead."
+ << endl;
+
+ e << "--include-with-brackets" << endl
+ << " Use angle brackets (<>) instead of quotes (\"\") in\n"
+ << " generated #include directives."
+ << endl;
+
+ e << "--include-prefix <prefix>" << endl
+ << " Add <prefix> to generated #include directive\n"
+ << " paths."
+ << endl;
+
+ e << "--include-regex <regex>" << endl
+ << " Add <regex> to the list of regular expressions\n"
+ << " used to transform #include directive paths."
+ << endl;
+
+ e << "--include-regex-trace" << endl
+ << " Trace the process of applying regular expressions\n"
+ << " specified with the --include-regex option."
+ << endl;
+
+ e << "--guard-prefix <prefix>" << endl
+ << " Add <prefix> to generated header inclusion guards."
+ << endl;
+
+ // File suffix.
+ //
+ e << "--hxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.hxx' to\n"
+ << " construct the name of the header files."
+ << endl;
+
+ e << "--ixx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.ixx' to\n"
+ << " construct the name of the inline files."
+ << endl;
+
+ e << "--cxx-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '.cxx' to\n"
+ << " construct the name of the source files."
+ << endl;
+
+ e << "--fwd-suffix <suffix>" << endl
+ << " Use <suffix> instead of the default '-fwd.hxx'\n"
+ << " to construct the name of the forward declaration\n"
+ << " file."
+ << endl;
+
+ // File regex.
+ //
+ e << "--hxx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the header\n"
+ << " files."
+ << endl;
+
+ e << "--ixx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the inline\n"
+ << " files."
+ << endl;
+
+ e << "--cxx-regex <regex>" << endl
+ << " Use <regex> to construct the names of the source\n"
+ << " files."
+ << endl;
+
+ e << "--fwd-regex <regex>" << endl
+ << " Use <regex> to construct the name of the forward\n"
+ << " declaration file."
+ << endl;
+
+
+ // Prologues.
+ //
+ e << "--hxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the header\n"
+ << " files."
+ << endl;
+
+ e << "--ixx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the inline\n"
+ << " files."
+ << endl;
+
+ e << "--cxx-prologue <text>" << endl
+ << " Insert <text> at the beginning of the source\n"
+ << " files."
+ << endl;
+
+ e << "--fwd-prologue <text>" << endl
+ << " Insert <text> at the beginning of the forward\n"
+ << " declaration file."
+ << endl;
+
+ e << "--prologue <text>" << endl
+ << " Insert <text> at the beginning of each generated\n"
+ << " file for which there is no file-specific prologue."
+ << endl;
+
+
+ // Epilogues.
+ //
+ e << "--hxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the header files."
+ << endl;
+
+ e << "--ixx-epilogue <text>" << endl
+ << " Insert <text> at the end of the inline files."
+ << endl;
+
+ e << "--cxx-epilogue <text>" << endl
+ << " Insert <text> at the end of the source files."
+ << endl;
+
+ e << "--fwd-epilogue <text>" << endl
+ << " Insert <text> at the end of the forward\n"
+ << " declaration file."
+ << endl;
+
+ e << "--epilogue <text>" << endl
+ << " Insert <text> at the end of each generated file\n"
+ << " for which there is no file-specific epilogue."
+ << endl;
+
+
+ // Prologue files.
+ //
+ e << "--hxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the header files."
+ << endl;
+
+ e << "--ixx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the inline files."
+ << endl;
+
+ e << "--cxx-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the source files."
+ << endl;
+
+ e << "--fwd-prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of the forward declaration file."
+ << endl;
+
+ e << "--prologue-file <file>" << endl
+ << " Insert the content of the <file> at the beginning\n"
+ << " of each generated file for which there is no file-\n"
+ << " specific prologue file."
+ << endl;
+
+
+ // Epilogue files.
+ //
+ e << "--hxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the header files."
+ << endl;
+
+ e << "--ixx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the inline files."
+ << endl;
+
+ e << "--cxx-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the source files."
+ << endl;
+
+ e << "--fwd-epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " the forward declaration file."
+ << endl;
+
+ e << "--epilogue-file <file>" << endl
+ << " Insert the content of the <file> at the end of\n"
+ << " each generated file for which there is no file-\n"
+ << " specific epilogue file."
+ << endl;
+
+
+ // Misc.
+ //
+ e << "--show-anonymous" << endl
+ << " Show elements and attributes that are of anonymous\n"
+ << " types."
+ << endl;
+
+ e << "--show-sloc" << endl
+ << " Show the number of generated physical source lines\n"
+ << " of code (SLOC)."
+ << endl;
+
+ e << "--sloc-limit <num>" << endl
+ << " Check that the number of generated physical source\n"
+ << " lines of code (SLOC) does not exceed <num>."
+ << endl;
+
+ e << "--options-file <file>" << endl
+ << " Read additional options from <file>. Each option\n"
+ << " should appear on a separate line optionally\n"
+ << " followed by space and an argument."
+ << endl;
+
+ e << "--proprietary-license" << endl
+ << " Indicate that the generated code is licensed under\n"
+ << " a proprietary license instead of the GPL."
+ << endl;
+ }
+
+ Hybrid::CLI::OptionsSpec Hybrid::Generator::
+ options_spec ()
+ {
+ CLI::OptionsSpec spec;
+
+ spec.option<CLI::pskel_file_suffix> ().default_value ("-pskel");
+ spec.option<CLI::sskel_file_suffix> ().default_value ("-sskel");
+ spec.option<CLI::pskel_type_suffix> ().default_value ("_pskel");
+ spec.option<CLI::sskel_type_suffix> ().default_value ("_sskel");
+
+ spec.option<CLI::pimpl_file_suffix> ().default_value ("-pimpl");
+ spec.option<CLI::simpl_file_suffix> ().default_value ("-simpl");
+ spec.option<CLI::pimpl_type_suffix> ().default_value ("_pimpl");
+ spec.option<CLI::simpl_type_suffix> ().default_value ("_simpl");
+
+ spec.option<CLI::paggr_type_suffix> ().default_value ("_paggr");
+ spec.option<CLI::saggr_type_suffix> ().default_value ("_saggr");
+
+ spec.option<CLI::hxx_suffix> ().default_value (".hxx");
+ spec.option<CLI::ixx_suffix> ().default_value (".ixx");
+ spec.option<CLI::cxx_suffix> ().default_value (".cxx");
+ spec.option<CLI::fwd_suffix> ().default_value ("-fwd.hxx");
+
+ return spec;
+ }
+
+ namespace
+ {
+ NarrowString
+ find_value (Cult::Containers::Vector<NarrowString> const& v,
+ Char const* key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Values;
+
+ for (Values::ConstIterator i (v.begin ()), e (v.end ()); i != e; ++i)
+ {
+ Size p (i->find ('='));
+
+ if (p == NarrowString::npos)
+ {
+ if (key[0] != '\0')
+ continue;
+ }
+ else
+ {
+ NarrowString k (*i, 0, p);
+
+ // Unless it is one of the valid keys, assume there is no key.
+ //
+ if (!(k.empty () || k == "*" || k == "pskel" ||
+ k == "pimpl" || k == "sskel" || k == "simpl"))
+ {
+ k.clear ();
+ p = NarrowString::npos;
+ }
+
+ if (k != key && k != "*")
+ continue;
+ }
+
+ return NarrowString (
+ *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos);
+ }
+
+ return NarrowString ();
+ }
+
+ Void
+ copy_values (Cult::Containers::Vector<NarrowString>& dst,
+ Cult::Containers::Vector<NarrowString> const& src,
+ Char const* key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Values;
+
+ for (Values::ConstIterator i (src.begin ()), e (src.end ()); i != e; ++i)
+ {
+ Size p (i->find ('='));
+
+ if (p == NarrowString::npos)
+ {
+ if (key[0] != '\0')
+ continue;
+ }
+ else
+ {
+ NarrowString k (*i, 0, p);
+
+ // Unless it is one of the valid keys, assume there is no key.
+ //
+ if (!(k.empty () || k == "*" || k == "pskel" ||
+ k == "pimpl" || k == "sskel" || k == "simpl"))
+ {
+ k.clear ();
+ p = NarrowString::npos;
+ }
+
+ if (k != key && k != "*")
+ continue;
+ }
+
+ dst.push_back (
+ NarrowString (
+ *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos));
+ }
+ }
+ }
+
+ Parser::CLI::Options* Hybrid::Generator::
+ parser_options (CLI::Options const& h)
+ {
+ namespace H = CLI;
+ namespace P = Parser::CLI;
+
+ Evptr<P::Options> r (new P::Options);
+
+ r->value<P::no_stl> () = h.value<H::no_stl> ();
+ r->value<P::no_iostream> () = h.value<H::no_iostream> ();
+ r->value<P::no_exceptions> () = h.value<H::no_exceptions> ();
+ r->value<P::no_long_long> () = h.value<H::no_long_long> ();
+ r->value<P::reuse_style_mixin> () = h.value<H::reuse_style_mixin> ();
+ r->value<P::reuse_style_none> () = false;
+ r->value<P::generate_inline> () = h.value<H::generate_inline> ();
+ r->value<P::suppress_validation> () = h.value<H::suppress_validation> ()
+ || h.value<H::suppress_parser_val> ();
+ r->value<P::generate_xml_schema> () = h.value<H::generate_xml_schema> ();
+ r->value<P::extern_xml_schema> () = h.value<H::extern_xml_schema> ();
+ r->value<P::suppress_reset> () = h.value<H::suppress_reset> ();
+ r->value<P::output_dir> () = h.value<H::output_dir> ();
+ r->value<P::skel_file_suffix> () = h.value<H::pskel_file_suffix> ();
+ r->value<P::skel_type_suffix> () = h.value<H::pskel_type_suffix> ();
+ r->value<P::impl_type_suffix> () = h.value<H::pimpl_type_suffix> ();
+ r->value<P::namespace_map> () = h.value<H::namespace_map> ();
+ r->value<P::namespace_regex> () = h.value<H::namespace_regex> ();
+ r->value<P::namespace_regex_trace> () = h.value<H::namespace_regex_trace> ();
+ r->value<P::reserved_name> () = h.value<H::reserved_name> ();
+ r->value<P::include_with_brackets> () = h.value<H::include_with_brackets> ();
+ r->value<P::include_prefix> () = h.value<H::include_prefix> ();
+ r->value<P::include_regex> () = h.value<H::include_regex> ();
+ r->value<P::include_regex_trace> () = h.value<H::include_regex_trace> ();
+ r->value<P::guard_prefix> () = h.value<H::guard_prefix> ();
+
+ r->value<P::hxx_suffix> () = h.value<H::hxx_suffix> ();
+ r->value<P::ixx_suffix> () = h.value<H::ixx_suffix> ();
+ r->value<P::cxx_suffix> () = h.value<H::cxx_suffix> ();
+
+ Char const* k = "pskel";
+
+ r->value<P::hxx_regex> () =
+ find_value (h.value<H::hxx_regex> (), k);
+ r->value<P::ixx_regex> () =
+ find_value (h.value<H::ixx_regex> (), k);
+ r->value<P::cxx_regex> () =
+ find_value (h.value<H::cxx_regex> (), k);
+
+ r->value<P::hxx_prologue_file> () = find_value (
+ h.value<H::hxx_prologue_file> (), k);
+ r->value<P::ixx_prologue_file> () = find_value (
+ h.value<H::ixx_prologue_file> (), k);
+ r->value<P::cxx_prologue_file> () = find_value (
+ h.value<H::cxx_prologue_file> (), k);
+ r->value<P::prologue_file> () = find_value (
+ h.value<H::prologue_file> (), k);
+ r->value<P::hxx_epilogue_file> () = find_value (
+ h.value<H::hxx_epilogue_file> (), k);
+ r->value<P::ixx_epilogue_file> () = find_value (
+ h.value<H::ixx_epilogue_file> (), k);
+ r->value<P::cxx_epilogue_file> () = find_value (
+ h.value<H::cxx_epilogue_file> (), k);
+ r->value<P::epilogue_file> () = find_value (
+ h.value<H::epilogue_file> (), k);
+
+ copy_values (r->value<P::hxx_prologue> (), h.value<H::hxx_prologue> (), k);
+ copy_values (r->value<P::ixx_prologue> (), h.value<H::ixx_prologue> (), k);
+ copy_values (r->value<P::cxx_prologue> (), h.value<H::cxx_prologue> (), k);
+ copy_values (r->value<P::prologue> (), h.value<H::prologue> (), k);
+ copy_values (r->value<P::hxx_epilogue> (), h.value<H::hxx_epilogue> (), k);
+ copy_values (r->value<P::ixx_epilogue> (), h.value<H::ixx_epilogue> (), k);
+ copy_values (r->value<P::cxx_epilogue> (), h.value<H::cxx_epilogue> (), k);
+ copy_values (r->value<P::epilogue> (), h.value<H::epilogue> (), k);
+
+ r->value<P::show_sloc> () = h.value<H::show_sloc> ();
+ r->value<P::proprietary_license> () = h.value<H::proprietary_license> ();
+
+ return r.release ();
+ }
+
+ Serializer::CLI::Options* Hybrid::Generator::
+ serializer_options (CLI::Options const& h)
+ {
+ namespace H = CLI;
+ namespace S = Serializer::CLI;
+
+ Evptr<S::Options> r (new S::Options);
+
+ r->value<S::no_stl> () = h.value<H::no_stl> ();
+ r->value<S::no_iostream> () = h.value<H::no_iostream> ();
+ r->value<S::no_exceptions> () = h.value<H::no_exceptions> ();
+ r->value<S::no_long_long> () = h.value<H::no_long_long> ();
+ r->value<S::reuse_style_mixin> () = h.value<H::reuse_style_mixin> ();
+ r->value<S::reuse_style_none> () = false;
+ r->value<S::generate_inline> () = h.value<H::generate_inline> ();
+ r->value<S::suppress_validation> () = h.value<H::suppress_validation> ()
+ || h.value<H::suppress_serializer_val> ();
+ r->value<S::generate_xml_schema> () = h.value<H::generate_xml_schema> ();
+ r->value<S::extern_xml_schema> () = h.value<H::extern_xml_schema> ();
+ r->value<S::suppress_reset> () = h.value<H::suppress_reset> ();
+ r->value<S::output_dir> () = h.value<H::output_dir> ();
+ r->value<S::skel_file_suffix> () = h.value<H::sskel_file_suffix> ();
+ r->value<S::skel_type_suffix> () = h.value<H::sskel_type_suffix> ();
+ r->value<S::impl_type_suffix> () = h.value<H::simpl_type_suffix> ();
+ r->value<S::namespace_map> () = h.value<H::namespace_map> ();
+ r->value<S::namespace_regex> () = h.value<H::namespace_regex> ();
+ r->value<S::namespace_regex_trace> () = h.value<H::namespace_regex_trace> ();
+ r->value<S::reserved_name> () = h.value<H::reserved_name> ();
+ r->value<S::include_with_brackets> () = h.value<H::include_with_brackets> ();
+ r->value<S::include_prefix> () = h.value<H::include_prefix> ();
+ r->value<S::include_regex> () = h.value<H::include_regex> ();
+ r->value<S::include_regex_trace> () = h.value<H::include_regex_trace> ();
+ r->value<S::guard_prefix> () = h.value<H::guard_prefix> ();
+
+ r->value<S::hxx_suffix> () = h.value<H::hxx_suffix> ();
+ r->value<S::ixx_suffix> () = h.value<H::ixx_suffix> ();
+ r->value<S::cxx_suffix> () = h.value<H::cxx_suffix> ();
+
+ Char const* k = "sskel";
+
+ r->value<S::hxx_regex> () =
+ find_value (h.value<H::hxx_regex> (), k);
+ r->value<S::ixx_regex> () =
+ find_value (h.value<H::ixx_regex> (), k);
+ r->value<S::cxx_regex> () =
+ find_value (h.value<H::cxx_regex> (), k);
+
+ r->value<S::hxx_prologue_file> () = find_value (
+ h.value<H::hxx_prologue_file> (), k);
+ r->value<S::ixx_prologue_file> () = find_value (
+ h.value<H::ixx_prologue_file> (), k);
+ r->value<S::cxx_prologue_file> () = find_value (
+ h.value<H::cxx_prologue_file> (), k);
+ r->value<S::prologue_file> () = find_value (
+ h.value<H::prologue_file> (), k);
+ r->value<S::hxx_epilogue_file> () = find_value (
+ h.value<H::hxx_epilogue_file> (), k);
+ r->value<S::ixx_epilogue_file> () = find_value (
+ h.value<H::ixx_epilogue_file> (), k);
+ r->value<S::cxx_epilogue_file> () = find_value (
+ h.value<H::cxx_epilogue_file> (), k);
+ r->value<S::epilogue_file> () = find_value (
+ h.value<H::epilogue_file> (), k);
+
+ copy_values (r->value<S::hxx_prologue> (), h.value<H::hxx_prologue> (), k);
+ copy_values (r->value<S::ixx_prologue> (), h.value<H::ixx_prologue> (), k);
+ copy_values (r->value<S::cxx_prologue> (), h.value<H::cxx_prologue> (), k);
+ copy_values (r->value<S::prologue> (), h.value<H::prologue> (), k);
+ copy_values (r->value<S::hxx_epilogue> (), h.value<H::hxx_epilogue> (), k);
+ copy_values (r->value<S::ixx_epilogue> (), h.value<H::ixx_epilogue> (), k);
+ copy_values (r->value<S::cxx_epilogue> (), h.value<H::cxx_epilogue> (), k);
+ copy_values (r->value<S::epilogue> (), h.value<H::epilogue> (), k);
+
+ r->value<S::show_sloc> () = h.value<H::show_sloc> ();
+ r->value<S::proprietary_license> () = h.value<H::proprietary_license> ();
+
+ return r.release ();
+ }
+
+ Void Hybrid::Generator::
+ calculate_size (CLI::Options const& ops,
+ XSDFrontend::SemanticGraph::Schema& schema,
+ XSDFrontend::SemanticGraph::Path const& file)
+ {
+ // Determine which types are fixed/variable-sized.
+ //
+ TreeSizeProcessor proc;
+ proc.process (ops, schema, file);
+ }
+
+ namespace
+ {
+ template <typename S>
+ Void
+ open (S& ifs, NarrowString const& path)
+ {
+ try
+ {
+ Path fs_path (path, boost::filesystem::native);
+ ifs.open (fs_path, std::ios_base::in | std::ios_base::binary);
+
+ if (!ifs.is_open ())
+ {
+ wcerr << path.c_str () << ": error: unable to open in read mode"
+ << endl;
+
+ throw Hybrid::Generator::Failed ();
+ }
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << "error: '" << path.c_str () << "' is not a valid "
+ << "filesystem path" << endl;
+
+ throw Hybrid::Generator::Failed ();
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ NarrowString const& path,
+ WideInputFileStream& default_is)
+ {
+ using std::ios_base;
+
+ if (path)
+ {
+ WideInputFileStream is;
+ open (is, path);
+ os << is.rdbuf ();
+ }
+ else if (default_is.is_open ())
+ {
+ os << default_is.rdbuf ();
+ default_is.seekg (0, ios_base::beg);
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ Cult::Containers::Vector<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def,
+ Char const* primary_key,
+ Char const* def_key)
+ {
+ typedef Cult::Containers::Vector<NarrowString> Values;
+
+ for (Values const* v = &primary; v != 0; v = (v == &def ? 0 : &def))
+ {
+ Boolean found (false);
+ Char const* key (v == &primary ? primary_key : def_key);
+
+ for (Values::ConstIterator i (v->begin ()), e (v->end ()); i != e; ++i)
+ {
+ if (key == 0)
+ os << i->c_str () << endl;
+ else
+ {
+ Size p (i->find ('='));
+
+ if (p == NarrowString::npos)
+ {
+ if (key[0] != '\0')
+ continue;
+ }
+ else
+ {
+ NarrowString k (*i, 0, p);
+
+ // Unless it is one of the valid keys, assume there is no key.
+ //
+ if (!(k.empty () || k == "*" || k == "pskel" ||
+ k == "pimpl" || k == "sskel" || k == "simpl"))
+ {
+ k.clear ();
+ p = NarrowString::npos;
+ }
+
+ if (k != key && k != "*")
+ continue;
+ }
+
+ NarrowString s (
+ *i, p == NarrowString::npos ? 0 : p + 1, NarrowString::npos);
+ os << s.c_str () << endl;
+ }
+
+ found = true;
+ }
+
+ if (found)
+ break;
+ }
+ }
+
+ Void
+ append (WideOutputFileStream& os,
+ Cult::Containers::Vector<NarrowString> const& primary,
+ Cult::Containers::Vector<NarrowString> const& def,
+ Char const* key)
+ {
+ append (os, primary, def, key, key);
+ }
+ }
+
+
+ UnsignedLong Hybrid::Generator::
+ generate_tree (Hybrid::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ const WarningSet& disabled_warnings,
+ TypeMap::Namespaces& parser_type_map,
+ TypeMap::Namespaces& serializer_type_map,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef Context::Regex Regex;
+
+ try
+ {
+ Boolean generate_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // We could be compiling several schemas at once in which case
+ // handling of the --generate-xml-schema option gets tricky: we
+ // will need to rely on the presence of the --extern-xml-schema
+ // to tell us which (fake) schema file corresponds to XML Schema.
+ //
+ if (generate_xml_schema)
+ {
+ if (NarrowString name = ops.value<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ generate_xml_schema = false;
+ }
+ }
+
+ // Evaluate the graph for possibility of generating something useful.
+ //
+ {
+ Validator validator;
+ if (!validator.validate (ops, schema, file_path, disabled_warnings))
+ throw Failed ();
+ }
+
+ // Process names.
+ //
+ {
+ TreeNameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ // Generate code.
+ //
+ Boolean inline_ (ops.value<CLI::generate_inline> () &&
+ !generate_xml_schema);
+
+ Boolean forward (ops.value<CLI::generate_forward> () &&
+ !generate_xml_schema);
+
+ Boolean source (!generate_xml_schema);
+
+ NarrowString name (file_path.leaf ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString ixx_suffix (ops.value <CLI::ixx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+ NarrowString fwd_suffix (ops.value <CLI::fwd_suffix> ());
+
+ NarrowString hxx_regex (find_value (ops.value <CLI::hxx_regex> (), ""));
+ NarrowString ixx_regex (find_value (ops.value <CLI::ixx_regex> (), ""));
+ NarrowString cxx_regex (find_value (ops.value <CLI::cxx_regex> (), ""));
+
+ Regex hxx_expr (
+ hxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#"
+ : hxx_regex);
+
+ Regex ixx_expr (
+ ixx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#"
+ : ixx_regex);
+
+ Regex cxx_expr (
+ cxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#"
+ : cxx_regex);
+
+ Regex fwd_expr (
+ ops.value <CLI::fwd_regex> ().empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + fwd_suffix + "#"
+ : ops.value <CLI::fwd_regex> ());
+
+ if (!hxx_expr.match (name))
+ {
+ wcerr << "error: header expression '" <<
+ hxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (inline_ && !ixx_expr.match (name))
+ {
+ wcerr << "error: inline expression '" <<
+ ixx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (source && !cxx_expr.match (name))
+ {
+ wcerr << "error: source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (forward && !fwd_expr.match (name))
+ {
+ wcerr << "error: forward expression '" <<
+ fwd_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ NarrowString hxx_name (hxx_expr.merge (name));
+ NarrowString ixx_name (inline_ ? ixx_expr.merge (name) : NarrowString ());
+ NarrowString cxx_name (source ? cxx_expr.merge (name) : NarrowString ());
+ NarrowString fwd_name (forward ? fwd_expr.merge (name) : NarrowString ());
+
+ Path hxx_path (hxx_name, boost::filesystem::native);
+ Path ixx_path (ixx_name, boost::filesystem::native);
+ Path cxx_path (cxx_name, boost::filesystem::native);
+ Path fwd_path (fwd_name, boost::filesystem::native);
+
+ if (NarrowString dir = ops.value<CLI::output_dir> ())
+ {
+ try
+ {
+ Path path (dir, boost::filesystem::native);
+
+ hxx_path = path / hxx_path;
+ ixx_path = path / ixx_path;
+ cxx_path = path / cxx_path;
+ fwd_path = path / fwd_path;
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ // Open the tree files.
+ //
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream ixx;
+ WideOutputFileStream cxx;
+ WideOutputFileStream fwd;
+
+ // FWD
+ //
+ if (forward)
+ {
+ fwd.open (fwd_path, ios_base::out);
+
+ if (!fwd.is_open ())
+ {
+ wcerr << fwd_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (fwd_path);
+ file_list.push_back (fwd_path.native_file_string ());
+ }
+
+ if (!hxx.is_open ())
+ {
+ wcerr << hxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_path);
+ file_list.push_back (hxx_path.native_file_string ());
+
+ if (inline_)
+ {
+ ixx.open (ixx_path, ios_base::out);
+
+ if (!ixx.is_open ())
+ {
+ wcerr << ixx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (ixx_path);
+ file_list.push_back (ixx_path.native_file_string ());
+ }
+
+ if (source)
+ {
+ cxx.open (cxx_path, ios_base::out);
+
+ if (!cxx.is_open ())
+ {
+ wcerr << cxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_path);
+ file_list.push_back (cxx_path.native_file_string ());
+ }
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ if (forward)
+ fwd << copyright;
+
+ hxx << copyright;
+
+ if (inline_)
+ ixx << copyright;
+
+ if (source)
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), ""));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), ""));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ if (!guard_prefix)
+ guard_prefix = file_path.branch_path ().native_directory_string ();
+
+ if (guard_prefix)
+ guard_prefix += '_';
+
+
+ // FWD
+ //
+ if (forward)
+ {
+ Context ctx (fwd, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> fwd_sloc (fwd);
+
+ String guard (guard_expr.merge (guard_prefix + fwd_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ fwd << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ fwd << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (fwd,
+ ops.value<CLI::fwd_prologue> (),
+ ops.value<CLI::prologue> (),
+ 0,
+ "");
+ append (fwd, ops.value<CLI::fwd_prologue_file> (), prologue);
+
+ fwd << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ fwd << "#include <xsde/cxx/version.hxx>" << endl
+ << endl
+ << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl
+ << "#error XSD/e runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ fwd << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> fwd_clip (fwd);
+
+ // Generate.
+ //
+ generate_tree_forward (ctx, false);
+
+ fwd << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ fwd << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (fwd, ops.value<CLI::fwd_epilogue_file> (), epilogue);
+ append (fwd,
+ ops.value<CLI::fwd_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ 0,
+ "");
+
+ fwd << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ fwd << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << fwd_path << ": "
+ << fwd_sloc.buffer ().count () << endl;
+
+ sloc += fwd_sloc.buffer ().count ();
+ }
+ }
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ hxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ ops.value<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), ""),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Version check.
+ //
+ hxx << "#include <xsde/cxx/version.hxx>" << endl
+ << endl
+ << "#if (XSDE_INT_VERSION != " << XSDE_INT_VERSION << "L)" << endl
+ << "#error XSD/e runtime version mismatch" << endl
+ << "#endif" << endl
+ << endl;
+
+ // Runtime/generated code compatibility checks.
+ //
+
+ hxx << "#include <xsde/cxx/config.hxx>" << endl
+ << endl;
+
+ if (ops.value<CLI::no_stl> ())
+ {
+ hxx << "#ifdef XSDE_STL" << endl
+ << "#error the XSD/e runtime uses STL while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-stl)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_STL" << endl
+ << "#error the generated code uses STL while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-stl)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::no_exceptions> ())
+ {
+ hxx << "#ifdef XSDE_EXCEPTIONS" << endl
+ << "#error the XSD/e runtime uses exceptions while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-exceptions)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_EXCEPTIONS" << endl
+ << "#error the generated code uses exceptions while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-exceptions)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ if (ops.value<CLI::no_long_long> ())
+ {
+ hxx << "#ifdef XSDE_LONGLONG" << endl
+ << "#error the XSD/e runtime uses long long while the " <<
+ "generated code does not (reconfigure the runtime or " <<
+ "remove --no-long-long)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+ else
+ {
+ hxx << "#ifndef XSDE_LONGLONG" << endl
+ << "#error the generated code uses long long while the " <<
+ "XSD/e runtime does not (reconfigure the runtime or " <<
+ "add --no-long-long)" << endl
+ << "#endif" << endl
+ << endl;
+ }
+
+ //
+ //
+
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ // Generate.
+ //
+ if (!generate_xml_schema)
+ {
+ if (forward)
+ hxx << "#include " << ctx.process_include_path (fwd_name)
+ << endl << endl;
+ else
+ generate_tree_forward (ctx, false);
+
+ generate_tree_header (ctx);
+ }
+ else
+ generate_tree_forward (ctx, true);
+
+ if (inline_)
+ {
+ hxx << "#ifndef XSDE_DONT_INCLUDE_INLINE" << endl
+ << "#include " << ctx.process_include_path (ixx_name) << endl
+ << "#endif // XSDE_DONT_INCLUDE_INLINE" << endl
+ << endl;
+ }
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), ""),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ hxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ hxx << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << hxx_path << ": "
+ << hxx_sloc.buffer ().count () << endl;
+
+ sloc += hxx_sloc.buffer ().count ();
+ }
+ }
+
+
+ // IXX
+ //
+ if (inline_)
+ {
+ Context ctx (ixx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> ixx_sloc (ixx);
+ // Guard
+ //
+ String guard (guard_expr.merge (guard_prefix + ixx_name));
+ guard = ctx.escape (guard); // make a c++ id
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ ixx << "#ifndef " << guard.c_str () << endl
+ << "#define " << guard.c_str () << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ ixx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (ixx,
+ ops.value<CLI::ixx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (ixx,
+ find_value (ops.value<CLI::ixx_prologue_file> (), ""),
+ prologue);
+
+ ixx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> ixx_clip (ixx);
+
+ // Generate.
+ //
+ generate_tree_inline (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ ixx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (ixx,
+ find_value (ops.value<CLI::ixx_epilogue_file> (), ""),
+ epilogue);
+ append (ixx,
+ ops.value<CLI::ixx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ ixx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ ixx << "#endif // " << guard.c_str () << endl;
+
+ if (show_sloc)
+ {
+ wcerr << ixx_path << ": "
+ << ixx_sloc.buffer ().count () << endl;
+
+ sloc += ixx_sloc.buffer ().count ();
+ }
+ }
+
+
+ // CXX
+ //
+ if (source)
+ {
+ Context ctx (cxx, schema, ops, &fwd_expr, &hxx_expr, &ixx_expr);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), ""),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ cxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ if (!inline_)
+ generate_tree_inline (ctx);
+
+ generate_tree_source (ctx);
+
+ cxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), ""),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "");
+
+ cxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_path << ": "
+ << cxx_sloc.buffer ().count () << endl;
+
+ sloc += cxx_sloc.buffer ().count ();
+ }
+ }
+
+ // Populate the type maps if we are generating parsing or
+ // serialization code.
+ //
+ if (ops.value<CLI::generate_parser> () ||
+ ops.value<CLI::generate_serializer> ())
+ {
+ generate_tree_type_map (
+ ops, schema, hxx_name, parser_type_map, serializer_type_map);
+ }
+
+ return sloc;
+ }
+ catch (NoNamespaceMapping const& e)
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: unable to map XML Schema namespace '" << e.ns ()
+ << "' to C++ namespace" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: use the --namespace-map or --namespace-regex option "
+ << "to provide custom mapping" << endl;
+
+ throw Failed ();
+ }
+ catch (InvalidNamespaceMapping const& e)
+ {
+ wcerr << "error: invalid XML to C++ namespace mapping specified: "
+ << "'" << e.mapping () << "': " << e.reason () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+
+ UnsignedLong Hybrid::Generator::
+ generate_parser (Hybrid::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ const WarningSet&,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ try
+ {
+ {
+ Boolean gen_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // We could be compiling several schemas at once in which case
+ // handling of the --generate-xml-schema option gets tricky: we
+ // will need to rely on the presence of the --extern-xml-schema
+ // to tell us which (fake) schema file corresponds to XML Schema.
+ //
+ if (gen_xml_schema)
+ {
+ if (NarrowString name = ops.value<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ gen_xml_schema = false;
+ }
+ }
+
+ if (gen_xml_schema)
+ return 0;
+ }
+
+ // Process names.
+ //
+ {
+ ParserNameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::pskel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::pimpl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ NarrowString hxx_obj_regex (
+ find_value (ops.value <CLI::hxx_regex> (), ""));
+
+ NarrowString hxx_skel_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "pskel"));
+
+ NarrowString hxx_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "pimpl"));
+ NarrowString cxx_regex (
+ find_value (ops.value <CLI::cxx_regex> (), "pimpl"));
+
+ // Here we need to make sure that hxx_obj_expr is the same
+ // as in generate().
+ //
+ Regex hxx_obj_expr (
+ hxx_obj_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#"
+ : hxx_obj_regex);
+
+ // Here we need to make sure that hxx_skel_expr is the same
+ // as in the C++/Parser generator.
+ //
+ Regex hxx_skel_expr (
+ hxx_skel_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : hxx_skel_regex);
+
+ Regex hxx_expr (
+ hxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#"
+ : hxx_regex);
+
+ Regex cxx_expr (
+ cxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#"
+ : cxx_regex);
+
+ if (!hxx_expr.match (name))
+ {
+ wcerr << "error: parser implementation header expression '" <<
+ hxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_expr.match (name))
+ {
+ wcerr << "error: parser implementation source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ NarrowString hxx_skel_name (hxx_skel_expr.merge (name));
+ NarrowString hxx_name (hxx_expr.merge (name));
+ NarrowString cxx_name (cxx_expr.merge (name));
+
+ Path hxx_path (hxx_name, boost::filesystem::native);
+ Path cxx_path (cxx_name, boost::filesystem::native);
+
+ if (NarrowString dir = ops.value<CLI::output_dir> ())
+ {
+ try
+ {
+ Path path (dir, boost::filesystem::native);
+
+ hxx_path = path / hxx_path;
+ cxx_path = path / cxx_path;
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream cxx (cxx_path, ios_base::out);
+
+ if (!hxx.is_open ())
+ {
+ wcerr << hxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_path);
+ file_list.push_back (hxx_path.native_file_string ());
+
+ if (!cxx.is_open ())
+ {
+ wcerr << cxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_path);
+ file_list.push_back (cxx_path.native_file_string ());
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ hxx << copyright;
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), "pimpl"));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), "pimpl"));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ if (!guard_prefix)
+ guard_prefix = file_path.branch_path ().native_directory_string ();
+
+ if (guard_prefix)
+ guard_prefix += '_';
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, 0, &hxx_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ hxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ ops.value<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "pimpl");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), "pimpl"),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ hxx << "#include " << ctx.process_include_path (hxx_skel_name)
+ << endl << endl;
+
+ generate_parser_header (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_parser_aggregate_header (ctx);
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), "pimpl"),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "pimpl");
+
+ hxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ hxx << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << hxx_path << ": "
+ << hxx_sloc.buffer ().count () << endl;
+
+ sloc += hxx_sloc.buffer ().count ();
+ }
+ }
+
+ // CXX
+ //
+ {
+ Context ctx (cxx, schema, ops, 0, &hxx_obj_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "pimpl");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), "pimpl"),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ generate_parser_source (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_parser_aggregate_source (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), "pimpl"),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "pimpl");
+
+ cxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_path << ": "
+ << cxx_sloc.buffer ().count () << endl;
+
+ sloc += cxx_sloc.buffer ().count ();
+ }
+ }
+
+ return sloc;
+ }
+ catch (NoNamespaceMapping const& e)
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: unable to map XML Schema namespace '" << e.ns ()
+ << "' to C++ namespace" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: use the --namespace-map or --namespace-regex option "
+ << "to provide custom mapping" << endl;
+
+ throw Failed ();
+ }
+ catch (InvalidNamespaceMapping const& e)
+ {
+ wcerr << "error: invalid XML to C++ namespace mapping specified: "
+ << "'" << e.mapping () << "': " << e.reason () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+
+ UnsignedLong Hybrid::Generator::
+ generate_serializer (Hybrid::CLI::Options const& ops,
+ Schema& schema,
+ Path const& file_path,
+ const WarningSet&,
+ FileList& file_list,
+ AutoUnlinks& unlinks)
+ {
+ using std::ios_base;
+ namespace Indentation = BackendElements::Indentation;
+
+ typedef BackendElements::Regex::Expression<Char> Regex;
+
+ try
+ {
+ {
+ Boolean gen_xml_schema (ops.value<CLI::generate_xml_schema> ());
+
+ // We could be compiling several schemas at once in which case
+ // handling of the --generate-xml-schema option gets tricky: we
+ // will need to rely on the presence of the --extern-xml-schema
+ // to tell us which (fake) schema file corresponds to XML Schema.
+ //
+ if (gen_xml_schema)
+ {
+ if (NarrowString name = ops.value<CLI::extern_xml_schema> ())
+ {
+ if (file_path.native_file_string () != name)
+ gen_xml_schema = false;
+ }
+ }
+
+ if (gen_xml_schema)
+ return 0;
+ }
+
+ // Process names.
+ //
+ {
+ SerializerNameProcessor proc;
+ proc.process (ops, schema, file_path);
+ }
+
+ NarrowString name (file_path.leaf ());
+ NarrowString skel_suffix (ops.value <CLI::sskel_file_suffix> ());
+ NarrowString impl_suffix (ops.value <CLI::simpl_file_suffix> ());
+
+ NarrowString hxx_suffix (ops.value <CLI::hxx_suffix> ());
+ NarrowString cxx_suffix (ops.value <CLI::cxx_suffix> ());
+
+ NarrowString hxx_skel_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "sskel"));
+ NarrowString hxx_regex (
+ find_value (ops.value <CLI::hxx_regex> (), "simpl"));
+ NarrowString cxx_regex (
+ find_value (ops.value <CLI::cxx_regex> (), "simpl"));
+
+ // Here we need to make sure that hxx_skel_expr is the same
+ // as in the C++/Serializer generator.
+ //
+ Regex hxx_skel_expr (
+ hxx_skel_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + skel_suffix + hxx_suffix + "#"
+ : hxx_skel_regex);
+
+ Regex hxx_expr (
+ hxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + hxx_suffix + "#"
+ : hxx_regex);
+
+ Regex cxx_expr (
+ cxx_regex.empty ()
+ ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + impl_suffix + cxx_suffix + "#"
+ : cxx_regex);
+
+ if (!hxx_expr.match (name))
+ {
+ wcerr << "error: serializer implementation header expression '" <<
+ hxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ if (!cxx_expr.match (name))
+ {
+ wcerr << "error: serializer implementation source expression '" <<
+ cxx_expr.pattern () << "' does not match '" <<
+ name.c_str () << "'" << endl;
+ throw Failed ();
+ }
+
+ NarrowString hxx_skel_name (hxx_skel_expr.merge (name));
+ NarrowString hxx_name (hxx_expr.merge (name));
+ NarrowString cxx_name (cxx_expr.merge (name));
+
+ Path hxx_path (hxx_name, boost::filesystem::native);
+ Path cxx_path (cxx_name, boost::filesystem::native);
+
+ if (NarrowString dir = ops.value<CLI::output_dir> ())
+ {
+ try
+ {
+ Path path (dir, boost::filesystem::native);
+
+ hxx_path = path / hxx_path;
+ cxx_path = path / cxx_path;
+ }
+ catch (InvalidPath const&)
+ {
+ wcerr << dir.c_str () << ": error: invalid path" << endl;
+ throw Failed ();
+ }
+ }
+
+ WideOutputFileStream hxx (hxx_path, ios_base::out);
+ WideOutputFileStream cxx (cxx_path, ios_base::out);
+
+ if (!hxx.is_open ())
+ {
+ wcerr << hxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (hxx_path);
+ file_list.push_back (hxx_path.native_file_string ());
+
+ if (!cxx.is_open ())
+ {
+ wcerr << cxx_path << ": error: unable to open in write mode" << endl;
+ throw Failed ();
+ }
+
+ unlinks.add (cxx_path);
+ file_list.push_back (cxx_path.native_file_string ());
+
+ // Print copyright and license.
+ //
+ Char const* copyright (
+ ops.value<CLI::proprietary_license> ()
+ ? copyright_proprietary
+ : copyright_gpl);
+
+ hxx << copyright;
+ cxx << copyright;
+
+ // Prologue.
+ //
+ WideInputFileStream prologue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::prologue_file> (), "simpl"));
+
+ if (name)
+ open (prologue, name);
+ }
+
+ // Epilogue.
+ //
+ WideInputFileStream epilogue;
+ {
+ NarrowString name (
+ find_value (ops.value<CLI::epilogue_file> (), "simpl"));
+
+ if (name)
+ open (epilogue, name);
+ }
+
+ // SLOC counter.
+ //
+ UnsignedLong sloc (0);
+ Boolean show_sloc (ops.value<CLI::show_sloc> ());
+
+ //
+ //
+ Regex guard_expr ("/([a-z])([A-Z])/$1_$2/"); // Split words.
+
+ NarrowString guard_prefix (ops.value<CLI::guard_prefix> ());
+
+ if (!guard_prefix)
+ guard_prefix = file_path.branch_path ().native_directory_string ();
+
+ if (guard_prefix)
+ guard_prefix += '_';
+
+
+ // HXX
+ //
+ {
+ Context ctx (hxx, schema, ops, 0, &hxx_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx);
+
+ String guard (guard_expr.merge (guard_prefix + hxx_name));
+ guard = ctx.escape (guard); // Make it a C++ id.
+ std::transform (guard.begin (), guard.end(), guard.begin (), upcase);
+
+ hxx << "#ifndef " << guard << endl
+ << "#define " << guard << endl
+ << endl;
+
+ // Copy prologue.
+ //
+ hxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ ops.value<CLI::hxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "simpl");
+ append (hxx,
+ find_value (ops.value<CLI::hxx_prologue_file> (), "simpl"),
+ prologue);
+
+ hxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ hxx << "#include <xsde/cxx/pre.hxx>" << endl
+ << endl;
+
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> hxx_clip (hxx);
+
+ hxx << "#include " << ctx.process_include_path (hxx_skel_name)
+ << endl << endl;
+
+ generate_serializer_header (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_serializer_aggregate_header (ctx);
+
+ hxx << "#include <xsde/cxx/post.hxx>" << endl
+ << endl;
+ }
+
+ // Copy epilogue.
+ //
+ hxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (hxx,
+ find_value (ops.value<CLI::hxx_epilogue_file> (), "simpl"),
+ epilogue);
+ append (hxx,
+ ops.value<CLI::hxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "simpl");
+
+ hxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ hxx << "#endif // " << guard << endl;
+
+ if (show_sloc)
+ {
+ wcerr << hxx_path << ": "
+ << hxx_sloc.buffer ().count () << endl;
+
+ sloc += hxx_sloc.buffer ().count ();
+ }
+ }
+
+ // CXX
+ //
+ {
+ Context ctx (cxx, schema, ops, 0, &hxx_expr, 0);
+
+ Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (cxx);
+
+ // Copy prologue.
+ //
+ cxx << "// Begin prologue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ ops.value<CLI::cxx_prologue> (),
+ ops.value<CLI::prologue> (),
+ "simpl");
+ append (cxx,
+ find_value (ops.value<CLI::cxx_prologue_file> (), "simpl"),
+ prologue);
+
+ cxx << "//" << endl
+ << "// End prologue." << endl
+ << endl;
+
+ {
+ // Set auto-indentation.
+ //
+ Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (cxx);
+
+ cxx << "#include " << ctx.process_include_path (hxx_name) << endl
+ << endl;
+
+ generate_serializer_source (ctx);
+
+ if (ops.value<CLI::generate_aggregate> ())
+ generate_serializer_aggregate_source (ctx);
+ }
+
+ // Copy epilogue.
+ //
+ cxx << "// Begin epilogue." << endl
+ << "//" << endl;
+
+ append (cxx,
+ find_value (ops.value<CLI::cxx_epilogue_file> (), "simpl"),
+ epilogue);
+ append (cxx,
+ ops.value<CLI::cxx_epilogue> (),
+ ops.value<CLI::epilogue> (),
+ "simpl");
+
+ cxx << "//" << endl
+ << "// End epilogue." << endl
+ << endl;
+
+ if (show_sloc)
+ {
+ wcerr << cxx_path << ": "
+ << cxx_sloc.buffer ().count () << endl;
+
+ sloc += cxx_sloc.buffer ().count ();
+ }
+ }
+
+ return sloc;
+ }
+ catch (NoNamespaceMapping const& e)
+ {
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": error: unable to map XML Schema namespace '" << e.ns ()
+ << "' to C++ namespace" << endl;
+
+ wcerr << e.file () << ":" << e.line () << ":" << e.column ()
+ << ": info: use the --namespace-map or --namespace-regex option "
+ << "to provide custom mapping" << endl;
+
+ throw Failed ();
+ }
+ catch (InvalidNamespaceMapping const& e)
+ {
+ wcerr << "error: invalid XML to C++ namespace mapping specified: "
+ << "'" << e.mapping () << "': " << e.reason () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<Char> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression ().c_str () << "': " <<
+ e.description ().c_str () << endl;
+
+ throw Failed ();
+ }
+ catch (BackendElements::Regex::Format<WideChar> const& e)
+ {
+ wcerr << "error: invalid regex: '" <<
+ e.expression () << "': " << e.description () << endl;
+
+ throw Failed ();
+ }
+ }
+}