diff options
Diffstat (limited to 'xsd/xsd/cxx/tree/generator.cxx')
-rw-r--r-- | xsd/xsd/cxx/tree/generator.cxx | 1842 |
1 files changed, 1842 insertions, 0 deletions
diff --git a/xsd/xsd/cxx/tree/generator.cxx b/xsd/xsd/cxx/tree/generator.cxx new file mode 100644 index 0000000..fe5286a --- /dev/null +++ b/xsd/xsd/cxx/tree/generator.cxx @@ -0,0 +1,1842 @@ +// file : xsd/cxx/tree/generator.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2010 Code Synthesis Tools CC +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include <cxx/tree/generator.hxx> + +#include <cxx/tree/elements.hxx> + +#include <cxx/tree/counter.hxx> +#include <cxx/tree/validator.hxx> +#include <cxx/tree/name-processor.hxx> +#include <cxx/tree/polymorphism-processor.hxx> + +#include <cxx/tree/tree-forward.hxx> +#include <cxx/tree/tree-header.hxx> +#include <cxx/tree/tree-inline.hxx> +#include <cxx/tree/tree-source.hxx> + +#include <cxx/tree/parser-header.hxx> +#include <cxx/tree/parser-source.hxx> + +#include <cxx/tree/stream-header.hxx> +#include <cxx/tree/stream-source.hxx> + +#include <cxx/tree/serialization-header.hxx> +#include <cxx/tree/serialization-source.hxx> + +#include <cxx/tree/stream-insertion-header.hxx> +#include <cxx/tree/stream-insertion-source.hxx> +#include <cxx/tree/stream-extraction-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 "../../../libxsd/xsd/cxx/version.hxx" + +using std::endl; +using std::wcerr; + +using namespace XSDFrontend::SemanticGraph; + +// +// +typedef +boost::filesystem::wifstream +WideInputFileStream; + +typedef +boost::filesystem::wofstream +WideOutputFileStream; + +namespace CXX +{ + namespace + { + Char const copyright_gpl[] = + "// Copyright (C) 2005-2010 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD, an XML Schema to\n" + "// C++ data binding compiler.\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" + "// In addition, as a special exception, Code Synthesis Tools CC gives\n" + "// permission to link this program with the Xerces-C++ library (or with\n" + "// modified versions of Xerces-C++ that use the same license as Xerces-C++),\n" + "// and distribute linked combinations including the two. You must obey\n" + "// the GNU General Public License version 2 in all respects for all of\n" + "// the code used other than Xerces-C++. If you modify this copy of the\n" + "// program, you may extend this exception to your version of the program,\n" + "// but you are not obligated to do so. If you do not wish to do so, delete\n" + "// this exception statement from your version.\n" + "//\n" + "// Furthermore, Code Synthesis Tools CC makes a special exception for\n" + "// the Free/Libre and Open Source Software (FLOSS) which is described\n" + "// in the accompanying FLOSSE file.\n" + "//\n\n"; + + Char const copyright_proprietary[] = + "// Copyright (C) 2005-2010 Code Synthesis Tools CC\n" + "//\n" + "// This program was generated by CodeSynthesis XSD, an XML Schema\n" + "// to C++ data binding compiler, in the Proprietary License mode.\n" + "// You should have received a proprietary license from Code Synthesis\n" + "// Tools CC prior to generating this code. See the license text for\n" + "// conditions.\n" + "//\n\n"; + } + + namespace Tree + { + namespace CLI + { + extern Key char_type = "char-type"; + extern Key char_encoding = "char-encoding"; + extern Key output_dir = "output-dir"; + extern Key generate_polymorphic = "generate-polymorphic"; + extern Key polymorphic_type = "polymorphic-type"; + extern Key polymorphic_type_all = "polymorphic-type-all"; + extern Key generate_serialization = "generate-serialization"; + extern Key generate_inline = "generate-inline"; + extern Key generate_ostream = "generate-ostream"; + extern Key generate_doxygen = "generate-doxygen"; + extern Key generate_comparison = "generate-comparison"; + extern Key generate_default_ctor = "generate-default-ctor"; + extern Key generate_from_base_ctor = "generate-from-base-ctor"; + extern Key generate_detach = "generate-detach"; + extern Key generate_wildcard = "generate-wildcard"; + extern Key generate_insertion = "generate-insertion"; + extern Key generate_extraction = "generate-extraction"; + 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_parsing = "suppress-parsing"; + extern Key generate_element_type = "generate-element-type"; + extern Key generate_element_map = "generate-element-map"; + extern Key generate_intellisense = "generate-intellisense"; + extern Key omit_default_attributes = "omit-default-attributes"; + 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 type_naming = "type-naming"; + extern Key function_naming = "function-naming"; + extern Key type_regex = "type-regex"; + extern Key accessor_regex = "accessor-regex"; + extern Key one_accessor_regex = "one-accessor-regex"; + extern Key opt_accessor_regex = "opt-accessor-regex"; + extern Key seq_accessor_regex = "seq-accessor-regex"; + extern Key modifier_regex = "modifier-regex"; + extern Key one_modifier_regex = "one-modifier-regex"; + extern Key opt_modifier_regex = "opt-modifier-regex"; + extern Key seq_modifier_regex = "seq-modifier-regex"; + extern Key parser_regex = "parser-regex"; + extern Key serializer_regex = "serializer-regex"; + extern Key enumerator_regex = "enumerator-regex"; + extern Key element_type_regex = "element-type-regex"; + extern Key name_regex_trace = "name-regex-trace"; + 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 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 custom_type = "custom-type"; + extern Key custom_type_regex = "custom-type-regex"; + 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 parts = "parts"; + extern Key parts_suffix = "parts-suffix"; + extern Key export_symbol = "export-symbol"; + extern Key export_xml_schema = "export-xml-schema"; + extern Key export_maps = "export-maps"; + extern Key import_maps = "import-maps"; + extern Key show_anonymous = "show-anonymous"; + extern Key show_sloc = "show-sloc"; + extern Key proprietary_license = "proprietary-license"; + extern Key disable_multi_import = "disable-multi-import"; + } + } + + Void Tree::Generator:: + usage () + { + std::wostream& e (wcerr); + ::CLI::Indent::Clip< ::CLI::OptionsUsage, WideChar> clip (e); + + e << "--char-type <type>" << endl + << " Use <type> as the base character type. Valid\n" + << " values are 'char' (default) and 'wchar_t'." + << endl; + + e << "--char-encoding <enc>" << endl + << " Specify the character encoding that should be used\n" + << " in the object model. Valid values for the 'char'\n" + << " character type are 'utf8' (default), 'iso8859-1',\n" + << " 'lcp', and 'custom'. For the 'wchar_t' character\n" + << " type the only valid value is 'auto'." + << endl; + + e << "--output-dir <dir>" << endl + << " Write generated files to <dir> instead of current\n" + << " directory." + << endl; + + e << "--generate-polymorphic" << endl + << " Generate polymorphism-aware code. Specify this\n" + << " option if you use substitution groups or xsi:type." + << endl; + + e << "--polymorphic-type <type>" << endl + << " Indicate that <type> is a root of a polymorphic\n" + << " type hierarchy." + << endl; + + e << "--polymorphic-type-all" << endl + << " Indicate that all types should be treated as\n" + << " polymorphic." + << endl; + + e << "--generate-serialization" << endl + << " Generate serialization functions. They convert an\n" + << " in-memory representation back to XML." + << endl; + + e << "--generate-inline" << endl + << " Generate certain functions inline." + << endl; + + e << "--generate-ostream" << endl + << " Generate ostream insertion operators." + << endl; + + e << "--generate-doxygen" << endl + << " Generate documentation comments in the Doxygen\n" + << " format." + << endl; + + e << "--generate-comparison" << endl + << " Generate comparison operators." + << endl; + + e << "--generate-default-ctor" << endl + << " Generate default constructors even for types that\n" + << " have required members." + << endl; + + e << "--generate-from-base-ctor" << endl + << " Generate from-base constructors." + << endl; + + e << "--generate-detach" << endl + << " Generate detach functions for required members." + << endl; + + e << "--generate-wildcard" << endl + << " Generate accessors/modifiers as well as parsing\n" + << " and serialization code for XML Schema wildcards." + << endl; + + e << "--generate-insertion <os>" << endl + << " Generate data representation stream insertion\n" + << " operators for the <os> output stream type." + << endl; + + e << "--generate-extraction <is>" << endl + << " Generate data representation stream extraction\n" + << " constructors for the <is> input stream type." + << endl; + + e << "--generate-forward" << endl + << " Generate forward declaration file." + << endl; + + e << "--generate-xml-schema" << endl + << " Generate a C++ header file 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-parsing" << endl + << " Suppress the generation of parsing functions." + << endl; + + e << "--generate-element-type" << endl + << " Generate types instead of parsing/serialization\n" + << " functions for root elements." + << endl; + + e << "--generate-element-map" << endl + << " Generate a root element map that allows uniform\n" + << " parsing/serialization of multiple root elements.\n" + << endl; + + e << "--generate-intellisense" << endl + << " Generate workarounds for IntelliSense bugs in\n" + << " Visual Studio 2005 (8.0)." + << endl; + + e << "--omit-default-attributes" << endl + << " Omit attributes with default and fixed values\n" + << " from serialized XML documents." + << 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 << "--type-naming <style>" << endl + << " Specify the type naming convention that should be\n" + << " used in the generated code. Valid styles are 'knr'\n" + << " (default), 'ucc', and 'java'." + << endl; + + e << "--function-naming <style>" << endl + << " Specify the function naming convention that should\n" + << " be used in the generated code. Valid styles are\n" + << " 'knr' (default), 'lcc', and 'java'." + << endl; + + e << "--type-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema type names to C++\n" + << " type names." + << endl; + + e << "--accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements and\n" + << " attributes to C++ accessor function names." + << endl; + + e << "--one-accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality one to C++\n" + << " accessor function names." + << endl; + + e << "--opt-accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality optional to C++\n" + << " accessor function names." + << endl; + + e << "--seq-accessor-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality sequence to C++\n" + << " accessor function names." + << endl; + + e << "--modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements and\n" + << " attributes to C++ modifier function names." + << endl; + + e << "--one-modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality one to C++\n" + << " modifier function names." + << endl; + + e << "--opt-modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality optional to C++\n" + << " modifier function names." + << endl; + + e << "--seq-modifier-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema names of elements\n" + << " and attributes with cardinality sequence to C++\n" + << " modifier function names." + << endl; + + e << "--parser-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema element names to\n" + << " C++ parsing function names." + << endl; + + e << "--serializer-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema element names to\n" + << " C++ serialization function names." + << endl; + + e << "--enumerator-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema enumeration values\n" + << " to C++ enumerator names." + << endl; + + e << "--element-type-regex <expr>" << endl + << " Add <expr> to the list of regular expressions\n" + << " used to translate XML Schema element names to\n" + << " C++ element type names." + << endl; + + e << "--name-regex-trace" << endl + << " Trace the process of applying regular expressions\n" + << " specified with the name transformation options." + << 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; + + 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 << "--custom-type <map>" << endl + << " Use a custom C++ type instead of the generated\n" + << " class. The <map> argument is in the form\n" + << " name[=type[/base]], where <name> is a type name as\n" + << " defined in XML Schema, <type> is a C++ type name\n" + << " that should be used instead, and optional <base>\n" + << " is a C++ name that should be given to the C++\n" + << " class generated from the XML Schema definition\n" + << " which is normally used as a base for the custom\n" + << " type." + << endl; + + e << "--custom-type-regex <regex>" << endl + << " Use custom C++ types instead of the generated\n" + << " classes. The <regex> argument is in the form\n" + << " /name/[type/[base/]], where <name> is a regex\n" + << " pattern that will be matched against type names\n" + << " as defined in XML Schema, <type> is a C++ type\n" + << " name that should be used instead, and optional\n" + << " <base> is a C++ name that should be given to\n" + << " the C++ class generated from the XML Schema\n" + << " definition." + << endl; + + e << "--hxx-suffix <suffix>" << endl + << " Use <suffix> instead of the default '.hxx' to\n" + << " construct the name of the header file." + << endl; + + e << "--ixx-suffix <suffix>" << endl + << " Use <suffix> instead of the default '.ixx' to\n" + << " construct the name of the inline file." + << endl; + + e << "--cxx-suffix <suffix>" << endl + << " Use <suffix> instead of the default '.cxx' to\n" + << " construct the name of the source file." + << 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; + + e << "--hxx-regex <regex>" << endl + << " Use <regex> to construct the name of the header\n" + << " file." + << endl; + + e << "--ixx-regex <regex>" << endl + << " Use <regex> to construct the name of the inline\n" + << " file." + << endl; + + e << "--cxx-regex <regex>" << endl + << " Use <regex> to construct the name of the source\n" + << " file." + << 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 file." + << endl; + + e << "--ixx-prologue <text>" << endl + << " Insert <text> at the beginning of the inline file." + << endl; + + e << "--cxx-prologue <text>" << endl + << " Insert <text> at the beginning of the source file." + << 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 file." + << endl; + + e << "--ixx-epilogue <text>" << endl + << " Insert <text> at the end of the inline file." + << endl; + + e << "--cxx-epilogue <text>" << endl + << " Insert <text> at the end of the source file." + << 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 file." + << endl; + + e << "--ixx-prologue-file <file>" << endl + << " Insert the content of the <file> at the beginning\n" + << " of the inline file." + << endl; + + e << "--cxx-prologue-file <file>" << endl + << " Insert the content of the <file> at the beginning\n" + << " of the source file." + << 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 file." + << endl; + + e << "--ixx-epilogue-file <file>" << endl + << " Insert the content of the <file> at the end of\n" + << " the inline file." + << endl; + + e << "--cxx-epilogue-file <file>" << endl + << " Insert the content of the <file> at the end of\n" + << " the source file." + << 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 << "--parts <num>" << endl + << " Split generated source code into <num> parts." + << endl; + + e << "--parts-suffix <suffix>" << endl + << " Use <suffix> instead of the default '-' to\n" + << " separate the file name from the part number." + << endl; + + e << "--custom-literals <file>" << endl + << " Load custom XML string to C++ literal mappings\n" + << " from <file>." + << endl; + + e << "--export-symbol <symbol>" << endl + << " Export symbol for Win32 DLL export/import control." + << endl; + + e << "--export-xml-schema" << endl + << " Export/import types in the XML Schema namespace." + << endl; + + e << "--export-maps" << endl + << " Export polymorphism support maps from Win32 DLL." + << endl; + + e << "--import-maps" << endl + << " Import polymorphism support maps from Win32 DLL." + << endl; + + 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; + } + + Tree::CLI::OptionsSpec Tree::Generator:: + options_spec () + { + CLI::OptionsSpec spec; + + spec.option<CLI::char_type> ().default_value ("char"); + + 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"); + + spec.option<CLI::type_naming> ().default_value ("knr"); + spec.option<CLI::function_naming> ().default_value ("knr"); + + spec.option<CLI::parts> ().default_value (1); + spec.option<CLI::parts_suffix> ().default_value ("-"); + + return spec; + } + + + namespace + { + Void + open (WideInputFileStream& ifs, NarrowString const& path) + { + try + { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path fs_path (path, boost::filesystem::native); +#else + Path fs_path (path.c_str()); +#endif + 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 Tree::Generator::Failed (); + } + } + catch (InvalidPath const&) + { + wcerr << "error: '" << path.c_str () << "' is not a valid " + << "filesystem path" << endl; + + throw Tree::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) + { + Cult::Containers::Vector<NarrowString> const& v ( + primary.empty () ? def : primary); + + for (Containers::Vector<NarrowString>::ConstIterator + i (v.begin ()), e (v.end ()); i != e; ++i) + { + os << i->c_str () << endl; + } + } + } + + + UnsignedLong Tree::Generator:: + generate (Tree::CLI::Options const& ops, + Schema& schema, + Path const& file_path, + Boolean fpt, + StringLiteralMap const& string_literal_map, + const WarningSet& disabled_warnings, + FileList& file_list, + AutoUnlinks& unlinks) + { + using std::ios_base; + namespace Indentation = BackendElements::Indentation; + + typedef BackendElements::Regex::Expression<Char> Regex; + + using Cult::Containers::Vector; + + typedef Vector<Path> Paths; + typedef Vector<Evptr<WideOutputFileStream> > WideOutputFileStreams; + + try + { + // Do option validation. + // + if (ops.value<CLI::parts> () < 1) + { + wcerr << "error: invalid value for option --parts: " << + ops.value<CLI::parts> () << endl; + throw Failed (); + } + + // Get counts. + // + Counts counts; + { + Counter counter; + counts = counter.count (ops, schema, file_path); + + /* + wcerr << "global type count: " << counts.global_types << endl; + wcerr << "global element count: " << counts.global_elements << endl; + wcerr << "generated global element count: " << + counts.generated_global_elements << endl; + + wcerr << "total complexity: " << counts.complexity_total << endl; + wcerr << "complexity vector size: " << counts.complexity.size () + << endl; + */ + } + + // Evaluate the graph for possibility of generating something useful. + // + { + Validator validator; + if (!validator.validate ( + ops, schema, file_path, disabled_warnings, counts)) + throw Failed (); + } + + // Process names. + // + { + NameProcessor proc; + if (!proc.process (ops, schema, file_path, string_literal_map)) + throw Failed (); + } + + // Process polymorphic types. + // + if (ops.value<CLI::generate_polymorphic> () && + !ops.value<CLI::polymorphic_type_all> ()) + { + PolymorphismProcessor proc; + if (!proc.process (ops, schema, file_path, disabled_warnings)) + throw Failed (); + } + + // Parts. + // + UnsignedLong parts (ops.value<CLI::parts> ()); + UnsignedLong units ( + counts.global_types + counts.generated_global_elements); + + UnsignedLong units_per_part (units / parts); + + if (parts != 1 && units_per_part < 1) + { + wcerr << "error: too many parts specified: " << parts << endl; + throw Failed (); + } + + UnsignedLong complexity_per_part (counts.complexity_total / parts); + + + NarrowString parts_suffix (ops.value<CLI::parts_suffix> ()); + + // + // + 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 !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + if (file_path.native_file_string () != name) +#else + if (file_path.string () != name) +#endif + generate_xml_schema = false; + } + } + + 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); + + // Generate code. + // +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + NarrowString name (file_path.leaf ()); +#else + NarrowString name (file_path.filename ().string()); +#endif + + 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> ()); + + Regex hxx_expr (ops.value <CLI::hxx_regex> ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + hxx_suffix + "#" + : ops.value <CLI::hxx_regex> ()); + + Regex ixx_expr (ops.value <CLI::ixx_regex> ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + ixx_suffix + "#" + : ops.value <CLI::ixx_regex> ()); + + Regex cxx_expr (ops.value <CLI::cxx_regex> ().empty () + ? "#^(.+?)(\\.[^./\\\\]+)?$#$1" + cxx_suffix + "#" + : ops.value <CLI::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 && parts == 1 && !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 fwd_name (forward ? fwd_expr.merge (name) : NarrowString ()); + +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path hxx_path (hxx_name, boost::filesystem::native); + Path ixx_path (ixx_name, boost::filesystem::native); + Path fwd_path (fwd_name, boost::filesystem::native); +#else + Path hxx_path (hxx_name.c_str()); + Path ixx_path (ixx_name.c_str()); + Path fwd_path (fwd_name.c_str()); +#endif + Paths cxx_paths; + + if (source) + { + if (parts > 1) + { + for (UnsignedLong i (0); i < parts; ++i) + { + std::ostringstream os; + os << i; + + Regex expr ( + "#^(.+?)(\\.[^./\\\\]+)?$#$1" + parts_suffix + os.str () + "$2#"); + + NarrowString part_name (expr.merge (name)); + + if (!cxx_expr.match (part_name)) + { + wcerr << "error: source expression '" << + cxx_expr.pattern () << "' does not match '" << + part_name.c_str () << "'" << endl; + throw Failed (); + } + + cxx_paths.push_back ( +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path (cxx_expr.merge (part_name), boost::filesystem::native)); +#else + Path (cxx_expr.merge (part_name).c_str())); +#endif + } + } + else + cxx_paths.push_back ( +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + Path (cxx_expr.merge (name), boost::filesystem::native)); +#else + Path (cxx_expr.merge (name).c_str())); +#endif + } + + Path out_dir; + + if (NarrowString dir = ops.value<CLI::output_dir> ()) + { + try + { +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + out_dir = Path (dir, boost::filesystem::native); +#else + out_dir = Path (dir.c_str()); +#endif + } + catch (InvalidPath const&) + { + wcerr << dir.c_str () << ": error: invalid path" << endl; + throw Failed (); + } + } + + if (fpt && !generate_xml_schema) + { + // In the file-per-type mode the schema files are always local + // unless the user added the directory so that we propagate this + // to the output files. + // + Path fpt_dir (file_path.branch_path ()); + + if (!fpt_dir.empty ()) + out_dir /= fpt_dir; + } + + if (!out_dir.empty ()) + { + hxx_path = out_dir / hxx_path; + ixx_path = out_dir / ixx_path; + fwd_path = out_dir / fwd_path; + + for (Paths::Iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + *i = out_dir / *i; + } + + // + // + WideOutputFileStream hxx (hxx_path, ios_base::out); + WideOutputFileStream ixx; + WideOutputFileStream fwd; + WideOutputFileStreams cxx; + + + // 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); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (fwd_path.native_file_string ()); +#else + file_list.push_back (fwd_path.string ()); +#endif + } + + + // HXX + // + if (!hxx.is_open ()) + { + wcerr << hxx_path << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (hxx_path); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (hxx_path.native_file_string ()); +#else + file_list.push_back (hxx_path.string ()); +#endif + + + // IXX + // + 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); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (ixx_path.native_file_string ()); +#else + file_list.push_back (ixx_path.string ()); +#endif + } + + + // CXX + // + if (source) + { + for (Paths::Iterator i (cxx_paths.begin ()); + i != cxx_paths.end (); ++i) + { + Evptr<WideOutputFileStream> s ( + new WideOutputFileStream (*i, ios_base::out)); + + if (!s->is_open ()) + { + wcerr << *i << ": error: unable to open in write mode" << endl; + throw Failed (); + } + + unlinks.add (*i); +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + file_list.push_back (i->native_file_string ()); +#else + file_list.push_back (i->string ()); +#endif + cxx.push_back (s); + } + } + + + // Print copyright and license. + // + Char const* copyright ( + ops.value<CLI::proprietary_license> () + ? copyright_proprietary + : copyright_gpl); + + if (forward) + fwd << copyright; + + hxx << copyright; + + if (ops.value<CLI::generate_doxygen> ()) + { + // Use native path format. + // + hxx << "/**" << endl + << " * @file" << endl + << " * @brief Generated from " << name.c_str () << "." << endl + << " */" << endl + << endl; + + } + + if (inline_) + ixx << copyright; + + if (source) + { + for (WideOutputFileStreams::Iterator i (cxx.begin ()); + i != cxx.end (); ++i) + **i << copyright; + } + + + // Prologue. + // + WideInputFileStream prologue; + { + NarrowString name (ops.value<CLI::prologue_file> ()); + + if (name) + open (prologue, name); + } + + // Epilogue. + // + WideInputFileStream epilogue; + { + NarrowString name (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) +#if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2 + guard_prefix = file_path.branch_path ().native_directory_string (); +#else + guard_prefix = file_path.branch_path ().string (); +#endif + + if (guard_prefix) + guard_prefix += '_'; + + // FWD + // + if (forward) + { + Context ctx (fwd, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + Indentation::Clip<Indentation::SLOC, WideChar> fwd_sloc (fwd); + + // Guard + // + String guard (guard_expr.merge (guard_prefix + fwd_name)); + guard = ctx.escape (guard); // make 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> ()); + append (fwd, ops.value<CLI::fwd_prologue_file> (), prologue); + + fwd << "//" << endl + << "// End prologue." << endl + << endl; + + // Version check. + // + fwd << "#include <xsd/cxx/version.hxx>" << endl + << endl + << "#if (XSD_INT_VERSION != " << XSD_INT_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + + << endl; + { + fwd << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + if (ctx.char_type == L"char") + { + fwd << "#ifndef XSD_USE_CHAR" << endl + << "#define XSD_USE_CHAR" << endl + << "#endif" << endl + << endl; + + fwd << "#ifndef XSD_CXX_TREE_USE_CHAR" << endl + << "#define XSD_CXX_TREE_USE_CHAR" << endl + << "#endif" << endl + << endl; + } + else if (ctx.char_type == L"wchar_t") + { + fwd << "#ifndef XSD_USE_WCHAR" << endl + << "#define XSD_USE_WCHAR" << endl + << "#endif" << endl + << endl; + + fwd << "#ifndef XSD_CXX_TREE_USE_WCHAR" << endl + << "#define XSD_CXX_TREE_USE_WCHAR" << endl + << "#endif" << endl + << endl; + } + + // Set auto-indentation. + // + Indentation::Clip<Indentation::CXX, WideChar> fwd_clip (fwd); + + + // Generate. + // + generate_forward (ctx); + + fwd << "#include <xsd/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> ()); + + 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, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + Indentation::Clip<Indentation::SLOC, WideChar> hxx_sloc (hxx); + + // Guard + // + String guard (guard_expr.merge (guard_prefix + hxx_name)); + guard = ctx.escape (guard); // make 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, ops.value<CLI::hxx_prologue_file> (), prologue); + + hxx << "//" << endl + << "// End prologue." << endl + << endl; + + // Version check. + // + hxx << "#include <xsd/cxx/config.hxx>" << endl + << endl + << "#if (XSD_INT_VERSION != " << XSD_INT_VERSION << "L)" << endl + << "#error XSD runtime version mismatch" << endl + << "#endif" << endl + << endl; + + { + hxx << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + // Generate character selection defines. + // + if (!forward) + { + if (ctx.char_type == L"char") + { + hxx << "#ifndef XSD_USE_CHAR" << endl + << "#define XSD_USE_CHAR" << endl + << "#endif" << endl + << endl; + + hxx << "#ifndef XSD_CXX_TREE_USE_CHAR" << endl + << "#define XSD_CXX_TREE_USE_CHAR" << endl + << "#endif" << endl + << endl; + } + else if (ctx.char_type == L"wchar_t") + { + hxx << "#ifndef XSD_USE_WCHAR" << endl + << "#define XSD_USE_WCHAR" << endl + << "#endif" << endl + << endl; + + hxx << "#ifndef XSD_CXX_TREE_USE_WCHAR" << endl + << "#define XSD_CXX_TREE_USE_WCHAR" << endl + << "#endif" << 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_forward (ctx); + } + + generate_tree_header (ctx); + + if (!generate_xml_schema) + { + + if (ops.value<CLI::generate_ostream> ()) + generate_stream_header (ctx); + + if (!ops.value<CLI::generate_element_type> () && + !ops.value<CLI::suppress_parsing> ()) + generate_parser_header (ctx); + + if (ops.value<CLI::generate_serialization> ()) + generate_serialization_header (ctx); + + if (!ops.value<CLI::generate_insertion> ().empty ()) + generate_stream_insertion_header (ctx); + } + + if (inline_) + { + hxx << "#ifndef XSD_DONT_INCLUDE_INLINE" << endl + << "#include " << ctx.process_include_path (ixx_name) << endl + << "#endif // XSD_DONT_INCLUDE_INLINE" << endl + << endl; + } + + hxx << "#include <xsd/cxx/post.hxx>" << endl + << endl; + } + + // Copy epilogue. + // + hxx << "// Begin epilogue." << endl + << "//" << endl; + + append (hxx, 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, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &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, 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, 1, 0); + } + + // Copy epilogue. + // + ixx << "// Begin epilogue." << endl + << "//" << endl; + + append (ixx, 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) + { + UnsignedLong first_unit (0); // First unit in the current part. + + for (UnsignedLong part (0); part < parts; ++part) + { + // Figure out the range of units for this part. + // + UnsignedLong last_unit (first_unit); + + if (units != 0) + { + UnsignedLong complexity (counts.complexity[last_unit]); + + while (complexity < complexity_per_part) + { + // Make sure there will be at least one unit for each part left. + // + if ((last_unit + 1) >= units || + (units - (last_unit + 1) - 1) < (parts - part - 1)) + break; + + // Check if the increase in complexity should be kept in this + // part or moved to the next. + // + UnsignedLong new_complexity ( + complexity + counts.complexity[last_unit + 1]); + + if (new_complexity > complexity_per_part) + { + if ((new_complexity - complexity_per_part) > + (counts.complexity[last_unit + 1] / 2)) + break; + } + + last_unit++; + complexity = new_complexity; + } + + if (part + 1 == parts) + { + // Last part. + // + last_unit = units - 1; + } + } + + // + // + UnsignedLong first (first_unit); + UnsignedLong last (last_unit); + + first_unit = last_unit + 1; + + //wcerr << "[" << first << ", " << last << "]: " << complexity + // << endl; + + WideOutputFileStream& os (*cxx[part]); + + Context ctx (os, + schema, + file_path, + ops, + counts, + generate_xml_schema, + &string_literal_map, + &fwd_expr, + &hxx_expr, + &ixx_expr); + + Indentation::Clip<Indentation::SLOC, WideChar> cxx_sloc (os); + + // Copy prologue. + // + os << "// Begin prologue." << endl + << "//" << endl; + + append (os, + ops.value<CLI::cxx_prologue> (), + ops.value<CLI::prologue> ()); + append (os, ops.value<CLI::cxx_prologue_file> (), prologue); + + os << "//" << endl + << "// End prologue." << endl + << endl; + + { + os << "#include <xsd/cxx/pre.hxx>" << endl + << endl; + + // Set auto-indentation. + // + Indentation::Clip<Indentation::CXX, WideChar> cxx_clip (os); + + + // Generate. + // + os << "#include " << ctx.process_include_path (hxx_name) << endl + << endl; + + if (!inline_) + generate_tree_inline (ctx, first, last); + + generate_tree_source (ctx, first, last); + + if (ops.value<CLI::generate_ostream> ()) + generate_stream_source (ctx, first, last); + + if (!ops.value<CLI::generate_element_type> () && + !ops.value<CLI::suppress_parsing> ()) + generate_parser_source (ctx, first, last); + + if (ops.value<CLI::generate_serialization> ()) + generate_serialization_source (ctx, first, last); + + if (!ops.value<CLI::generate_extraction> ().empty ()) + generate_stream_extraction_source (ctx); + + if (!ops.value<CLI::generate_insertion> ().empty ()) + generate_stream_insertion_source (ctx); + + os << "#include <xsd/cxx/post.hxx>" << endl + << endl; + } + + // Copy epilogue. + // + os << "// Begin epilogue." << endl + << "//" << endl; + + append (os, ops.value<CLI::cxx_epilogue_file> (), epilogue); + append (os, + ops.value<CLI::cxx_epilogue> (), + ops.value<CLI::epilogue> ()); + + os << "//" << endl + << "// End epilogue." << endl + << endl; + + if (show_sloc) + { + wcerr << cxx_paths[part] << ": " + << cxx_sloc.buffer ().count () << endl; + + sloc += cxx_sloc.buffer ().count (); + } + } + } + + return sloc; + } + catch (UnrepresentableCharacter const& e) + { + wcerr << "error: character at position " << e.position () << " " + << "in string '" << e.string () << "' is unrepresentable in " + << "the target encoding" << endl; + + wcerr << "info: use the --custom-literals option to provide custom " + << "string literals mapping" << endl; + + throw Failed (); + } + 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 (InvalidCustomTypeMapping const& e) + { + wcerr << "error: invalid custom type 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 (); + } + } +} |